('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 pin_chat: {\n id: 'pin_chat',\n defaultMessage: 'Pin',\n description: 'Menu item [Pin] for pinning chat to the top.'\n },\n unpin_chat: {\n id: 'unpin_chat',\n defaultMessage: 'Unpin',\n description: 'Menu item [Unpin] for un-pinning the chat.'\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 params.topicTitle || 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 params.topicTitle || 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 params.topicTitle || 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 params.topicTitle || 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 'topic_pin': {\n id: 'topic_pin',\n title: formatMessage(messages.pin_chat),\n handler: (params, errorHandler) => {\n const me = this.props.tinode.getMeTopic();\n if (!me) {\n console.warn(\"'me' topic not found\");\n return;\n }\n return me.pinTopic(params.topicName, true).catch(err => {\n if (errorHandler) {\n errorHandler(err.message, 'err');\n }\n });\n }\n },\n 'topic_unpin': {\n id: 'topic_unpin',\n title: formatMessage(messages.unpin_chat),\n handler: (params, errorHandler) => {\n const me = this.props.tinode.getMeTopic();\n if (!me) {\n console.warn(\"'me' topic not found\");\n return;\n }\n return me.pinTopic(params.topicName, 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\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 { truncateString } from '../lib/strformat.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: truncateString(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
{truncateString(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","// 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';\nimport { truncateString } from '../lib/strformat.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.containerRef = React.createRef();\n this.localRef = React.createRef();\n this.remoteRef = React.createRef();\n\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 this.bounds = {};\n\n this.dragStart = (event) => {\n if (!event.target.classList.contains('draggable')) {\n // Prevent dragging when clicking on buttons or other non-draggable elements.\n return;\n }\n if (window.matchMedia('(width<=640px)')) {\n // No dragging on small screens.\n return;\n }\n if (this.props.minimized && this.containerRef) {\n event.stopPropagation();\n this.containerRef.current.setPointerCapture(event.pointerId);\n this.containerRef.current.style.cursor = 'grabbing';\n this.bounds.left = this.containerRef.current.offsetLeft;\n this.bounds.top = this.containerRef.current.offsetTop;\n this.bounds.width = this.containerRef.current.offsetWidth;\n this.bounds.height = this.containerRef.current.offsetHeight;\n\n const parent = this.containerRef.current.offsetParent;\n this.bounds.maxX = parent.offsetWidth;\n this.bounds.maxY = parent.offsetHeight;\n }\n };\n this.drag = (event) => {\n event.stopPropagation();\n const el = this.containerRef.current;\n if (this.props.minimized && this.containerRef && el.hasPointerCapture(event.pointerId)) {\n // Calculate new position. Restrict to the visible area of the parent element.\n this.bounds.left = Math.min(Math.max(this.bounds.left + event.movementX, 0),\n this.bounds.maxX - this.bounds.width);\n this.bounds.top = Math.min(Math.max(this.bounds.top + event.movementY, 0),\n this.bounds.maxY - this.bounds.height);\n\n el.style.left = `${this.bounds.left}px`;\n el.style.top = `${this.bounds.top}px`;\n }\n };\n this.dragEnd = (event) => {\n event.stopPropagation();\n if (this.props.minimized && this.containerRef) {\n this.containerRef.current.releasePointerCapture(event.pointerId);\n this.containerRef.current.style.cursor = 'grab';\n }\n };\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 if (this.containerRef) {\n this.containerRef.current.addEventListener('pointerdown', this.dragStart);\n this.containerRef.current.addEventListener('pointermove', this.drag);\n this.containerRef.current.addEventListener('pointerup', this.dragEnd);\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 if (this.containerRef) {\n this.containerRef.current.removeEventListener('pointerdown', this.dragStart);\n this.containerRef.current.removeEventListener('pointermove', this.drag);\n this.containerRef.current.removeEventListener('pointerup', this.dragEnd);\n }\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 = truncateString(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 const minimizedClass = this.props.minimized ? 'minimized' : null;\n const fullScreen = this.props.minimized ? 'fullscreen' : 'fullscreen_exit';\n\n return (\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 {fullScreen} \n \n
\n \n call_end \n \n \n {videoIcon} \n \n \n {audioIcon} \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 (Drafty.isFormResponseType(att.mime)) {\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 // Enter pressed: either send, or enter a new line.\n if (e.key === 'Enter') {\n if (this.props.sendOnEnter == 'plain') {\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 } else {\n if (e.ctrlKey || e.metaKey) {\n e.preventDefault();\n e.stopPropagation();\n\n this.handleSend(e);\n }\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 DRAFTY_FR_MIME_TYPE_LEGACY, KEYPRESS_DELAY, MESSAGES_PAGE, MAX_EXTERN_ATTACHMENT_SIZE, MAX_IMAGE_DIM,\n MAX_INBAND_ATTACHMENT_SIZE, 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: {timestamp}',\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 subscriber_count: {\n id: 'subscriber_count',\n defaultMessage: '{count, plural, ' +\n 'one {{count, number} subscriber} ' +\n 'two {{count, number} subscribers} ' +\n 'three {{count, number} subscribers} ' +\n 'few {{count, number} subscribers} ' +\n 'many {{count, number} subscribers} ' +\n 'other {{count, number} subscribers}}',\n description: 'Count of channel subscribers'\n },\n member_count: {\n id: 'member_count',\n defaultMessage: '{count, plural, ' +\n 'one {{count, number} member} ' +\n 'two {{count, number} members} ' +\n 'three {{count, number} members} ' +\n 'few {{count, number} members} ' +\n 'many {{count, number} members} ' +\n 'other {{count, number} members}}',\n description: 'Count of group topic members'\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.handleCallPanelToggle = this.handleCallPanelToggle.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 minimizedCallPanel: false,\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 minimizedCallPanel: false,\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 === DRAFTY_FR_MIME_TYPE_LEGACY ? '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 handleCallPanelToggle() {\n this.setState({minimizedCallPanel: !this.state.minimizedCallPanel});\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 // P2P call is an overlay, not a separate component because it cannot be\n // re-mounted between full screen/minimized.\n const overlay = this.state.rtcPanel ? (\n \n ) : null;\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 {\n const topic = this.props.tinode.getTopic(this.state.topic);\n const isChannel = topic.isChannelType() || topic.chan;\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.subscriber_count, {count: topic.subcnt});\n } else {\n const cont = this.props.tinode.getMeTopic().getContact(this.state.topic);\n if (cont) {\n if (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 {timestamp: shortDateFormat(cont.seen.when, this.props.intl.locale)});\n // TODO: also handle user agent in c.seen.ua\n }\n } else if (Tinode.isGroupTopicName(cont.topic)) {\n lastSeen = formatMessage(messages.member_count, {count: topic.subcnt});\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 const darkModeClass = this.props.colorSchema == 'dark' ? 'dark' : '';\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}{overlay}
\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\n const me = props.tinode.getMeTopic();\n props.chatList.forEach(c => {\n const blocked = c.acs && !c.acs.isJoiner();\n c.pinned = me.pinnedTopicRank(c.topic);\n\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 const pin = b.pinned - a.pinned;\n return pin != 0 ? pin : (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\nexport default class AccGeneralView extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.state = {\n colorSchema: props.colorSchema || 'auto',\n textSize: (props.textSize * 10) || '100',\n sendOnEnter: props.sendOnEnter || 'plain',\n };\n\n this.isMac = ((navigator.userAgentData && navigator.userAgentData.platform)\n || navigator.platform).toLowerCase().startsWith('mac');\n this.handleColorSchemaSelected = this.handleColorSchemaSelected.bind(this);\n this.handleTextSizeChanged = this.handleTextSizeChanged.bind(this);\n this.handleSendOnEnterSelected = this.handleSendOnEnterSelected.bind(this);\n }\n\n handleColorSchemaSelected(e) {\n this.setState({colorSchema: e.currentTarget.value});\n this.props.onChangeColorSchema(e.currentTarget.value);\n }\n\n handleTextSizeChanged(e) {\n // In %%.\n this.setState({textSize: e.currentTarget.value});\n // Convert %% to pt, 100% = 10pt.\n this.props.onTextSizeChanged((e.currentTarget.value / 10) | 0);\n }\n\n handleSendOnEnterSelected(e) {\n this.setState({sendOnEnter: e.currentTarget.value});\n this.props.onSendOnEnterChanged(e.currentTarget.value);\n }\n\n render() {\n return (\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 AccNotificationsView 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 }\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","// 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';\nimport { truncateString } from '../lib/strformat.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 = truncateString(this.state.fullName.trim(), MAX_TITLE_LENGTH);\n const comment = truncateString(this.state.private.trim(), MAX_TITLE_LENGTH);\n const description = truncateString(this.state.description.trim(), 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 AccGeneralView from './acc-general-view.jsx';\nimport AccNotificationsView from './acc-notifications-view.jsx';\nconst AccSecurityView = React.lazy(_ => import('./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';\nconst WallpapersView = React.lazy(_ => import('./wallpapers.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 acc_general: {\n id: 'sidepanel_title_acc_general',\n description: 'Sidepanel title for AccGeneralView.',\n defaultMessage: 'General'\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 wallpapers: {\n id: 'wallpapers',\n description: 'Link or title for working with wallpapers.',\n defaultMessage: 'Wallpapers'\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 === 'acc_general' ?\n :\n\n view === 'notif' ?\n :\n\n view === 'security' ?\n }>\n \n :\n\n view === 'support' ?\n :\n\n view === 'wallpapers' ?\n }>\n \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\nconst InfoView = React.lazy(_ => import('./info-view.jsx'));\nimport MessagesView from './messages-view.jsx';\nimport SidepanelView from './sidepanel-view.jsx';\n\nimport { API_KEY, APP_NAME, DEFAULT_COLOR_SCHEME, DEFAULT_P2P_ACCESS_MODE, DEFAULT_TEXT_SIZE, FORWARDED_PREVIEW_LENGTH,\n LOGGING_ENABLED, 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 { defaultWallpaper, 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.handleColorSchemeChange = this.handleColorSchemeChange.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.handleChangeColorSchema = this.handleChangeColorSchema.bind(this);\n this.handleChangeTextSize = this.handleChangeTextSize.bind(this);\n this.handleSendOnEnter = this.handleSendOnEnter.bind(this);\n this.handleSelectWallpapers = this.handleSelectWallpapers.bind(this);\n this.handleWallpaperSelected = this.handleWallpaperSelected.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 if (!settings.wallpaper) {\n const wallpaper = defaultWallpaper();\n settings.wallpaper = wallpaper.name || '';\n settings.wallpaperSize = wallpaper.size || 0;\n settings.wallpaperBlur = 0;\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 // Manually selected color scheme. Default: 'system default' ('auto').\n colorSchema: settings.colorSchema || DEFAULT_COLOR_SCHEME,\n systemColorSchema: window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light',\n // Wallpaper settings.\n wallpaper: settings.wallpaper,\n wallpaperSize: settings.wallpaperSize,\n wallpaperBlur: 0,\n // Text size in points. Default size: 10pt\n textSize: settings.textSize || DEFAULT_TEXT_SIZE,\n // Default: 'plain' (just Enter)\n sendOnEnter: settings.sendOnEnter || 'plain',\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 window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', this.handleColorSchemeChange);\n\n // Window/tab visible or invisible for pausing timers.\n document.addEventListener('visibilitychange', this.handleVisibilityEvent);\n\n document.documentElement.style.colorScheme = this.state.colorSchema == 'auto' ? 'light dark' : this.state.colorSchema;\n document.documentElement.style.setProperty('--message-text-size', `${this.state.textSize}pt`);\n\n this.applyWallpaperSettings(this.state.wallpaper, this.state.wallpaperSize, this.state.wallpaperBlur,\n this.state.colorSchema == 'auto' ? this.state.systemColorSchema : this.state.colorSchema);\n\n console.log(\"Wallpaper settings:\", this.state.wallpaper, this.state.wallpaperSize, this.state.wallpaperBlur);\n console.log(\"Wallpaper type:\", this.state.wallpaperSize == 0 ? 'wpimg' : 'wppatt');\n console.log(\"System color scheme:\", this.state.systemColorSchema);\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 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 window.matchMedia('(prefers-color-scheme: dark)').removeEventListener('change', this.handleColorSchemeChange);\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 (['acc_general','archive','blocked','contacts','cred','crop','edit','general',\n 'newtpk','notif','register','reset','security','settings','support','wallpapers',\n ''].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 return;\n }\n\n if (desc.public) {\n this.setState({\n sidePanelTitle: desc.public.fn,\n sidePanelAvatar: makeImageUrl(desc.public.photo)\n });\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\n if (desc.acs) {\n this.setState({\n incognitoMode: !desc.acs.isPresencer()\n });\n }\n\n if (TinodeWeb.checkIfPinsUpdated(desc, this.state.chatList)) {\n this.resetContactList();\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 const me = this.tinode.getMeTopic();\n me.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 // Pinned topics take precedence.\n const pins = me.pinnedTopicRank(b.topic) - me.pinnedTopicRank(a.topic);\n // Then sort by last touched time.\n return pins != 0 ? pins : (b.touched || past).getTime() - (a.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 static checkIfPinsUpdated(me, chatList) {\n for (let i = 0; i < chatList.length; i++) {\n const c = chatList[i];\n if (!!me.pinnedTopicRank(c.topic) != c.pinned) {\n return true;\n }\n }\n return false;\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 // Manual change of color scheme: 'dark', 'light', 'auto'.\n handleChangeColorSchema(schema) {\n console.log(\"User color scheme change:\", schema);\n this.setState({colorSchema: schema});\n LocalStorageUtil.updateObject('settings', {colorSchema: schema});\n document.documentElement.style.colorScheme = schema == 'auto' ? 'light dark' : schema;\n this.applyColorSchema(schema, this.state.systemColorSchema, this.state.wallpaperSize);\n }\n\n // System color scheme has changed.\n handleColorSchemeChange(event) {\n const systemSchema = event.matches ? 'dark' : 'light';\n console.log(\"System color scheme change:\", systemSchema);\n this.setState({systemColorSchema: systemSchema});\n this.applyColorSchema(this.state.colorSchema, systemSchema, this.state.wallpaperSize);\n }\n\n applyColorSchema(schema, systemSchema, size) {\n const effectiveSchema = schema == 'auto' ? systemSchema : schema;\n console.log(\"applyColorSchema:\", effectiveSchema);\n document.documentElement.style.setProperty('--wallpaper-invert', effectiveSchema == 'dark' && size ? '1' : '0');\n document.documentElement.style.setProperty('--wallpaper-brightness', effectiveSchema == 'dark' && !size ? '0.5' : '1');\n }\n\n handleSelectWallpapers() {\n this.handleError();\n HashNavigation.navigateTo(HashNavigation.setUrlSidePanel(window.location.hash, 'wallpapers'));\n }\n\n applyWallpaperSettings(wallpaper, size, blur, effectiveSchema) {\n document.documentElement.style.setProperty('--wallpaper-url', `url('${wallpaper}')`);\n document.documentElement.style.setProperty('--wallpaper-repeat', size ? 'repeat' : 'no-repeat');\n document.documentElement.style.setProperty('--wallpaper-blur', size ? '0px' : `${blur}px`);\n document.documentElement.style.setProperty('--wallpaper-size', size ? `${size}px` : 'cover');\n document.documentElement.style.setProperty('--wallpaper-position', size ? 'unset' : 'center');\n document.documentElement.style.setProperty('--wallpaper-invert', effectiveSchema == 'dark' && size ? '1' : '0');\n document.documentElement.style.setProperty('--wallpaper-brightness', effectiveSchema == 'dark' && !size ? '0.5' : '1');\n }\n\n handleWallpaperSelected(wallpaper, size, blur) {\n this.handleError();\n LocalStorageUtil.updateObject('settings', {wallpaper: wallpaper, wallpaperSize: size, wallpaperBlur: blur});\n this.setState({wallpaper: wallpaper, wallpaperSize: size, wallpaperBlur: blur});\n this.applyWallpaperSettings(wallpaper, size, blur,\n this.state.colorSchema == 'auto' ? this.state.systemColorSchema : this.state.colorSchema);\n }\n\n handleChangeTextSize(size) {\n this.setState({textSize: size | 0});\n LocalStorageUtil.updateObject('settings', {textSize: size});\n document.documentElement.style.setProperty('--message-text-size', `${size}pt`);\n }\n\n handleSendOnEnter(option) {\n this.setState({sendOnEnter: option});\n LocalStorageUtil.updateObject('settings', {sendOnEnter: option});\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','acc_general'].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 ('wallpapers' == parsed.path[0]) {\n path = 'acc_general';\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 // Reset color scheme.\n document.documentElement.style.colorScheme = DEFAULT_COLOR_SCHEME == 'auto' ? 'light dark' : DEFAULT_COLOR_SCHEME;\n document.documentElement.style.setProperty('--message-text-size', `${DEFAULT_TEXT_SIZE}pt`);\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 const me = this.tinode.getMeTopic();\n let muted = false, blocked = false, self_blocked = false, subscribed = false, deleter = false,\n archived = false, pinned = false, webrtc = false, writer = false, p2p = false, self = false;\n if (topic) {\n subscribed = topic.isSubscribed();\n archived = topic.isArchived();\n pinned = me.pinnedTopicRank(topicName) > 0;\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 pinned ? 'topic_unpin' : 'topic_pin',\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 const colorSchema = this.state.colorSchema !== 'auto' ? this.state.colorSchema : this.state.systemColorSchema;\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 \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 'it': _ => import('./i18n.min/it.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","imgTop","imgBottom","coLeft","coRight","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","ContactBadges","badges","forEach","b","color","icon","push","key","name","messages","defineMessages","badge_verified","badge_staff","badge_danger","BadgeList","formatMessage","intl","trustedBadges","comment","short","injectIntl","LoadSpinner","large","clear","centered","show","CheckBox","checked","iconName","classList","Array","isArray","attrs","join","ErrorPanel","hide","componentDidUpdate","prevProps","level","onClearError","warn","info","text","action","href","whiteSpace","actionText","MenuCancel","InPlaceEdit","selfRef","active","initialValue","valid","handeTextChange","handleKeyDown","handleStartEditing","handleEditingFinished","handlePasswordFinished","prevState","newValue","validator","Promise","resolve","keyCode","readOnly","_","focus","event","trim","required","checkValidity","onFinished","spanText","spanClass","placeholder","multiline","iconLeft","iconRight","element","attr","VisiblePassword","rows","maxLength","onKeyDown","onBlur","autoComplete","autoFocus","undefined","spellCheck","module","exports","TagManager","tags","alias","Tinode","tagByPrefix","TAG_ALIAS","tagInput","activated","handleTagInput","handleAddTag","handleRemoveTag","handleCancel","getDerivedStateFromProps","nextProps","arrayEqual","last","substring","tag","maxTagCount","tinode","getServerParam","MAX_TAG_COUNT","slice","onTagsChanged","index","splice","setUniqueTag","minTagLength","MIN_TAG_LENGTH","maxTagLength","MAX_TAG_LENGTH","user","invalid","title","add_tags_prompt","ChipInput","chips","avatarDisabled","prompt","tabIndex","onEnter","onFocusLost","onChipRemoved","filterFunc","updateFavicon","count","oldIcon","getElementById","head","getElementsByTagName","newIcon","createElement","rel","removeChild","appendChild","theCard","fn","imageUrl","imageMimeType","note","card","DEL_CHAR","mimeType","matches","exec","photo","data","indexOf","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","MESSAGE_STATUS_SENT","MESSAGE_STATUS_RECEIVED","MESSAGE_STATUS_READ","cancelablePromise","promise","hasCanceled","Error","reject","result","isCanceled","error","cancel","defaultWallpaper","wp","require","WALLPAPER_DEFAULTS","path","size","ContactAction","handleClick","stopPropagation","onAction","values","badge_you","badge_owner","ContactList","showCheckmark","topicSelected","contactNodes","contactsCount","showSelfTopic","selected","Contact","showMode","onSelected","onTopicSelected","showContextMenu","item","contacts","c","topic","filter","filterOn","private","toLowerCase","public","isChannel","isChannelTopicName","isGroup","isGroupTopicName","myUserId","acs","isOwner","forwarded","previewIsResponse","deliveryStatus","latestMessage","msg","_status","msgStatus","from","content","substr","MESSAGE_PREVIEW_LENGTH","Drafty","makeImageUrl","unread","showUnread","now","online","connected","pinned","showOnline","isVerified","trusted","verified","isStaff","staff","isDangerous","danger","deleted","_deleted","noScroll","dangerouslySetInnerHTML","__html","emptyListMessage","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","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","Chip","noAvatar","LetterTile","deriveStateFromProps","input","focused","handleTextInput","removeChipAt","handleChipCancel","handleFocusGained","handleFocusLost","sortedChips","sortChips","staticMembers","chipIndex","indexChips","keep","normal","includes","concat","idx","removed","at","onFocus","UnreadBadge","self_topic_name","self_topic_comment","handleContextClick","topicName","topicTitle","self","isSelfTopicName","truncateString","icon_badges","getMode","isMuted","isJoiner","isValid","format","previewFormatter","marker","titleClass","bgColor","small","SUPPORTED_IMAGE_FORMATS","MIME_EXTENSIONS","fitImageSize","maxWidth","maxHeight","forceSquare","dstWidth","dstHeight","srcWidth","srcHeight","xoffset","yoffset","fileNameForMime","fname","ext","lastIndexOf","imageScaled","fileOrBlob","maxSize","Image","crossOrigin","onerror","onload","async","URL","revokeObjectURL","dim","canvas","ctx","imageSmoothingEnabled","drawImage","toBlob","createObjectURL","objURL","fileToBase64","file","reader","FileReader","bits","split","readAsDataURL","blobToBase64","filePasted","onImageSuccess","onAttachmentSuccess","items","clipboardData","originalEvent","kind","getAsFile","base64ReEncode","str","btoa","atob","base64ToBlob","bin","buf","ArrayBuffer","arr","Uint8Array","charCodeAt","Blob","intArrayToBase64","String","fromCharCode","b64","inputRef","visible","handleVisibility","currentTarget","setTimeout","contains","activeElement","SELF_AVATAR_URI","iconColor","idToColorClass","letter","charAt","authorizeURL","HashNavigation","parseUrlHash","hash","parts","arg","eq","decodeURIComponent","navigateTo","location","composeUrlHash","args","hasOwnProperty","encodeURIComponent","addUrlParam","parsed","removeUrlParam","setUrlSidePanel","sidepanel","setUrlInfoPanel","infopanel","setUrlTopic","CallMessage","isCallDropped","callState","successClass","callIcon","incoming","CallStatus","icon2","InlineVideo","videoRef","LazyImage","isvideo","Object","assign","padding","whenDone","UploadingImage","FileProgress","progress","onCancelUpload","drafty_form","drafty_attachment","drafty_image","drafty_video","drafty_unknown","fullFormatter","stack","quoteFormatter","call","el","tagName","attrValue","loading","handleImageData","onFormButtonClick","inner","child","CLICKABLE_URL_SCHEMES","onQuoteClick","handleVideoData","IMAGE_THUMBNAIL_DIM","viewportWidth","REM_SIZE","BROKEN_IMAGE_SIZE","minWidth","minHeight","isProcessing","onImagePreview","NO_DIMENSIONS_VIDEO","onVideoPreview","isFormResponseType","inlineImageAttr","inlineVideoAttr","VIDEO_THUMBNAIL_WIDTH","shortenFileName","quoteImageOrVideo","isVideo","premime","preref","fetch","evt","ok","status","statusText","scaled","replyFormatter","loadedPromise","message","alias_invalid","alias_already_taken","TopicDescEdit","getTopic","getAccessMode","isSelf","isMe","isMeTopicName","owner","fullName","description","newAvatar","newAvatarMime","aliasError","previousOnTags","aliasCheckTimer","aliasCheckPromise","tnNewTags","handleFullNameUpdate","handleImageUpdated","handleAvatarCropped","handleAvatarCropCancel","uploadAvatar","handlePrivateUpdate","handleAliasUpdate","handleDescriptionUpdate","handleTagsUpdated","validateAlias","cancelValidator","onTagsUpdated","MAX_TITLE_LENGTH","onUpdateTopicDesc","desc","MAX_TOPIC_DESCRIPTION_LENGTH","readyToUpload","image","MAX_AVATAR_BYTES","getLargeFileHelper","upload","du","AVATAR_SIZE","MAX_EXTERN_ATTACHMENT_SIZE","clearTagPrefix","isValidTagValue","fnd","getFndTopic","validationPromise","checkTagUniqueness","clearTimeout","onUpdateTags","editable","find","t","AvatarUpload","uid","onImageUpdated","full_name_placeholder","group_name_placeholder","private_placeholder","title_tag_manager","TopicCommonView","previousTagsUpdated","getType","onUpdateTagsRequest","ReactIntl","LocalStorageUtil","setObject","localStorage","setItem","JSON","stringify","getObject","getItem","parse","updateObject","oldVal","removeItem","shortDateFormat","locale","navigator","userLanguage","language","Date","getFullYear","getMonth","getDate","toLocaleTimeString","hour12","hour","minute","toLocaleDateString","month","day","year","relativeDateFormat","diff","floor","getTime","getTimezoneOffset","abs","Intl","RelativeTimeFormat","numeric","DateTimeFormat","seconds","fixedMin","hours","sec","bytesToHumanSize","bytes","sizes","bucket","log2","pow","round","toFixed","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","DEFAULT_P2P_ACCESS_MODE","NO_ACCESS_MODE","MEDIA_BREAKPOINT","MESSAGES_PAGE","MAX_INBAND_ATTACHMENT_SIZE","MAX_IMAGE_DIM","IMAGE_PREVIEW_DIM","VIDEO_PREVIEW_DIM","MAX_ONLINE_IN_TOPIC","MAX_PEER_TITLE_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","QRCODE_SIZE","WAKE_UP_TIMEOUT","WAKE_UP_TICK","MIN_SWIPE_DISTANCE","TOAST_DURATION","DEFAULT_COLOR_SCHEME","DEFAULT_TEXT_SIZE","DRAFTY_FR_MIME_TYPE_LEGACY","handleFileReceived","files","randId","random","accept","htmlFor","uploading","QRCode","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","__webpack_modules__","n","getter","__esModule","d","getPrototypeOf","obj","__proto__","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","nc","setAttribute","onScriptComplete","prev","timeout","doneFns","parentNode","Symbol","toStringTag","p","installedChunks","installedChunkData","errorType","realSrc","request","webpackJsonpCallback","parentChunkLoadingFunction","chunkIds","moreModules","runtime","some","chunkLoadingGlobal","stringToByteArray$1","out","base64","byteToCharMap_","charToByteMap_","byteToCharMapWebSafe_","charToByteMapWebSafe_","ENCODED_VALS_BASE","ENCODED_VALS","ENCODED_VALS_WEBSAFE","HAS_NATIVE_SUPPORT","encodeByteArray","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","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","openDB","version","blocked","upgrade","blocking","terminated","openPromise","oldVersion","newVersion","db","deleteDB","readMethods","writeMethods","cachedMethods","getMethod","targetFuncName","useIndex","isWrite","storeName","store","shift","oldTraps","PlatformLoggerServiceImpl","getPlatformInfoString","isVersionServiceProvider","library","logString","name$q","version$1","logger","_logLevel","_logHandler","_userLogHandler","TypeError","setLogLevel","logHandler","userLogHandler","debug","log","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","overwrite","getHeartbeatsHeader","heartbeatsToSend","unsentEntries","heartbeatsCache","heartbeatEntry","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","getHeaders","apiKey","Headers","Accept","getHeadersWithAuth","appConfig","refreshToken","headers","getAuthorizationHeader","retryIfServerError","sleep","ms","VALID_FID_PATTERN","generateFid","fidByteArray","crypto","msCrypto","getRandomValues","fid","b64String","array","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","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","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","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","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","pin_chat","unpin_chat","ContextMenu","handlePageClick","handleEscapeKey","MenuItems","handler","errorHandler","onShowAlert","deleteMessages","retryMessage","replyToMessage","editMessage","pinMessage","topicPermissionSetter","ctrl","onTopicRemoved","delTopic","me","getMeTopic","pinTopic","delSubscription","dataset","hard","cancelSend","seq","delMessagesAll","delMessagesEdits","delMessagesList","flushMessage","createMessage","publishDraft","pin","updateMode","pickReply","userFrom","userName","menu","disabled","hSize","vSize","position","bounds","clickAt","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","previousMetaDesc","resetDesc","onMetaDesc","handleRejectCall","handleAcceptCall","ringTimer","setInterval","onRinging","clearInterval","onAcceptCall","onClose","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","containerRef","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","dragStart","matchMedia","minimized","setPointerCapture","pointerId","cursor","offsetLeft","offsetTop","parent","offsetParent","maxX","maxY","drag","hasPointerCapture","movementX","movementY","dragEnd","releasePointerCapture","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","minimizedClass","fullScreen","autoPlay","muted","playsInline","onToggleMinimize","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","menuItems","userIsWriter","immutable","entities","_0","_1","tp","styles","userIsAdmin","parseInt","ratio","replyToSeq","sideClass","sequence","bubbleClass","userAvatar","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","sendOnEnter","shiftKey","ctrlKey","metaKey","onKeyPress","messagePrompt","sendIcon","editing","onCancelReply","audioEnabled","attachImage","click","attachFile","Suspense","fallback","onRecordingProgress","onDeleted","display","DocPreview","handleSendDoc","caption","mimeToIcon","default","iconFromMime","GroupSubs","usersOnline","totalCount","subscribers","countToShow","sub","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","isAdmin","unrecognized_video_format","VideoPreview","handleSendVideo","videoWidth","videoHeight","controlist","controls","controlsList","disablePictureInPicture","poster","online_now","last_seen","not_found","invalid_content","editing_message","drag_file","subscriber_count","member_count","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","handleCallPanelToggle","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","onSubsUpdated","onPres","onAuxUpdated","newTopic","newTopicParams","_topicName","isP2PType","getMeta","startMetaQuery","withDesc","build","isSubscribed","isReader","withLaterData","nextState","docPreview","imagePreview","imagePostview","videoPreview","videoPostview","minimizedCallPanel","typingIndicator","fetchingMessages","showGoToLastButton","contentToEdit","dragging","selectedPin","forwardMessage","subs","onlineSubs","isSelfType","peer","p2pPeerDesc","peerMessagingDisabled","minMsgSeq","maxMsgSeq","latestClearId","maxClearId","isChannelType","aux","pinsLoaded","callTopic","subsVersion","readingBlocked","isSharer","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","newState","isNewMessage","getPinnedMessages","attachJSON","searchParams","messageSpecificMenuItems","isDeleter","canDelete","maxDelAge","MSG_DELETE_AGE","onNewChat","onChangePermissions","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","onCallInvite","onCallSendOffer","onCallIceCandidate","onCallSendAnswer","component2","chan","groupTopic","isGroupType","pinnedMessages","latestMsgVersion","messageNodes","previousFrom","prevDate","chatBoxClass","nextFrom","thisFrom","isReply","userDesc","isNaN","thisDate","ts","toDateString","ChatMessage","isChan","_uploader","lastSeen","subcnt","cont","getContact","isP2PTopicName","seen","when","darkModeClass","colorSchema","messagesComponent","displayMobile","onHideMessagesView","marginLeft","errorLevel","errorText","ButtonBack","onBack","MenuContacts","onNewTopic","onSettings","MenuStart","onSignUp","SideNavbar","archived_contacts_title","ContactsView","handleAction","unreadThreads","archivedCount","chatList","pinnedTopicRank","arch","touched","contactList","action_ignored","onShowArchive","no_contacts","AccGeneralView","textSize","isMac","userAgentData","platform","handleColorSchemaSelected","handleTextSizeChanged","handleSendOnEnterSelected","onChangeColorSchema","onTextSizeChanged","onSendOnEnterChanged","verticalAlign","onSelectWallpapers","list","label","AccNotificationsView","handleCheckboxClick","onToggleMessageSounds","onTogglePushNotifications","messageSounds","desktopAlertsEnabled","desktopAlerts","AccSupportView","LoginView","login","password","hostName","saveToken","persist","handleLoginChange","handlePasswordChange","handleToggleSaveToken","onPersistenceChange","onLogin","submitClasses","login_prompt","autoCorrect","autoCapitalize","password_prompt","invalid_id","NewTopicById","qrCodeRef","groupId","myURI","prefix","NewTopicGroup","handleFieldEdit","handleImageChanged","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","URI_TOPIC_ID_PREFIX","getCurrentUserID","HostSelector","changed","handleHostNameChange","onServerAddressChange","hostOptions","SettingsView","transport","secureConnection","handleTransportSelected","handleServerAddressChange","handleToggleSecure","onUpdate","names","ws","lp","transportOptions","phone","ValidationView","credCode","codeReceived","handleCodeChange","credMethod","credToken","numbers_only","AccountSettingsView","CreateAccountView","AccSecurityView","PasswordResetView","WallpapersView","settings","general","security","crop","notif","acc_general","support","newtpk","cred","reset","wallpapers","SidepanelView","handleNewTopic","onNavigate","view","errorAction","errorActionText","loadSpinnerVisible","loginDisabled","onLoginRequest","reqCredMethod","onShowCountrySelector","onCreateAccount","onGlobalSettings","onCredAdd","onCredDelete","onCredConfirm","onUpdateAccountDesc","onUpdateAccountTags","incognitoMode","onUpdatePassword","onLogout","onDeleteAccount","onShowBlocked","onToggleIncognitoMode","systemColorSchema","onWallpaperSelected","onValidateCredentials","onRequest","onPasswordResetRequest","onReset","onResetPassword","detectServerAddress","host","protocol","hostname","port","isSecureConnection","PhoneCountrySelector","InfoView","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","handleColorSchemeChange","checkForAppUpdate","handleVisibilityEvent","handleLoginRequest","handlePersistenceChange","handleConnected","handleAutoreconnectIteration","doLogin","handleLoginSuccessful","handleDisconnect","tnMeMetaDesc","tnMeContactUpdate","tnMeSubsUpdated","resetContactList","tnInitFind","tnFndSubsUpdated","handleTopicSelected","handleHideMessagesView","handleSendMessage","handleNewChatInvitation","handleNewAccount","handleNewAccountRequest","handleUpdatePasswordRequest","handleUpdateAccountTagsRequest","handleToggleIncognitoMode","handleChangeColorSchema","handleChangeTextSize","handleSendOnEnter","handleSelectWallpapers","handleWallpaperSelected","handleSettings","handleGlobalSettings","handleShowArchive","handleShowBlocked","handleToggleMessageSounds","handleCredAdd","handleCredDelete","handleCredConfirm","initFCMessaging","toggleFCMToken","handlePushMessage","handleSidepanelCancel","handleStartTopicRequest","handleNewTopicCreated","handleTopicUpdateRequest","handleUnarchive","handleChangePermissions","handleTagsUpdateRequest","handleLogout","handleDeleteAccount","handleDeleteTopicRequest","handleDeleteMessagesRequest","handleLeaveUnsubRequest","handleBlockTopicRequest","handleReportTopic","handleShowContextMenu","defaultTopicContextMenu","handleHideContextMenu","handleShowAlert","handleShowInfoView","handleMemberUpdateRequest","handleValidateCredentialsRequest","handlePasswordResetRequest","handleResetPassword","handleContextMenuAction","handleShowCountrySelector","handleShowForwardDialog","handleHideForwardDialog","handleStartVideoCall","handleStartAudioCall","handleInfoMessage","handleDataMessage","handleCallClose","handleCallInvite","handleCallRinging","handleCallSendOffer","handleCallIceCandidate","handleCallSendAnswer","handleCallAccept","sendMessageToTopic","callTimeoutTimer","wallpaper","wallpaperSize","wallpaperBlur","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","searchableContacts","requestedTopic","handleOnlineOn","handleOnlineOff","documentElement","colorScheme","setProperty","applyWallpaperSettings","lastWakeUpCheck","wakeUpTicker","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","withTags","withCred","disconnect","urlHash","isPresencer","checkIfPinsUpdated","archived","isArchived","unused","prepareSearchableContacts","foundContacts","merged","updated","past","withSub","setMeta","isTopicOnline","completion","subscribePromise","calls","publishMessage","getGiven","am","updateWant","getWant","login_","password_","public_","cred_","tags_","createAccountBasic","on","schema","applyColorSchema","systemSchema","effectiveSchema","blur","option","firebaseDelToken","delCredential","scheme","basicNavigator","infoNavigator","defacs","newGroupTopicName","oldName","newName","updateAccountBasic","getCurrentLogin","updateGiven","cleared","Promose","delCurrentUser","report","header","forwardedContent","mention","msgPreview","self_blocked","subscribed","deleter","writer","p2p","keepForwardedMessage","confirmText","rejectText","added","invite","requestResetAuthSecret","newPassword","tempAuth","secret","dial","selectedCallback","aonly","videoCall","sdp","setCallTopic","upd","myUserName","panel","onTopicDescUpdateRequest","onMemberUpdateRequest","onDeleteTopic","onDeleteMessages","onLeaveTopic","onBlockTopic","onReportTopic","onAddMember","handleManageGroupMembers","onTopicTagsUpdateRequest","onTopicUnArchive","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/contact-badges.jsx","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/./src/widgets/error-panel.jsx","webpack://tinode-webapp/./src/widgets/in-place-edit.jsx","webpack://tinode-webapp/external var \"React\"","webpack://tinode-webapp/./src/widgets/tag-manager.jsx","webpack://tinode-webapp/./src/lib/utils.js","webpack://tinode-webapp/./src/widgets/menu-cancel.jsx","webpack://tinode-webapp/./src/widgets/contact-action.jsx","webpack://tinode-webapp/./src/widgets/contact-list.jsx","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/widgets/chip.jsx","webpack://tinode-webapp/./src/widgets/chip-input.jsx","webpack://tinode-webapp/./src/widgets/unread-badge.jsx","webpack://tinode-webapp/./src/widgets/contact.jsx","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/./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/uploading-image.jsx","webpack://tinode-webapp/./src/lib/formatters.js","webpack://tinode-webapp/./src/widgets/topic-desc-edit.jsx","webpack://tinode-webapp/./src/views/topic-common-view.jsx","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/external var \"QRCode\"","webpack://tinode-webapp/./src/widgets/file-progress.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/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/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-general-view.jsx","webpack://tinode-webapp/./src/views/acc-notifications-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\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 = 8;\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 bounding box (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.001,\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 (does not change).\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 (does not change).\n this.cutoutRect = {};\n this.bBoxRect = {};\n // Center of the bounding box (does not change).\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 cutout circle bounds 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: minZoom * DEFAULT_MAX_ZOOM\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\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 const imgTop = this.originY - (this.originY - panY) * zoom;\n const imgBottom = imgTop + this.imageHeight * zoom;\n\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 const coTop = this.cutoutRect.top - this.bBoxRect.top;\n const coBottom = coTop + this.cutoutRect.height;\n\n if (coLeft < imgLeft) {\n panX -= (imgLeft - coLeft) / zoom;\n } else if (coRight > imgRight) {\n panX += (coRight - imgRight) / zoom;\n }\n\n if (coTop < imgTop) {\n panY -= (imgTop - coTop) / zoom;\n } else if (coBottom > imgBottom) {\n panY += (coBottom - imgBottom) /zoom;\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) / this.state.zoom;\n const dY = (pageY - this.mouseY) / this.state.zoom;\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 const panX = Cropper.checkBound(this.state.panX, [imgRect.left, imgRect.right],\n [this.cutoutRect.left, this.cutoutRect.right], dX);\n const 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.25.0-beta2\";\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","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","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","// 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","module.exports = React;","// 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","// Odds and ends\n\nimport { Tinode } from 'tinode-sdk';\nimport { WALLPAPER_DEFAULTS } from '../config.js';\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\nexport function defaultWallpaper() {\n const wallpaperIndex = require('../../img/bkg/index.json');\n const wp = wallpaperIndex[WALLPAPER_DEFAULTS.type][WALLPAPER_DEFAULTS.index];\n return {name: `../${WALLPAPER_DEFAULTS.path}${wp.name}`, size: wp.size};\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","// 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","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 = '#1781d7'; // average between dark and light accent colors.\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","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","// 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","// 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';\nimport { truncateString } from '../lib/strformat.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({\n topicName: this.props.item,\n topicTitle: this.props.title,\n y: e.pageY,\n x: e.pageX\n });\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 // Have to support RTL languages too.\n title = truncateString(title, 30);\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 const bgColor = this.props.showCheckmark ? null :\n (this.props.selected ? 'selected' : (this.props.pinned ? 'tpinned' : null));\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 ? podcasts : 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","// 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","// 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","// 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,\n REM_SIZE, 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\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 (Drafty.isFormResponseType(data.mime)) {\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 (Drafty.isFormResponseType(data.mime)) {\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","// 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 { truncateString } from '../lib/strformat.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 = truncateString(fn.trim(), 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","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\n// Truncate a string to a specific length and add ellipsis if needed.\n// Support both LTR and RTL languages.\nexport function truncateString(str, maxLength) {\n if (typeof str !== 'string') {\n return str;\n }\n if (str.length <= maxLength) {\n return str;\n }\n\n // Detect RTL characters in the string and truncate accordingly.\n const isRTL = /[\\u0590-\\u05FF\\u0600-\\u06FF\\u0750-\\u077F\\u08A0-\\u08FF\\uFB50-\\uFDFF\\uFE70-\\uFEFF]/.test(str);\n return isRTL ? '…' + str.slice(0, maxLength - 1) : str.slice(0, maxLength - 1) + '…';\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\n// Initial/default color scheme.\nexport const DEFAULT_COLOR_SCHEME = 'auto';\n\n// Default text size in points.\nexport const DEFAULT_TEXT_SIZE = 10;\n\n// MIME type for the legacy Drafty form-response data.\nexport const DRAFTY_FR_MIME_TYPE_LEGACY = 'application/json'; // Remove in 2026.\n\n// Path to wallpaper images.\nexport const WALLPAPER_DEFAULTS = {type: 'patt', index: 0, path:'img/bkg/'};\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","module.exports = QRCode;","// 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","// 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 pin_chat: {\n id: 'pin_chat',\n defaultMessage: 'Pin',\n description: 'Menu item [Pin] for pinning chat to the top.'\n },\n unpin_chat: {\n id: 'unpin_chat',\n defaultMessage: 'Unpin',\n description: 'Menu item [Unpin] for un-pinning the chat.'\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 params.topicTitle || 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 params.topicTitle || 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 params.topicTitle || 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 params.topicTitle || 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 'topic_pin': {\n id: 'topic_pin',\n title: formatMessage(messages.pin_chat),\n handler: (params, errorHandler) => {\n const me = this.props.tinode.getMeTopic();\n if (!me) {\n console.warn(\"'me' topic not found\");\n return;\n }\n return me.pinTopic(params.topicName, true).catch(err => {\n if (errorHandler) {\n errorHandler(err.message, 'err');\n }\n });\n }\n },\n 'topic_unpin': {\n id: 'topic_unpin',\n title: formatMessage(messages.unpin_chat),\n handler: (params, errorHandler) => {\n const me = this.props.tinode.getMeTopic();\n if (!me) {\n console.warn(\"'me' topic not found\");\n return;\n }\n return me.pinTopic(params.topicName, 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\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 { truncateString } from '../lib/strformat.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: truncateString(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
{truncateString(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","// 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';\nimport { truncateString } from '../lib/strformat.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.containerRef = React.createRef();\n this.localRef = React.createRef();\n this.remoteRef = React.createRef();\n\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 this.bounds = {};\n\n this.dragStart = (event) => {\n if (!event.target.classList.contains('draggable')) {\n // Prevent dragging when clicking on buttons or other non-draggable elements.\n return;\n }\n if (window.matchMedia('(width<=640px)')) {\n // No dragging on small screens.\n return;\n }\n if (this.props.minimized && this.containerRef) {\n event.stopPropagation();\n this.containerRef.current.setPointerCapture(event.pointerId);\n this.containerRef.current.style.cursor = 'grabbing';\n this.bounds.left = this.containerRef.current.offsetLeft;\n this.bounds.top = this.containerRef.current.offsetTop;\n this.bounds.width = this.containerRef.current.offsetWidth;\n this.bounds.height = this.containerRef.current.offsetHeight;\n\n const parent = this.containerRef.current.offsetParent;\n this.bounds.maxX = parent.offsetWidth;\n this.bounds.maxY = parent.offsetHeight;\n }\n };\n this.drag = (event) => {\n event.stopPropagation();\n const el = this.containerRef.current;\n if (this.props.minimized && this.containerRef && el.hasPointerCapture(event.pointerId)) {\n // Calculate new position. Restrict to the visible area of the parent element.\n this.bounds.left = Math.min(Math.max(this.bounds.left + event.movementX, 0),\n this.bounds.maxX - this.bounds.width);\n this.bounds.top = Math.min(Math.max(this.bounds.top + event.movementY, 0),\n this.bounds.maxY - this.bounds.height);\n\n el.style.left = `${this.bounds.left}px`;\n el.style.top = `${this.bounds.top}px`;\n }\n };\n this.dragEnd = (event) => {\n event.stopPropagation();\n if (this.props.minimized && this.containerRef) {\n this.containerRef.current.releasePointerCapture(event.pointerId);\n this.containerRef.current.style.cursor = 'grab';\n }\n };\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 if (this.containerRef) {\n this.containerRef.current.addEventListener('pointerdown', this.dragStart);\n this.containerRef.current.addEventListener('pointermove', this.drag);\n this.containerRef.current.addEventListener('pointerup', this.dragEnd);\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 if (this.containerRef) {\n this.containerRef.current.removeEventListener('pointerdown', this.dragStart);\n this.containerRef.current.removeEventListener('pointermove', this.drag);\n this.containerRef.current.removeEventListener('pointerup', this.dragEnd);\n }\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 = truncateString(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 const minimizedClass = this.props.minimized ? 'minimized' : null;\n const fullScreen = this.props.minimized ? 'fullscreen' : 'fullscreen_exit';\n\n return (\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 {fullScreen} \n \n
\n \n call_end \n \n \n {videoIcon} \n \n \n {audioIcon} \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 (Drafty.isFormResponseType(att.mime)) {\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 // Enter pressed: either send, or enter a new line.\n if (e.key === 'Enter') {\n if (this.props.sendOnEnter == 'plain') {\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 } else {\n if (e.ctrlKey || e.metaKey) {\n e.preventDefault();\n e.stopPropagation();\n\n this.handleSend(e);\n }\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 DRAFTY_FR_MIME_TYPE_LEGACY, KEYPRESS_DELAY, MESSAGES_PAGE, MAX_EXTERN_ATTACHMENT_SIZE, MAX_IMAGE_DIM,\n MAX_INBAND_ATTACHMENT_SIZE, 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: {timestamp}',\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 subscriber_count: {\n id: 'subscriber_count',\n defaultMessage: '{count, plural, ' +\n 'one {{count, number} subscriber} ' +\n 'two {{count, number} subscribers} ' +\n 'three {{count, number} subscribers} ' +\n 'few {{count, number} subscribers} ' +\n 'many {{count, number} subscribers} ' +\n 'other {{count, number} subscribers}}',\n description: 'Count of channel subscribers'\n },\n member_count: {\n id: 'member_count',\n defaultMessage: '{count, plural, ' +\n 'one {{count, number} member} ' +\n 'two {{count, number} members} ' +\n 'three {{count, number} members} ' +\n 'few {{count, number} members} ' +\n 'many {{count, number} members} ' +\n 'other {{count, number} members}}',\n description: 'Count of group topic members'\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.handleCallPanelToggle = this.handleCallPanelToggle.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 minimizedCallPanel: false,\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 minimizedCallPanel: false,\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 === DRAFTY_FR_MIME_TYPE_LEGACY ? '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 handleCallPanelToggle() {\n this.setState({minimizedCallPanel: !this.state.minimizedCallPanel});\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 // P2P call is an overlay, not a separate component because it cannot be\n // re-mounted between full screen/minimized.\n const overlay = this.state.rtcPanel ? (\n \n ) : null;\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 {\n const topic = this.props.tinode.getTopic(this.state.topic);\n const isChannel = topic.isChannelType() || topic.chan;\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.subscriber_count, {count: topic.subcnt});\n } else {\n const cont = this.props.tinode.getMeTopic().getContact(this.state.topic);\n if (cont) {\n if (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 {timestamp: shortDateFormat(cont.seen.when, this.props.intl.locale)});\n // TODO: also handle user agent in c.seen.ua\n }\n } else if (Tinode.isGroupTopicName(cont.topic)) {\n lastSeen = formatMessage(messages.member_count, {count: topic.subcnt});\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 const darkModeClass = this.props.colorSchema == 'dark' ? 'dark' : '';\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}{overlay}
\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\n const me = props.tinode.getMeTopic();\n props.chatList.forEach(c => {\n const blocked = c.acs && !c.acs.isJoiner();\n c.pinned = me.pinnedTopicRank(c.topic);\n\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 const pin = b.pinned - a.pinned;\n return pin != 0 ? pin : (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\nexport default class AccGeneralView extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.state = {\n colorSchema: props.colorSchema || 'auto',\n textSize: (props.textSize * 10) || '100',\n sendOnEnter: props.sendOnEnter || 'plain',\n };\n\n this.isMac = ((navigator.userAgentData && navigator.userAgentData.platform)\n || navigator.platform).toLowerCase().startsWith('mac');\n this.handleColorSchemaSelected = this.handleColorSchemaSelected.bind(this);\n this.handleTextSizeChanged = this.handleTextSizeChanged.bind(this);\n this.handleSendOnEnterSelected = this.handleSendOnEnterSelected.bind(this);\n }\n\n handleColorSchemaSelected(e) {\n this.setState({colorSchema: e.currentTarget.value});\n this.props.onChangeColorSchema(e.currentTarget.value);\n }\n\n handleTextSizeChanged(e) {\n // In %%.\n this.setState({textSize: e.currentTarget.value});\n // Convert %% to pt, 100% = 10pt.\n this.props.onTextSizeChanged((e.currentTarget.value / 10) | 0);\n }\n\n handleSendOnEnterSelected(e) {\n this.setState({sendOnEnter: e.currentTarget.value});\n this.props.onSendOnEnterChanged(e.currentTarget.value);\n }\n\n render() {\n return (\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 AccNotificationsView 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 }\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","// 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';\nimport { truncateString } from '../lib/strformat.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 = truncateString(this.state.fullName.trim(), MAX_TITLE_LENGTH);\n const comment = truncateString(this.state.private.trim(), MAX_TITLE_LENGTH);\n const description = truncateString(this.state.description.trim(), 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 AccGeneralView from './acc-general-view.jsx';\nimport AccNotificationsView from './acc-notifications-view.jsx';\nconst AccSecurityView = React.lazy(_ => import('./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';\nconst WallpapersView = React.lazy(_ => import('./wallpapers.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 acc_general: {\n id: 'sidepanel_title_acc_general',\n description: 'Sidepanel title for AccGeneralView.',\n defaultMessage: 'General'\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 wallpapers: {\n id: 'wallpapers',\n description: 'Link or title for working with wallpapers.',\n defaultMessage: 'Wallpapers'\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 === 'acc_general' ?\n :\n\n view === 'notif' ?\n :\n\n view === 'security' ?\n }>\n \n :\n\n view === 'support' ?\n :\n\n view === 'wallpapers' ?\n }>\n \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\nconst InfoView = React.lazy(_ => import('./info-view.jsx'));\nimport MessagesView from './messages-view.jsx';\nimport SidepanelView from './sidepanel-view.jsx';\n\nimport { API_KEY, APP_NAME, DEFAULT_COLOR_SCHEME, DEFAULT_P2P_ACCESS_MODE, DEFAULT_TEXT_SIZE, FORWARDED_PREVIEW_LENGTH,\n LOGGING_ENABLED, 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 { defaultWallpaper, 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.handleColorSchemeChange = this.handleColorSchemeChange.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.handleChangeColorSchema = this.handleChangeColorSchema.bind(this);\n this.handleChangeTextSize = this.handleChangeTextSize.bind(this);\n this.handleSendOnEnter = this.handleSendOnEnter.bind(this);\n this.handleSelectWallpapers = this.handleSelectWallpapers.bind(this);\n this.handleWallpaperSelected = this.handleWallpaperSelected.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 if (!settings.wallpaper) {\n const wallpaper = defaultWallpaper();\n settings.wallpaper = wallpaper.name || '';\n settings.wallpaperSize = wallpaper.size || 0;\n settings.wallpaperBlur = 0;\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 // Manually selected color scheme. Default: 'system default' ('auto').\n colorSchema: settings.colorSchema || DEFAULT_COLOR_SCHEME,\n systemColorSchema: window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light',\n // Wallpaper settings.\n wallpaper: settings.wallpaper,\n wallpaperSize: settings.wallpaperSize,\n wallpaperBlur: 0,\n // Text size in points. Default size: 10pt\n textSize: settings.textSize || DEFAULT_TEXT_SIZE,\n // Default: 'plain' (just Enter)\n sendOnEnter: settings.sendOnEnter || 'plain',\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 window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', this.handleColorSchemeChange);\n\n // Window/tab visible or invisible for pausing timers.\n document.addEventListener('visibilitychange', this.handleVisibilityEvent);\n\n document.documentElement.style.colorScheme = this.state.colorSchema == 'auto' ? 'light dark' : this.state.colorSchema;\n document.documentElement.style.setProperty('--message-text-size', `${this.state.textSize}pt`);\n\n this.applyWallpaperSettings(this.state.wallpaper, this.state.wallpaperSize, this.state.wallpaperBlur,\n this.state.colorSchema == 'auto' ? this.state.systemColorSchema : this.state.colorSchema);\n\n console.log(\"Wallpaper settings:\", this.state.wallpaper, this.state.wallpaperSize, this.state.wallpaperBlur);\n console.log(\"Wallpaper type:\", this.state.wallpaperSize == 0 ? 'wpimg' : 'wppatt');\n console.log(\"System color scheme:\", this.state.systemColorSchema);\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 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 window.matchMedia('(prefers-color-scheme: dark)').removeEventListener('change', this.handleColorSchemeChange);\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 (['acc_general','archive','blocked','contacts','cred','crop','edit','general',\n 'newtpk','notif','register','reset','security','settings','support','wallpapers',\n ''].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 return;\n }\n\n if (desc.public) {\n this.setState({\n sidePanelTitle: desc.public.fn,\n sidePanelAvatar: makeImageUrl(desc.public.photo)\n });\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\n if (desc.acs) {\n this.setState({\n incognitoMode: !desc.acs.isPresencer()\n });\n }\n\n if (TinodeWeb.checkIfPinsUpdated(desc, this.state.chatList)) {\n this.resetContactList();\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 const me = this.tinode.getMeTopic();\n me.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 // Pinned topics take precedence.\n const pins = me.pinnedTopicRank(b.topic) - me.pinnedTopicRank(a.topic);\n // Then sort by last touched time.\n return pins != 0 ? pins : (b.touched || past).getTime() - (a.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 static checkIfPinsUpdated(me, chatList) {\n for (let i = 0; i < chatList.length; i++) {\n const c = chatList[i];\n if (!!me.pinnedTopicRank(c.topic) != c.pinned) {\n return true;\n }\n }\n return false;\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 // Manual change of color scheme: 'dark', 'light', 'auto'.\n handleChangeColorSchema(schema) {\n console.log(\"User color scheme change:\", schema);\n this.setState({colorSchema: schema});\n LocalStorageUtil.updateObject('settings', {colorSchema: schema});\n document.documentElement.style.colorScheme = schema == 'auto' ? 'light dark' : schema;\n this.applyColorSchema(schema, this.state.systemColorSchema, this.state.wallpaperSize);\n }\n\n // System color scheme has changed.\n handleColorSchemeChange(event) {\n const systemSchema = event.matches ? 'dark' : 'light';\n console.log(\"System color scheme change:\", systemSchema);\n this.setState({systemColorSchema: systemSchema});\n this.applyColorSchema(this.state.colorSchema, systemSchema, this.state.wallpaperSize);\n }\n\n applyColorSchema(schema, systemSchema, size) {\n const effectiveSchema = schema == 'auto' ? systemSchema : schema;\n console.log(\"applyColorSchema:\", effectiveSchema);\n document.documentElement.style.setProperty('--wallpaper-invert', effectiveSchema == 'dark' && size ? '1' : '0');\n document.documentElement.style.setProperty('--wallpaper-brightness', effectiveSchema == 'dark' && !size ? '0.5' : '1');\n }\n\n handleSelectWallpapers() {\n this.handleError();\n HashNavigation.navigateTo(HashNavigation.setUrlSidePanel(window.location.hash, 'wallpapers'));\n }\n\n applyWallpaperSettings(wallpaper, size, blur, effectiveSchema) {\n document.documentElement.style.setProperty('--wallpaper-url', `url('${wallpaper}')`);\n document.documentElement.style.setProperty('--wallpaper-repeat', size ? 'repeat' : 'no-repeat');\n document.documentElement.style.setProperty('--wallpaper-blur', size ? '0px' : `${blur}px`);\n document.documentElement.style.setProperty('--wallpaper-size', size ? `${size}px` : 'cover');\n document.documentElement.style.setProperty('--wallpaper-position', size ? 'unset' : 'center');\n document.documentElement.style.setProperty('--wallpaper-invert', effectiveSchema == 'dark' && size ? '1' : '0');\n document.documentElement.style.setProperty('--wallpaper-brightness', effectiveSchema == 'dark' && !size ? '0.5' : '1');\n }\n\n handleWallpaperSelected(wallpaper, size, blur) {\n this.handleError();\n LocalStorageUtil.updateObject('settings', {wallpaper: wallpaper, wallpaperSize: size, wallpaperBlur: blur});\n this.setState({wallpaper: wallpaper, wallpaperSize: size, wallpaperBlur: blur});\n this.applyWallpaperSettings(wallpaper, size, blur,\n this.state.colorSchema == 'auto' ? this.state.systemColorSchema : this.state.colorSchema);\n }\n\n handleChangeTextSize(size) {\n this.setState({textSize: size | 0});\n LocalStorageUtil.updateObject('settings', {textSize: size});\n document.documentElement.style.setProperty('--message-text-size', `${size}pt`);\n }\n\n handleSendOnEnter(option) {\n this.setState({sendOnEnter: option});\n LocalStorageUtil.updateObject('settings', {sendOnEnter: option});\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','acc_general'].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 ('wallpapers' == parsed.path[0]) {\n path = 'acc_general';\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 // Reset color scheme.\n document.documentElement.style.colorScheme = DEFAULT_COLOR_SCHEME == 'auto' ? 'light dark' : DEFAULT_COLOR_SCHEME;\n document.documentElement.style.setProperty('--message-text-size', `${DEFAULT_TEXT_SIZE}pt`);\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 const me = this.tinode.getMeTopic();\n let muted = false, blocked = false, self_blocked = false, subscribed = false, deleter = false,\n archived = false, pinned = false, webrtc = false, writer = false, p2p = false, self = false;\n if (topic) {\n subscribed = topic.isSubscribed();\n archived = topic.isArchived();\n pinned = me.pinnedTopicRank(topicName) > 0;\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 pinned ? 'topic_unpin' : 'topic_pin',\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 const colorSchema = this.state.colorSchema !== 'auto' ? this.state.colorSchema : this.state.systemColorSchema;\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 \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 'it': _ => import('./i18n.min/it.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","imgTop","imgBottom","coLeft","coRight","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","ContactBadges","badges","forEach","b","color","icon","push","key","name","messages","defineMessages","badge_verified","badge_staff","badge_danger","BadgeList","formatMessage","intl","trustedBadges","comment","short","injectIntl","LoadSpinner","large","clear","centered","show","CheckBox","checked","iconName","classList","Array","isArray","attrs","join","ErrorPanel","hide","componentDidUpdate","prevProps","level","onClearError","warn","info","text","action","href","whiteSpace","actionText","MenuCancel","InPlaceEdit","selfRef","active","initialValue","valid","handeTextChange","handleKeyDown","handleStartEditing","handleEditingFinished","handlePasswordFinished","prevState","newValue","validator","Promise","resolve","keyCode","readOnly","_","focus","event","trim","required","checkValidity","onFinished","spanText","spanClass","placeholder","multiline","iconLeft","iconRight","element","attr","VisiblePassword","rows","maxLength","onKeyDown","onBlur","autoComplete","autoFocus","undefined","spellCheck","module","exports","TagManager","tags","alias","Tinode","tagByPrefix","TAG_ALIAS","tagInput","activated","handleTagInput","handleAddTag","handleRemoveTag","handleCancel","getDerivedStateFromProps","nextProps","arrayEqual","last","substring","tag","maxTagCount","tinode","getServerParam","MAX_TAG_COUNT","slice","onTagsChanged","index","splice","setUniqueTag","minTagLength","MIN_TAG_LENGTH","maxTagLength","MAX_TAG_LENGTH","user","invalid","title","add_tags_prompt","ChipInput","chips","avatarDisabled","prompt","tabIndex","onEnter","onFocusLost","onChipRemoved","filterFunc","updateFavicon","count","oldIcon","getElementById","head","getElementsByTagName","newIcon","createElement","rel","removeChild","appendChild","theCard","fn","imageUrl","imageMimeType","note","card","DEL_CHAR","mimeType","matches","exec","photo","data","indexOf","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","MESSAGE_STATUS_SENT","MESSAGE_STATUS_RECEIVED","MESSAGE_STATUS_READ","cancelablePromise","promise","hasCanceled","Error","reject","result","isCanceled","error","cancel","defaultWallpaper","wp","require","WALLPAPER_DEFAULTS","path","size","ContactAction","handleClick","stopPropagation","onAction","values","badge_you","badge_owner","ContactList","showCheckmark","topicSelected","contactNodes","contactsCount","showSelfTopic","selected","Contact","showMode","onSelected","onTopicSelected","showContextMenu","item","contacts","c","topic","filter","filterOn","private","toLowerCase","public","isChannel","isChannelTopicName","isGroup","isGroupTopicName","myUserId","acs","isOwner","forwarded","previewIsResponse","deliveryStatus","latestMessage","msg","_status","msgStatus","from","content","substr","MESSAGE_PREVIEW_LENGTH","Drafty","makeImageUrl","unread","showUnread","now","online","connected","pinned","showOnline","isVerified","trusted","verified","isStaff","staff","isDangerous","danger","deleted","_deleted","noScroll","dangerouslySetInnerHTML","__html","emptyListMessage","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","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","Chip","noAvatar","LetterTile","deriveStateFromProps","input","focused","handleTextInput","removeChipAt","handleChipCancel","handleFocusGained","handleFocusLost","sortedChips","sortChips","staticMembers","chipIndex","indexChips","keep","normal","includes","concat","idx","removed","at","onFocus","UnreadBadge","self_topic_name","self_topic_comment","handleContextClick","topicName","topicTitle","self","isSelfTopicName","truncateString","icon_badges","getMode","isMuted","isJoiner","isValid","format","previewFormatter","marker","titleClass","bgColor","small","SUPPORTED_IMAGE_FORMATS","MIME_EXTENSIONS","fitImageSize","maxWidth","maxHeight","forceSquare","dstWidth","dstHeight","srcWidth","srcHeight","xoffset","yoffset","fileNameForMime","fname","ext","lastIndexOf","imageScaled","fileOrBlob","maxSize","Image","crossOrigin","onerror","onload","async","URL","revokeObjectURL","dim","canvas","ctx","imageSmoothingEnabled","drawImage","toBlob","createObjectURL","objURL","fileToBase64","file","reader","FileReader","bits","split","readAsDataURL","blobToBase64","filePasted","onImageSuccess","onAttachmentSuccess","items","clipboardData","originalEvent","kind","getAsFile","base64ReEncode","str","btoa","atob","base64ToBlob","bin","buf","ArrayBuffer","arr","Uint8Array","charCodeAt","Blob","intArrayToBase64","String","fromCharCode","b64","inputRef","visible","handleVisibility","currentTarget","setTimeout","contains","activeElement","SELF_AVATAR_URI","iconColor","idToColorClass","letter","charAt","authorizeURL","HashNavigation","parseUrlHash","hash","parts","arg","eq","decodeURIComponent","navigateTo","location","composeUrlHash","args","hasOwnProperty","encodeURIComponent","addUrlParam","parsed","removeUrlParam","setUrlSidePanel","sidepanel","setUrlInfoPanel","infopanel","setUrlTopic","CallMessage","isCallDropped","callState","successClass","callIcon","incoming","CallStatus","icon2","InlineVideo","videoRef","LazyImage","isvideo","Object","assign","padding","whenDone","UploadingImage","FileProgress","progress","onCancelUpload","drafty_form","drafty_attachment","drafty_image","drafty_video","drafty_unknown","fullFormatter","stack","quoteFormatter","call","el","tagName","attrValue","loading","handleImageData","onFormButtonClick","inner","child","CLICKABLE_URL_SCHEMES","onQuoteClick","handleVideoData","IMAGE_THUMBNAIL_DIM","viewportWidth","REM_SIZE","BROKEN_IMAGE_SIZE","minWidth","minHeight","isProcessing","onImagePreview","NO_DIMENSIONS_VIDEO","onVideoPreview","isFormResponseType","inlineImageAttr","inlineVideoAttr","VIDEO_THUMBNAIL_WIDTH","shortenFileName","quoteImageOrVideo","isVideo","premime","preref","fetch","evt","ok","status","statusText","scaled","replyFormatter","loadedPromise","message","alias_invalid","alias_already_taken","TopicDescEdit","getTopic","getAccessMode","isSelf","isMe","isMeTopicName","owner","fullName","description","newAvatar","newAvatarMime","aliasError","previousOnTags","aliasCheckTimer","aliasCheckPromise","tnNewTags","handleFullNameUpdate","handleImageUpdated","handleAvatarCropped","handleAvatarCropCancel","uploadAvatar","handlePrivateUpdate","handleAliasUpdate","handleDescriptionUpdate","handleTagsUpdated","validateAlias","cancelValidator","onTagsUpdated","MAX_TITLE_LENGTH","onUpdateTopicDesc","desc","MAX_TOPIC_DESCRIPTION_LENGTH","readyToUpload","image","MAX_AVATAR_BYTES","getLargeFileHelper","upload","du","AVATAR_SIZE","MAX_EXTERN_ATTACHMENT_SIZE","clearTagPrefix","isValidTagValue","fnd","getFndTopic","validationPromise","checkTagUniqueness","clearTimeout","onUpdateTags","editable","find","t","AvatarUpload","uid","onImageUpdated","full_name_placeholder","group_name_placeholder","private_placeholder","title_tag_manager","TopicCommonView","previousTagsUpdated","getType","onUpdateTagsRequest","ReactIntl","LocalStorageUtil","setObject","localStorage","setItem","JSON","stringify","getObject","getItem","parse","updateObject","oldVal","removeItem","shortDateFormat","locale","navigator","userLanguage","language","Date","getFullYear","getMonth","getDate","toLocaleTimeString","hour12","hour","minute","toLocaleDateString","month","day","year","relativeDateFormat","diff","floor","getTime","getTimezoneOffset","abs","Intl","RelativeTimeFormat","numeric","DateTimeFormat","seconds","fixedMin","hours","sec","bytesToHumanSize","bytes","sizes","bucket","log2","pow","round","toFixed","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","DEFAULT_P2P_ACCESS_MODE","NO_ACCESS_MODE","MEDIA_BREAKPOINT","MESSAGES_PAGE","MAX_INBAND_ATTACHMENT_SIZE","MAX_IMAGE_DIM","IMAGE_PREVIEW_DIM","VIDEO_PREVIEW_DIM","MAX_ONLINE_IN_TOPIC","MAX_PEER_TITLE_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","QRCODE_SIZE","WAKE_UP_TIMEOUT","WAKE_UP_TICK","MIN_SWIPE_DISTANCE","TOAST_DURATION","DEFAULT_COLOR_SCHEME","DEFAULT_TEXT_SIZE","DRAFTY_FR_MIME_TYPE_LEGACY","handleFileReceived","files","randId","random","accept","htmlFor","uploading","QRCode","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","__webpack_modules__","n","getter","__esModule","d","getPrototypeOf","obj","__proto__","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","nc","setAttribute","onScriptComplete","prev","timeout","doneFns","parentNode","Symbol","toStringTag","p","installedChunks","installedChunkData","errorType","realSrc","request","webpackJsonpCallback","parentChunkLoadingFunction","chunkIds","moreModules","runtime","some","chunkLoadingGlobal","stringToByteArray$1","out","base64","byteToCharMap_","charToByteMap_","byteToCharMapWebSafe_","charToByteMapWebSafe_","ENCODED_VALS_BASE","ENCODED_VALS","ENCODED_VALS_WEBSAFE","HAS_NATIVE_SUPPORT","encodeByteArray","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","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","openDB","version","blocked","upgrade","blocking","terminated","openPromise","oldVersion","newVersion","db","deleteDB","readMethods","writeMethods","cachedMethods","getMethod","targetFuncName","useIndex","isWrite","storeName","store","shift","oldTraps","PlatformLoggerServiceImpl","getPlatformInfoString","isVersionServiceProvider","library","logString","name$q","version$1","logger","_logLevel","_logHandler","_userLogHandler","TypeError","setLogLevel","logHandler","userLogHandler","debug","log","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","overwrite","getHeartbeatsHeader","heartbeatsToSend","unsentEntries","heartbeatsCache","heartbeatEntry","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","getHeaders","apiKey","Headers","Accept","getHeadersWithAuth","appConfig","refreshToken","headers","getAuthorizationHeader","retryIfServerError","sleep","ms","VALID_FID_PATTERN","generateFid","fidByteArray","crypto","msCrypto","getRandomValues","fid","b64String","array","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","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","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","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","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","pin_chat","unpin_chat","ContextMenu","handlePageClick","handleEscapeKey","MenuItems","handler","errorHandler","onShowAlert","deleteMessages","retryMessage","replyToMessage","editMessage","pinMessage","topicPermissionSetter","ctrl","onTopicRemoved","delTopic","me","getMeTopic","pinTopic","delSubscription","dataset","hard","cancelSend","seq","delMessagesAll","delMessagesEdits","delMessagesList","flushMessage","createMessage","publishDraft","pin","updateMode","pickReply","userFrom","userName","menu","disabled","hSize","vSize","position","bounds","clickAt","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","previousMetaDesc","resetDesc","onMetaDesc","handleRejectCall","handleAcceptCall","ringTimer","setInterval","onRinging","clearInterval","onAcceptCall","onClose","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","containerRef","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","dragStart","matchMedia","minimized","setPointerCapture","pointerId","cursor","offsetLeft","offsetTop","parent","offsetParent","maxX","maxY","drag","hasPointerCapture","movementX","movementY","dragEnd","releasePointerCapture","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","minimizedClass","fullScreen","autoPlay","muted","playsInline","onToggleMinimize","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","menuItems","userIsWriter","immutable","entities","_0","_1","tp","styles","userIsAdmin","parseInt","ratio","replyToSeq","sideClass","sequence","bubbleClass","userAvatar","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","sendOnEnter","shiftKey","ctrlKey","metaKey","onKeyPress","messagePrompt","sendIcon","editing","onCancelReply","audioEnabled","attachImage","click","attachFile","Suspense","fallback","onRecordingProgress","onDeleted","display","DocPreview","handleSendDoc","caption","mimeToIcon","default","iconFromMime","GroupSubs","usersOnline","totalCount","subscribers","countToShow","sub","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","isAdmin","unrecognized_video_format","VideoPreview","handleSendVideo","videoWidth","videoHeight","controlist","controls","controlsList","disablePictureInPicture","poster","online_now","last_seen","not_found","invalid_content","editing_message","drag_file","subscriber_count","member_count","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","handleCallPanelToggle","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","onSubsUpdated","onPres","onAuxUpdated","newTopic","newTopicParams","_topicName","isP2PType","getMeta","startMetaQuery","withDesc","build","isSubscribed","isReader","withLaterData","nextState","docPreview","imagePreview","imagePostview","videoPreview","videoPostview","minimizedCallPanel","typingIndicator","fetchingMessages","showGoToLastButton","contentToEdit","dragging","selectedPin","forwardMessage","subs","onlineSubs","isSelfType","peer","p2pPeerDesc","peerMessagingDisabled","minMsgSeq","maxMsgSeq","latestClearId","maxClearId","isChannelType","aux","pinsLoaded","callTopic","subsVersion","readingBlocked","isSharer","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","newState","isNewMessage","getPinnedMessages","attachJSON","searchParams","messageSpecificMenuItems","isDeleter","canDelete","maxDelAge","MSG_DELETE_AGE","onNewChat","onChangePermissions","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","onCallInvite","onCallSendOffer","onCallIceCandidate","onCallSendAnswer","component2","chan","groupTopic","isGroupType","pinnedMessages","latestMsgVersion","messageNodes","previousFrom","prevDate","chatBoxClass","nextFrom","thisFrom","isReply","userDesc","isNaN","thisDate","ts","toDateString","ChatMessage","isChan","_uploader","lastSeen","subcnt","cont","getContact","isP2PTopicName","seen","when","darkModeClass","colorSchema","messagesComponent","displayMobile","onHideMessagesView","marginLeft","errorLevel","errorText","ButtonBack","onBack","MenuContacts","onNewTopic","onSettings","MenuStart","onSignUp","SideNavbar","archived_contacts_title","ContactsView","handleAction","unreadThreads","archivedCount","chatList","pinnedTopicRank","arch","touched","contactList","action_ignored","onShowArchive","no_contacts","AccGeneralView","textSize","isMac","userAgentData","platform","handleColorSchemaSelected","handleTextSizeChanged","handleSendOnEnterSelected","onChangeColorSchema","onTextSizeChanged","onSendOnEnterChanged","verticalAlign","onSelectWallpapers","list","label","AccNotificationsView","handleCheckboxClick","onToggleMessageSounds","onTogglePushNotifications","messageSounds","desktopAlertsEnabled","desktopAlerts","AccSupportView","LoginView","login","password","hostName","saveToken","persist","handleLoginChange","handlePasswordChange","handleToggleSaveToken","onPersistenceChange","onLogin","submitClasses","login_prompt","autoCorrect","autoCapitalize","password_prompt","invalid_id","NewTopicById","qrCodeRef","groupId","myURI","prefix","NewTopicGroup","handleFieldEdit","handleImageChanged","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","URI_TOPIC_ID_PREFIX","getCurrentUserID","HostSelector","changed","handleHostNameChange","onServerAddressChange","hostOptions","SettingsView","transport","secureConnection","handleTransportSelected","handleServerAddressChange","handleToggleSecure","onUpdate","names","ws","lp","transportOptions","phone","ValidationView","credCode","codeReceived","handleCodeChange","credMethod","credToken","numbers_only","AccountSettingsView","CreateAccountView","AccSecurityView","PasswordResetView","WallpapersView","settings","general","security","crop","notif","acc_general","support","newtpk","cred","reset","wallpapers","SidepanelView","handleNewTopic","onNavigate","view","errorAction","errorActionText","loadSpinnerVisible","loginDisabled","onLoginRequest","reqCredMethod","onShowCountrySelector","onCreateAccount","onGlobalSettings","onCredAdd","onCredDelete","onCredConfirm","onUpdateAccountDesc","onUpdateAccountTags","incognitoMode","onUpdatePassword","onLogout","onDeleteAccount","onShowBlocked","onToggleIncognitoMode","systemColorSchema","onWallpaperSelected","onValidateCredentials","onRequest","onPasswordResetRequest","onReset","onResetPassword","detectServerAddress","host","protocol","hostname","port","isSecureConnection","PhoneCountrySelector","InfoView","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","handleColorSchemeChange","checkForAppUpdate","handleVisibilityEvent","handleLoginRequest","handlePersistenceChange","handleConnected","handleAutoreconnectIteration","doLogin","handleLoginSuccessful","handleDisconnect","tnMeMetaDesc","tnMeContactUpdate","tnMeSubsUpdated","resetContactList","tnInitFind","tnFndSubsUpdated","handleTopicSelected","handleHideMessagesView","handleSendMessage","handleNewChatInvitation","handleNewAccount","handleNewAccountRequest","handleUpdatePasswordRequest","handleUpdateAccountTagsRequest","handleToggleIncognitoMode","handleChangeColorSchema","handleChangeTextSize","handleSendOnEnter","handleSelectWallpapers","handleWallpaperSelected","handleSettings","handleGlobalSettings","handleShowArchive","handleShowBlocked","handleToggleMessageSounds","handleCredAdd","handleCredDelete","handleCredConfirm","initFCMessaging","toggleFCMToken","handlePushMessage","handleSidepanelCancel","handleStartTopicRequest","handleNewTopicCreated","handleTopicUpdateRequest","handleUnarchive","handleChangePermissions","handleTagsUpdateRequest","handleLogout","handleDeleteAccount","handleDeleteTopicRequest","handleDeleteMessagesRequest","handleLeaveUnsubRequest","handleBlockTopicRequest","handleReportTopic","handleShowContextMenu","defaultTopicContextMenu","handleHideContextMenu","handleShowAlert","handleShowInfoView","handleMemberUpdateRequest","handleValidateCredentialsRequest","handlePasswordResetRequest","handleResetPassword","handleContextMenuAction","handleShowCountrySelector","handleShowForwardDialog","handleHideForwardDialog","handleStartVideoCall","handleStartAudioCall","handleInfoMessage","handleDataMessage","handleCallClose","handleCallInvite","handleCallRinging","handleCallSendOffer","handleCallIceCandidate","handleCallSendAnswer","handleCallAccept","sendMessageToTopic","callTimeoutTimer","wallpaper","wallpaperSize","wallpaperBlur","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","searchableContacts","requestedTopic","handleOnlineOn","handleOnlineOff","documentElement","colorScheme","setProperty","applyWallpaperSettings","lastWakeUpCheck","wakeUpTicker","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","withTags","withCred","disconnect","urlHash","isPresencer","checkIfPinsUpdated","archived","isArchived","unused","prepareSearchableContacts","foundContacts","merged","updated","past","withSub","setMeta","isTopicOnline","completion","subscribePromise","calls","publishMessage","getGiven","am","updateWant","getWant","login_","password_","public_","cred_","tags_","createAccountBasic","on","schema","applyColorSchema","systemSchema","effectiveSchema","blur","option","firebaseDelToken","delCredential","scheme","basicNavigator","infoNavigator","defacs","newGroupTopicName","oldName","newName","updateAccountBasic","getCurrentLogin","updateGiven","cleared","Promose","delCurrentUser","report","header","forwardedContent","mention","msgPreview","self_blocked","subscribed","deleter","writer","p2p","keepForwardedMessage","confirmText","rejectText","added","invite","requestResetAuthSecret","newPassword","tempAuth","secret","dial","selectedCallback","aonly","videoCall","sdp","setCallTopic","upd","myUserName","panel","onTopicDescUpdateRequest","onMemberUpdateRequest","onDeleteTopic","onDeleteMessages","onLeaveTopic","onBlockTopic","onReportTopic","onAddMember","handleManageGroupMembers","onTopicTagsUpdateRequest","onTopicUnArchive","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 4fd55416..374a1261 100644
--- a/umd/tinode.dev.js
+++ b/umd/tinode.dev.js
@@ -3753,6 +3753,38 @@ class TopicMe extends _topic_js__WEBPACK_IMPORTED_MODULE_2__["default"] {
getCredentials() {
return this._credentials;
}
+ pinTopic(topic, pin) {
+ if (!this._attached) {
+ return Promise.reject(new Error("Cannot pin topic in inactive 'me' topic"));
+ }
+ if (!_topic_js__WEBPACK_IMPORTED_MODULE_2__["default"].isCommTopicName(topic)) {
+ return Promise.reject(new Error("Invalid topic to pin"));
+ }
+ const tpin = Array.isArray(this.private && this.private.tpin) ? this.private.tpin : [];
+ const found = tpin.includes(topic);
+ if (pin && found || !pin && !found) {
+ return Promise.resolve(tpin);
+ }
+ if (pin) {
+ tpin.unshift(topic);
+ } else {
+ tpin.splice(tpin.indexOf(topic), 1);
+ }
+ return this.setMeta({
+ desc: {
+ private: {
+ tpin: tpin.length > 0 ? tpin : _config_js__WEBPACK_IMPORTED_MODULE_1__.DEL_CHAR
+ }
+ }
+ });
+ }
+ pinnedTopicRank(topic) {
+ if (!this.private || !this.private.tpin) {
+ return 0;
+ }
+ const idx = this.private.tpin.indexOf(topic);
+ return idx < 0 ? 0 : this.private.tpin.length - idx;
+ }
}
/***/ }),
@@ -4315,6 +4347,12 @@ class Topic {
}
return Promise.resolve();
}
+ pinTopic(topic, pin) {
+ return Promise.reject(new Error("Pinning topics is not supported here"));
+ }
+ pinnedTopicRank(topic) {
+ return 0;
+ }
delMessages(ranges, hard) {
if (!this._attached) {
return Promise.reject(new Error("Cannot delete messages in inactive topic"));
@@ -5006,10 +5044,14 @@ class Topic {
acs: sub.acs
});
}
+ if (!this._users[sub.user]) {
+ this.subcnt++;
+ }
user = this._updateCachedUser(sub.user, sub);
} else {
delete this._users[sub.user];
user = sub;
+ this.subcnt--;
}
if (this.onMetaSub) {
this.onMetaSub(user);
@@ -5204,7 +5246,7 @@ function rfc3339DateString(d) {
const millis = d.getUTCMilliseconds();
return d.getUTCFullYear() + '-' + pad(d.getUTCMonth() + 1) + '-' + pad(d.getUTCDate()) + 'T' + pad(d.getUTCHours()) + ':' + pad(d.getUTCMinutes()) + ':' + pad(d.getUTCSeconds()) + (millis ? '.' + pad(millis, 3) : '') + 'Z';
}
-function mergeObj(dst, src, ignore) {
+function mergeObj(dst, src) {
if (typeof src != 'object') {
if (src === undefined) {
return dst;
@@ -5215,7 +5257,7 @@ function mergeObj(dst, src, ignore) {
return src;
}
if (src === null) {
- return src;
+ return dst;
}
if (src instanceof Date && !isNaN(src)) {
return !dst || !(dst instanceof Date) || isNaN(dst) || dst < src ? src : dst;
@@ -5230,16 +5272,18 @@ function mergeObj(dst, src, ignore) {
dst = src.constructor();
}
for (let prop in src) {
- if (src.hasOwnProperty(prop) && (!ignore || !ignore[prop]) && prop != '_noForwarding') {
+ if (src.hasOwnProperty(prop) && prop != '_noForwarding') {
try {
dst[prop] = mergeObj(dst[prop], src[prop]);
- } catch (err) {}
+ } catch (err) {
+ console.warn("Error merging property:", prop, err);
+ }
}
}
return dst;
}
-function mergeToCache(cache, key, newval, ignore) {
- cache[key] = mergeObj(cache[key], newval, ignore);
+function mergeToCache(cache, key, newval) {
+ cache[key] = mergeObj(cache[key], newval);
return cache[key];
}
function simplify(obj) {
@@ -5385,7 +5429,7 @@ function clipInRange(src, clip) {
hi: Math.min(src.hi, clip.hi)
};
// removed by dead control flow
-{}
+
}
/***/ }),
@@ -5400,7 +5444,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.4";
+const PACKAGE_VERSION = "0.25.0-beta1";
/***/ })
diff --git a/umd/tinode.dev.js.map b/umd/tinode.dev.js.map
index 70d6d726..b02b5c2f 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 DRAFTY_MIME_TYPE = 'text/x-drafty';\n// Drafty form-response MIME type.\nconst DRAFTY_FR_MIME_TYPE = 'text/x-drafty-fr';\n// Legacy Drafty form-response MIME type.\nconst DRAFTY_FR_MIME_TYPE_LEGACY = 'application/json'; // Remove in 2026.\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: DRAFTY_FR_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 (!Drafty.isFormResponseType(entData.mime) && 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 * Check if the given mime-type is a MIME type of drafty form response.\n * @memberof Drafty\n * @static\n *\n * @returns {boolean} true if given mime type is drafty form response, false otherwise.\n */\nDrafty.isFormResponseType = function(mimeType) {\n return mimeType === DRAFTY_FR_MIME_TYPE ||\n mimeType === DRAFTY_FR_MIME_TYPE_LEGACY;\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 (Drafty.isFormResponseType(c.data['mime'])) {\n // Form response 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.4\";\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","DRAFTY_MIME_TYPE","DRAFTY_FR_MIME_TYPE","DRAFTY_FR_MIME_TYPE_LEGACY","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","isFormResponseType","isProcessing","getPreviewUrl","getEntitySize","getEntityMimeType","tagName","attrValue","getContentType","mimeType","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 DRAFTY_MIME_TYPE = 'text/x-drafty';\n// Drafty form-response MIME type.\nconst DRAFTY_FR_MIME_TYPE = 'text/x-drafty-fr';\n// Legacy Drafty form-response MIME type.\nconst DRAFTY_FR_MIME_TYPE_LEGACY = 'application/json'; // Remove in 2026.\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: DRAFTY_FR_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 (!Drafty.isFormResponseType(entData.mime) && 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 * Check if the given mime-type is a MIME type of drafty form response.\n * @memberof Drafty\n * @static\n *\n * @returns {boolean} true if given mime type is drafty form response, false otherwise.\n */\nDrafty.isFormResponseType = function(mimeType) {\n return mimeType === DRAFTY_FR_MIME_TYPE ||\n mimeType === DRAFTY_FR_MIME_TYPE_LEGACY;\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 (Drafty.isFormResponseType(c.data['mime'])) {\n // Form response 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-2025 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 * Pin topic to the top of the contact list.\n * @memberof Tinode.TopicMe#\n *\n * @param {string} topic - Name of the topic to pin.\n * @param {boolean} [pin=false] - If true, pin the topic, otherwise unpin.\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n pinTopic(topic, pin) {\n if (!this._attached) {\n return Promise.reject(new Error(\"Cannot pin topic in inactive 'me' topic\"));\n }\n if (!Topic.isCommTopicName(topic)) {\n return Promise.reject(new Error(\"Invalid topic to pin\"));\n }\n\n const tpin = Array.isArray(this.private && this.private.tpin) ? this.private.tpin : [];\n const found = tpin.includes(topic);\n if ((pin && found) || (!pin && !found)) {\n // Nothing to do.\n return Promise.resolve(tpin);\n }\n\n if (pin) {\n // Add topic to the top of the pinned list.\n tpin.unshift(topic);\n } else {\n // Remove topic from the pinned list.\n tpin.splice(tpin.indexOf(topic), 1);\n }\n\n return this.setMeta({\n desc: {\n private: {\n tpin: tpin.length > 0 ? tpin : Const.DEL_CHAR\n }\n }\n });\n }\n\n /**\n * Get the rank of the pinned topic.\n * @memberof Tinode.TopicMe#\n * @param {string} topic - Name of the topic to check.\n *\n * @returns {number} numeric rank of the pinned topic in the range 1..N (N being the top,\n * N - the number of pinned topics) or 0 if not pinned.\n */\n pinnedTopicRank(topic) {\n if (!this.private || !this.private.tpin) {\n return 0;\n }\n const idx = this.private.tpin.indexOf(topic);\n return idx < 0 ? 0 : this.private.tpin.length - idx;\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} callbacks.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 /**\n * Pin topic to the top of the contact list.\n * @memberof Tinode.TopicMe#\n *\n * @param {string} topic - Name of the topic to pin.\n * @param {boolean} [pin=false] - If true, pin the topic, otherwise unpin.\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n pinTopic(topic, pin) {\n // Unsupported operation for non-me topics.\n return Promise.reject(new Error(\"Pinning topics is not supported here\"));\n }\n\n /**\n * Get the rank of the pinned topic.\n * @memberof Tinode.TopicMe#\n * @param {string} topic - Name of the topic to check.\n *\n * @returns {number} numeric rank of the pinned topic in the range 1..N (N being the top,\n * N - the number of pinned topics) or 0 if not pinned.\n */\n pinnedTopicRank(topic) {\n // Unsupported for non-me topics.\n return 0;\n }\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, in response to received\n // {ctrl} after setMeta-sub, or as a handler for {pres what=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 if (!this._users[sub.user]) {\n // New subscription.\n this.subcnt++;\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 this.subcnt--;\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-2025 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// Array and Date objects are shallow-copied.\nexport function mergeObj(dst, src) {\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 dst;\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) && (prop != '_noForwarding')) {\n try {\n dst[prop] = mergeObj(dst[prop], src[prop]);\n } catch (err) {\n console.warn(\"Error merging property:\", prop, err);\n }\n }\n }\n return dst;\n}\n\n// Update object stored in a cache. Returns updated value.\nexport function mergeToCache(cache, key, newval) {\n cache[key] = mergeObj(cache[key], newval);\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.25.0-beta1\";\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","DRAFTY_MIME_TYPE","DRAFTY_FR_MIME_TYPE","DRAFTY_FR_MIME_TYPE_LEGACY","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","isFormResponseType","isProcessing","getPreviewUrl","getEntitySize","getEntityMimeType","tagName","attrValue","getContentType","mimeType","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","pinTopic","pin","isCommTopicName","tpin","unshift","pinnedTopicRank","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","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","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","subcnt","_allMessagesReceived","cached","date","isNaN","isValidDate","d","getTime","rfc3339DateString","pad","sp","repeat","millis","getUTCMilliseconds","getUTCFullYear","getUTCMonth","getUTCDate","getUTCHours","getUTCMinutes","getUTCSeconds","prop","console","warn","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","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 fe4990c8..4e37fc63 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="text/x-drafty-fr",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,t){if(!e)return null;if(e.att)e.text=" ",delete e.att,delete e.children;else if(e.children){const s=[],i=[];for(let n in e.children){const r=e.children[n];if(r.att){if(s.length==t)continue;if(l.isFormResponseType(r.data.mime))continue;delete r.att,delete r.children,r.text=" ",s.push(r)}else i.push(r)}e.children=i.concat(s)}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 t=null;return!l.isFormResponseType(e.mime)&&e.val?t=h(e.val,e.mime,l.logger):"string"==typeof e.ref&&(t=e.ref),t},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"},l.isFormResponseType=function(e){return e===t||"application/json"===e},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 R{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 R.#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){R.#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(R.#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);R.#t("LP connecting to:",n),t=i(n,e,s),t.send(null)}).catch(e=>{R.#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);R.#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}R.NETWORK_ERROR=503,R.NETWORK_ERROR_TEXT=P,R.NETWORK_USER=A,R.NETWORK_USER_TEXT=D;const N="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(N,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(N);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 F 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(F.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 B 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")}}}),R.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"),R.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 R(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 B:t.name==d?new F:new z(t.name),this._db.deserializeTopic(s,t),this.#R(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.#N("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,R.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}`)}}#N(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}#R(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.#N("user",e,w({},t.public))},e._cacheDelUser=e=>{this.#j("user",e)},e._cachePutSelf=t=>{this.#N("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,R.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 B:e==d?new F:new z(e),this.#R(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="text/x-drafty-fr",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>E(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=E(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=E(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=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 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=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 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,t){if(!e)return null;if(e.att)e.text=" ",delete e.att,delete e.children;else if(e.children){const s=[],i=[];for(let n in e.children){const r=e.children[n];if(r.att){if(s.length==t)continue;if(l.isFormResponseType(r.data.mime))continue;delete r.att,delete r.children,r.text=" ",s.push(r)}else i.push(r)}e.children=i.concat(s)}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=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},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:E(i.txt).length,tp:"QQ"}),i},l.mention=function(e,t){return{txt:e||"",fmt:[{at:0,len:E(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 t=null;return!l.isFormResponseType(e.mime)&&e.val?t=h(e.val,e.mime,l.logger):"string"==typeof e.ref&&(t=e.ref),t},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"},l.isFormResponseType=function(e){return e===t||"application/json"===e},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){if("object"!=typeof t){if(void 0===t)return e;if(t===p)return;return t}if(null===t)return e;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,E="Disconnected by client";function D(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 R{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 R.#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){R.#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(R.#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?E: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=D(this.host,this.secure?"https":"http",this.version,this.apiKey);R.#t("LP connecting to:",n),t=i(n,e,s),t.send(null)}).catch(e=>{R.#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(E,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=D(this.host,this.secure?"wss":"ws",this.version,this.apiKey);R.#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?E: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}R.NETWORK_ERROR=503,R.NETWORK_ERROR_TEXT=P,R.NETWORK_USER=A,R.NETWORK_USER_TEXT=E;const N="tinode-web";let k;class I{#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=k.open(N,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=k.deleteDatabase(N);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(I.#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){I.#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(I.#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(I.#_(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(I.#_(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){I.#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 I.#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){k=e}}var C=s(767),q=s.n(C);let O,U,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 O;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 O;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){O=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()}pinTopic(e,t){return Promise.reject(new Error("Pinning topics is not supported here"))}pinnedTopicRank(e){return 0}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 F 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(F.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 B 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}pinTopic(e,t){if(!this._attached)return Promise.reject(new Error("Cannot pin topic in inactive 'me' topic"));if(!z.isCommTopicName(e))return Promise.reject(new Error("Invalid topic to pin"));const s=Array.isArray(this.private&&this.private.tpin)?this.private.tpin:[],i=s.includes(e);return t&&i||!t&&!i?Promise.resolve(s):(t?s.unshift(e):s.splice(s.indexOf(e),1),this.setMeta({desc:{private:{tpin:s.length>0?s:p}}}))}pinnedTopicRank(e){if(!this.private||!this.private.tpin)return 0;const t=this.private.tpin.indexOf(e);return t<0?0:this.private.tpin.length-t}}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&&(U=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:U,XMLHttpRequest:j,indexedDB:L,URL:{createObjectURL:function(){throw new Error("Unable to use URL.createObjectURL in a non-browser application")}}}),R.setNetworkProviders(U,j),V.setNetworkProvider(j),I.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"),R.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 R(e,"0",!0),this._connection.onMessage=e=>{this.#P(e)},this._connection.onOpen=e=>this.#A(),this._connection.onDisconnect=(e,t)=>this.#E(e,t),this._connection.onAutoreconnectIteration=(e,t)=>{this.onAutoreconnectIteration&&this.onAutoreconnectIteration(e,t)},this._persist=e.persist,this._db=new I(this.logger,this.logger),this._persist){const e=[];this._db.initDatabase().then(t=>this._db.mapTopics(t=>{let s=this.#D("topic",t.name);s||(s=t.name==c?new B:t.name==d?new F:new z(t.name),this._db.deserializeTopic(s,t),this.#R(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.#N("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(" "))}}#k(e){let t=null;return e&&(t=new Promise((t,s)=>{this._pendingPromises[e]={resolve:t,reject:s,ts:new Date}})),t}#I(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.#k(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.#I(t,R.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.#I(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.#D("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.#D("topic",t.ctrl.topic);e&&e._allMessagesReceived(t.ctrl.params.count)}else if("sub"==t.ctrl.params.what){const e=this.#D("topic",t.ctrl.topic);e&&e._processMetaSubs([])}},0)):setTimeout(e=>{if(t.meta){const e=this.#D("topic",t.meta.topic);e&&e._routeMeta(t.meta),t.meta.id&&this.#I(t.meta.id,200,t.meta,"META"),this.onMetaMessage&&this.onMetaMessage(t.meta)}else if(t.data){const e=this.#D("topic",t.data.topic);e&&e._routeData(t.data),this.onDataMessage&&this.onDataMessage(t.data)}else if(t.pres){const e=this.#D("topic",t.pres.topic);e&&e._routePres(t.pres),this.onPresMessage&&this.onPresMessage(t.pres)}else if(t.info){const e=this.#D("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)}#O(){return this._appName+" ("+(this._browser?this._browser+"; ":"")+this._hwos+"); "+a}#U(e,t){switch(e){case"hi":return{hi:{id:this.getNextUniqueId(),ver:r,ua:this.#O(),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}`)}}#N(e,t,s){this._cache[e+":"+t]=s}#D(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}#R(e){e._tinode=this,e._cacheGetUser=e=>{const t=this.#D("user",e);if(t)return{user:e,public:w({},t)}},e._cachePutUser=(e,t)=>{this.#N("user",e,w({},t.public))},e._cacheDelUser=e=>{this.#j("user",e)},e._cachePutSelf=t=>{this.#N("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){U=e,j=t,R.setNetworkProviders(U,j),V.setNetworkProvider(j)}static setDatabaseProvider(e){L=e,I.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.#U("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.#U("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.#U("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.#U("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.#U("leave",e);return s.leave.unsub=t,this.#C(s,s.leave.id)}createMessage(e,t,s){const i=this.#U("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.#D("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.#U("get",e);return s.get=w(s.get,t),this.#C(s,s.get.id)}setMeta(e,t){const s=this.#U("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.#U("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.#U("del",e);return s.del.what="topic",s.del.hard=t,this.#C(s,s.del.id)}delSubscription(e,t){const s=this.#U("del",e);return s.del.what="sub",s.del.user=t,this.#C(s,s.del.id)}delCredential(e,t){const s=this.#U("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.#U("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.#U("note",e);i.note.what=t,i.note.seq=s,this.#C(i)}noteKeyPress(e,t){const s=this.#U("note",e);s.note.what=t||"kp",this.#C(s)}videoCall(e,t,s,i){const n=this.#U("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.#D("topic",e);return!t&&e&&(t=e==c?new B:e==d?new F:new z(e),this.#R(t),t._cachePutSelf()),t}cacheGetTopic(e){return this.#D("topic",e)}cacheRemTopic(e){this.#j("topic",e)}mapTopics(e,t){this.#q("topic",e,t)}isTopicCached(e){return!!this.#D("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.#D("topic",e);return t&&t.online}getTopicAccessMode(e){const t=this.#D("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 312a775f..07321375 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 DRAFTY_MIME_TYPE = 'text/x-drafty';\n// Drafty form-response MIME type.\nconst DRAFTY_FR_MIME_TYPE = 'text/x-drafty-fr';\n// Legacy Drafty form-response MIME type.\nconst DRAFTY_FR_MIME_TYPE_LEGACY = 'application/json'; // Remove in 2026.\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: DRAFTY_FR_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 (!Drafty.isFormResponseType(entData.mime) && 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 * Check if the given mime-type is a MIME type of drafty form response.\n * @memberof Drafty\n * @static\n *\n * @returns {boolean} true if given mime type is drafty form response, false otherwise.\n */\nDrafty.isFormResponseType = function(mimeType) {\n return mimeType === DRAFTY_FR_MIME_TYPE ||\n mimeType === DRAFTY_FR_MIME_TYPE_LEGACY;\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 (Drafty.isFormResponseType(c.data['mime'])) {\n // Form response 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.4\";\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","DRAFTY_FR_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","isFormResponseType","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","mimeType","__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 DRAFTY_MIME_TYPE = 'text/x-drafty';\n// Drafty form-response MIME type.\nconst DRAFTY_FR_MIME_TYPE = 'text/x-drafty-fr';\n// Legacy Drafty form-response MIME type.\nconst DRAFTY_FR_MIME_TYPE_LEGACY = 'application/json'; // Remove in 2026.\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: DRAFTY_FR_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 (!Drafty.isFormResponseType(entData.mime) && 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 * Check if the given mime-type is a MIME type of drafty form response.\n * @memberof Drafty\n * @static\n *\n * @returns {boolean} true if given mime type is drafty form response, false otherwise.\n */\nDrafty.isFormResponseType = function(mimeType) {\n return mimeType === DRAFTY_FR_MIME_TYPE ||\n mimeType === DRAFTY_FR_MIME_TYPE_LEGACY;\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 (Drafty.isFormResponseType(c.data['mime'])) {\n // Form response 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.25.0-beta1\";\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-2025 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// Array and Date objects are shallow-copied.\nexport function mergeObj(dst, src) {\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 dst;\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) && (prop != '_noForwarding')) {\n try {\n dst[prop] = mergeObj(dst[prop], src[prop]);\n } catch (err) {\n console.warn(\"Error merging property:\", prop, err);\n }\n }\n }\n return dst;\n}\n\n// Update object stored in a cache. Returns updated value.\nexport function mergeToCache(cache, key, newval) {\n cache[key] = mergeObj(cache[key], newval);\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} callbacks.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 /**\n * Pin topic to the top of the contact list.\n * @memberof Tinode.TopicMe#\n *\n * @param {string} topic - Name of the topic to pin.\n * @param {boolean} [pin=false] - If true, pin the topic, otherwise unpin.\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n pinTopic(topic, pin) {\n // Unsupported operation for non-me topics.\n return Promise.reject(new Error(\"Pinning topics is not supported here\"));\n }\n\n /**\n * Get the rank of the pinned topic.\n * @memberof Tinode.TopicMe#\n * @param {string} topic - Name of the topic to check.\n *\n * @returns {number} numeric rank of the pinned topic in the range 1..N (N being the top,\n * N - the number of pinned topics) or 0 if not pinned.\n */\n pinnedTopicRank(topic) {\n // Unsupported for non-me topics.\n return 0;\n }\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, in response to received\n // {ctrl} after setMeta-sub, or as a handler for {pres what=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 if (!this._users[sub.user]) {\n // New subscription.\n this.subcnt++;\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 this.subcnt--;\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-2025 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 * Pin topic to the top of the contact list.\n * @memberof Tinode.TopicMe#\n *\n * @param {string} topic - Name of the topic to pin.\n * @param {boolean} [pin=false] - If true, pin the topic, otherwise unpin.\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n pinTopic(topic, pin) {\n if (!this._attached) {\n return Promise.reject(new Error(\"Cannot pin topic in inactive 'me' topic\"));\n }\n if (!Topic.isCommTopicName(topic)) {\n return Promise.reject(new Error(\"Invalid topic to pin\"));\n }\n\n const tpin = Array.isArray(this.private && this.private.tpin) ? this.private.tpin : [];\n const found = tpin.includes(topic);\n if ((pin && found) || (!pin && !found)) {\n // Nothing to do.\n return Promise.resolve(tpin);\n }\n\n if (pin) {\n // Add topic to the top of the pinned list.\n tpin.unshift(topic);\n } else {\n // Remove topic from the pinned list.\n tpin.splice(tpin.indexOf(topic), 1);\n }\n\n return this.setMeta({\n desc: {\n private: {\n tpin: tpin.length > 0 ? tpin : Const.DEL_CHAR\n }\n }\n });\n }\n\n /**\n * Get the rank of the pinned topic.\n * @memberof Tinode.TopicMe#\n * @param {string} topic - Name of the topic to check.\n *\n * @returns {number} numeric rank of the pinned topic in the range 1..N (N being the top,\n * N - the number of pinned topics) or 0 if not pinned.\n */\n pinnedTopicRank(topic) {\n if (!this.private || !this.private.tpin) {\n return 0;\n }\n const idx = this.private.tpin.indexOf(topic);\n return idx < 0 ? 0 : this.private.tpin.length - idx;\n }\n}\n"],"names":["root","factory","exports","module","define","amd","this","DRAFTY_FR_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","isFormResponseType","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","mimeType","__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","console","warn","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","pinTopic","pinnedTopicRank","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","subcnt","_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","tpin","unshift","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","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
diff --git a/web-desktop.jpg b/web-desktop.jpg
index 170a92ee..73d6fed8 100644
Binary files a/web-desktop.jpg and b/web-desktop.jpg differ
diff --git a/web-mob-avatar.png b/web-mob-avatar.png
deleted file mode 100644
index dc37f245..00000000
Binary files a/web-mob-avatar.png and /dev/null differ
diff --git a/web-mob-chat-dark.png b/web-mob-chat-dark.png
new file mode 100644
index 00000000..51a8d092
Binary files /dev/null and b/web-mob-chat-dark.png differ
diff --git a/web-mob-chat.png b/web-mob-chat.png
index 815b8de2..37b907b5 100644
Binary files a/web-mob-chat.png and b/web-mob-chat.png differ
diff --git a/web-mob-contacts.png b/web-mob-contacts.png
index d7e46e67..1ffdc4b8 100644
Binary files a/web-mob-contacts.png and b/web-mob-contacts.png differ
diff --git a/web-mob-forward.png b/web-mob-forward.png
index 25febede..5405690d 100644
Binary files a/web-mob-forward.png and b/web-mob-forward.png differ
diff --git a/web-mob-info.png b/web-mob-info.png
index 6cfb467e..9b080742 100644
Binary files a/web-mob-info.png and b/web-mob-info.png differ
diff --git a/web-mob-video-call.png b/web-mob-video-call.png
index 08c8a14a..77be4407 100644
Binary files a/web-mob-video-call.png and b/web-mob-video-call.png differ