Full Code of tinode/webapp for AI

master ac779ef31bc4 cached
256 files
6.2 MB
1.6M tokens
5326 symbols
1 requests
Download .txt
Showing preview only (6,811K chars total). Download the full file or copy to clipboard to get everything.
Repository: tinode/webapp
Branch: master
Commit: ac779ef31bc4
Files: 256
Total size: 6.2 MB

Directory structure:
gitextract_okuamhsj/

├── .babelrc
├── .gitattributes
├── .github/
│   └── ISSUE_TEMPLATE/
│       ├── bug_report.md
│       └── feature_request.md
├── .gitignore
├── .well-known/
│   └── assetlinks.json
├── LICENSE
├── README.md
├── audio/
│   ├── call-end.m4a
│   ├── call-in.m4a
│   ├── call-out.m4a
│   ├── dialing.m4a
│   └── msg.m4a
├── css/
│   └── base.css
├── firebase-init.js
├── img/
│   └── bkg/
│       └── index.json
├── index-dev.html
├── index.html
├── manifest.json
├── package.json
├── postcss.config.js
├── push.md
├── scripts/
│   ├── gen-version.js
│   └── i18n.js
├── service-worker.js
├── src/
│   ├── config.js
│   ├── constants.js
│   ├── dcodes.json
│   ├── i18n/
│   │   ├── ar.json
│   │   ├── de.json
│   │   ├── en.json
│   │   ├── es.json
│   │   ├── ex/
│   │   │   └── base-en.json
│   │   ├── fr.json
│   │   ├── it.json
│   │   ├── ko.json
│   │   ├── ro.json
│   │   ├── ru.json
│   │   ├── th.json
│   │   ├── uk.json
│   │   ├── vi.json
│   │   ├── zh-TW.json
│   │   └── zh.json
│   ├── i18n.min/
│   │   ├── ar.json
│   │   ├── de.json
│   │   ├── en.json
│   │   ├── es.json
│   │   ├── fr.json
│   │   ├── it.json
│   │   ├── ko.json
│   │   ├── ro.json
│   │   ├── ru.json
│   │   ├── th.json
│   │   ├── uk.json
│   │   ├── vi.json
│   │   ├── zh-TW.json
│   │   └── zh.json
│   ├── index.js
│   ├── lib/
│   │   ├── blob-helpers.js
│   │   ├── formatters.js
│   │   ├── host-name.js
│   │   ├── local-storage.js
│   │   ├── navigation.js
│   │   ├── strformat.js
│   │   ├── strformat.test.js
│   │   ├── utils.js
│   │   └── utils.test.js
│   ├── version.js
│   ├── views/
│   │   ├── acc-general-view.jsx
│   │   ├── acc-notifications-view.jsx
│   │   ├── acc-security-view.jsx
│   │   ├── acc-support-view.jsx
│   │   ├── account-settings-view.jsx
│   │   ├── contacts-view.jsx
│   │   ├── create-account-view.jsx
│   │   ├── info-view.jsx
│   │   ├── login-view.jsx
│   │   ├── logo-view.jsx
│   │   ├── messages-view.jsx
│   │   ├── new-topic-view.jsx
│   │   ├── password-reset-view.jsx
│   │   ├── settings-view.jsx
│   │   ├── sidepanel-view.jsx
│   │   ├── tinode-web.jsx
│   │   ├── topic-common-view.jsx
│   │   ├── validation-view.jsx
│   │   └── wallpapers.jsx
│   └── widgets/
│       ├── alert.jsx
│       ├── attachment.jsx
│       ├── audio-player.jsx
│       ├── audio-recorder.jsx
│       ├── avatar-crop.jsx
│       ├── avatar-upload.jsx
│       ├── badge-list.jsx
│       ├── button-back.jsx
│       ├── call-incoming.jsx
│       ├── call-message.jsx
│       ├── call-panel.jsx
│       ├── call-status.jsx
│       ├── chat-message.jsx
│       ├── checkbox.jsx
│       ├── chip-input.jsx
│       ├── chip.jsx
│       ├── contact-action.jsx
│       ├── contact-badges.jsx
│       ├── contact-list.jsx
│       ├── contact.jsx
│       ├── context-menu.jsx
│       ├── credential-edit.jsx
│       ├── cropper.jsx
│       ├── doc-preview.jsx
│       ├── error-panel.jsx
│       ├── file-progress.jsx
│       ├── forward-dialog.jsx
│       ├── group-manager.jsx
│       ├── group-subs.jsx
│       ├── host-selector.jsx
│       ├── image-preview.jsx
│       ├── in-place-edit.jsx
│       ├── inline-video.jsx
│       ├── invitation.jsx
│       ├── lazy-image.jsx
│       ├── letter-tile.jsx
│       ├── load-spinner.jsx
│       ├── menu-cancel.jsx
│       ├── menu-contacts.jsx
│       ├── menu-start.jsx
│       ├── meta-message.jsx
│       ├── new-topic-by-id.jsx
│       ├── new-topic-group.jsx
│       ├── permissions-editor.jsx
│       ├── phone-country-selector.jsx
│       ├── phone-edit.jsx
│       ├── pinned-messages.jsx
│       ├── received-marker.jsx
│       ├── search-contacts.jsx
│       ├── send-message.jsx
│       ├── show-qrcode.jsx
│       ├── side-navbar.jsx
│       ├── tag-manager.jsx
│       ├── the-card-mini.jsx
│       ├── the-card-preview.jsx
│       ├── topic-desc-edit.jsx
│       ├── topic-security.jsx
│       ├── unread-badge.jsx
│       ├── uploading-image.jsx
│       ├── video-preview.jsx
│       └── visible-password.jsx
├── umd/
│   ├── 0.prod.js
│   ├── 107.prod.js
│   ├── 128.prod.js
│   ├── 140.prod.js
│   ├── 143.prod.js
│   ├── 175.prod.js
│   ├── 178.prod.js
│   ├── 186.prod.js
│   ├── 187.prod.js
│   ├── 197.prod.js
│   ├── 203.prod.js
│   ├── 226.prod.js
│   ├── 246.prod.js
│   ├── 252.prod.js
│   ├── 264.prod.js
│   ├── 271.prod.js
│   ├── 290.prod.js
│   ├── 297.prod.js
│   ├── 311.prod.js
│   ├── 316.prod.js
│   ├── 327.prod.js
│   ├── 330.prod.js
│   ├── 336.prod.js
│   ├── 352.prod.js
│   ├── 365.prod.js
│   ├── 371.prod.js
│   ├── 372.prod.js
│   ├── 399.prod.js
│   ├── 429.prod.js
│   ├── 440.prod.js
│   ├── 472.prod.js
│   ├── 500.prod.js
│   ├── 501.prod.js
│   ├── 514.prod.js
│   ├── 536.prod.js
│   ├── 537.prod.js
│   ├── 552.prod.js
│   ├── 553.prod.js
│   ├── 564.prod.js
│   ├── 570.prod.js
│   ├── 632.prod.js
│   ├── 634.prod.js
│   ├── 64.prod.js
│   ├── 648.prod.js
│   ├── 688.prod.js
│   ├── 700.prod.js
│   ├── 734.prod.js
│   ├── 744.prod.js
│   ├── 747.prod.js
│   ├── 752.prod.js
│   ├── 780.prod.js
│   ├── 817.prod.js
│   ├── 827.prod.js
│   ├── 836.prod.js
│   ├── 844.prod.js
│   ├── 864.prod.js
│   ├── 868.prod.js
│   ├── 884.prod.js
│   ├── 889.prod.js
│   ├── 892.prod.js
│   ├── 898.prod.js
│   ├── 92.prod.js
│   ├── 932.prod.js
│   ├── 936.prod.js
│   ├── 942.prod.js
│   ├── 952.prod.js
│   ├── 961.prod.js
│   ├── 978.prod.js
│   ├── 993.prod.js
│   ├── 996.prod.js
│   ├── index.dev.js
│   ├── index.prod.js
│   ├── src_i18n_min_ar_json.dev.js
│   ├── src_i18n_min_de_json.dev.js
│   ├── src_i18n_min_en_json.dev.js
│   ├── src_i18n_min_es_json.dev.js
│   ├── src_i18n_min_fr_json.dev.js
│   ├── src_i18n_min_it_json.dev.js
│   ├── src_i18n_min_ko_json.dev.js
│   ├── src_i18n_min_ro_json.dev.js
│   ├── src_i18n_min_ru_json.dev.js
│   ├── src_i18n_min_th_json.dev.js
│   ├── src_i18n_min_uk_json.dev.js
│   ├── src_i18n_min_vi_json.dev.js
│   ├── src_i18n_min_zh-TW_json.dev.js
│   ├── src_i18n_min_zh_json.dev.js
│   ├── src_views_acc-security-view_jsx.dev.js
│   ├── src_views_account-settings-view_jsx.dev.js
│   ├── src_views_create-account-view_jsx.dev.js
│   ├── src_views_info-view_jsx.dev.js
│   ├── src_views_messages-view_jsx.dev.js
│   ├── src_views_password-reset-view_jsx.dev.js
│   ├── src_views_wallpapers_jsx.dev.js
│   ├── src_widgets_audio-recorder_jsx.dev.js
│   ├── src_widgets_call-panel_jsx.dev.js
│   ├── src_widgets_doc-preview_jsx.dev.js
│   ├── src_widgets_image-preview_jsx.dev.js
│   ├── src_widgets_phone-country-selector_jsx.dev.js
│   ├── src_widgets_the-card-preview_jsx.dev.js
│   ├── src_widgets_video-preview_jsx.dev.js
│   ├── tinode.dev.js
│   ├── tinode.prod.js
│   ├── vendors-node_modules_libphonenumber-js_examples_mobile_json_js-node_modules_libphonenumber-js-7e28c7.dev.js
│   ├── vendors-node_modules_libphonenumber-js_examples_mobile_json_js-node_modules_libphonenumber-js-883e54.dev.js
│   ├── vendors-node_modules_libphonenumber-js_mobile_exports_parsePhoneNumberWithError_js.dev.js
│   └── vendors-node_modules_webm-duration-fix_lib_index_js.dev.js
├── version.js
└── webpack.config.js

================================================
FILE CONTENTS
================================================

================================================
FILE: .babelrc
================================================
{
  "presets": ["@babel/preset-react", "@babel/preset-env"],
  "comments": false,
  "plugins": [
    [
      "formatjs",
      {
        "idInterpolationPattern": "[sha512:contenthash:base64:6]",
        "ast": true
      }
    ]
  ]
}


================================================
FILE: .gitattributes
================================================
umd/* binary
package-lock.json binary
*.min.css binary
src/i18n.min/* binary


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve TinodeWeb
title: ''
labels: bug
assignees: ''

---

If you want to ask a question, please post to https://groups.google.com/d/forum/tinode instead.
---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

**Expected behavior**
A clear and concise description of what you expected to happen.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Environment (please complete the following information):**
 - OS: [e.g. Mac OS, Windows 10 Home]
 - Browser [e.g. Chrome, Safari]
 - TinodeWeb Version [e.g. 0.16.6]

**Console log**
Please attach or insert console log which illustrates the problem. Please use the log produced by `index-dev.html`, not `index.html`; `index.html` uses minified javascript which produces unusable logs.

**Additional context**
Add any other context about the problem here.


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: feature request
assignees: ''

---

If you want to ask a question, please post to https://groups.google.com/d/forum/tinode instead.
---

**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
A clear and concise description of what you want to happen.

**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.

**Additional context**
Add any other context or screenshots about the feature request here.


================================================
FILE: .gitignore
================================================
.DS_Store
node_modules
src/i18n/srci/
webapp.code-workspace.code-workspace


================================================
FILE: .well-known/assetlinks.json
================================================
[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "co.tinode.tindroidx",
    "sha256_cert_fingerprints":
    ["25:9A:71:EE:BD:2E:9F:D3:2D:64:1E:90:49:33:BD:F3:E3:42:BD:C4:DD:FA:BA:68:EE:D2:EB:76:65:33:DC:92"]
  }
},
{
  "relation": ["delegate_permission/common.get_login_creds"],
  "target": {
    "namespace": "web",
    "site": "https://web.tinode.co"
  }
},
{
  "relation": ["delegate_permission/common.get_login_creds"],
  "target": {
    "namespace": "android_app",
    "package_name": "co.tinode.tindroidx",
    "sha256_cert_fingerprints":
    ["5B:BE:6A:C4:A7:66:A8:BB:4B:C1:52:66:E5:A4:BD:66:3C:33:50:04:11:CB:17:44:45:89:5E:3C:8D:55:77:7A"]
  }
}
]


================================================
FILE: LICENSE
================================================
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.


================================================
FILE: README.md
================================================
# Tinode Web

## Briefing

Single-page web chat application for [Tinode](https://github.com/tinode/chat/). The app is built on
[React](https://reactjs.org/). The [Tinode javascript SDK](https://github.com/tinode/tinode-js/) has no external dependencies.
Overall, it's a lot like open source WhatsApp or Telegram web apps.

Although the app is generally usable, keep in mind that this is work in progress. Some bugs probably exist, some features are missing. The app was tested in the latest Chrome & Firefox only. NPM package is [available](https://www.npmjs.com/package/tinode-webapp).

Try possibly newer or older version live at https://sandbox.tinode.co/.

<a href="https://web.tinode.co/"><img src="web-app.svg" height=36></a>

For demo access and other instructions [see here](https://github.com/tinode/chat/#demosandbox).

## Installing and running

This is _NOT_ a standalone app, this is just a frontend, a client. It requires a [backend](https://github.com/tinode/chat/). See [installation instructions](https://github.com/tinode/chat/blob/master/INSTALL.md). See instructions for [enabling push notifications](push.md).

## Getting support

* Read [client-side](http://tinode.github.io/js-api/) and [server-side](https://github.com/tinode/chat/blob/master/docs/API.md) API documentation.
* For support, general questions, discussions post to [https://groups.google.com/d/forum/tinode](https://groups.google.com/d/forum/tinode).
* For bugs and feature requests [open an issue](https://github.com/tinode/webchat/issues/new).
* Use https://tinode.co/contact for commercial inquiries.

## Helping out

* If you appreciate our work, please help spread the word! Sharing on Reddit, HN, and other communities helps more than you think.
* Consider buying paid support: https://tinode.co/support.html
* If you are a software developer, send us your pull requests with bug fixes and new features.
* If you use the app and discover bugs or missing features, let us know by filing bug reports and feature requests. Vote for existing [feature requests](https://github.com/tinode/chat/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc+label%3A%22feature+request%22) you find most valuable.
* If you speak a language other than English, [translate](https://github.com/tinode/chat/blob/devel/docs/translations.md#webapp) the apps into your language. You may also review and improve existing translations.
* If you are a UI/UX expert, help us polish the app UI.
* Use it: install it for your colleagues or friends at work or at home.

## Internationalization

The app is fully internationalized using [React-Intl](https://github.com/formatjs/react-intl). The UI language is selected automatically from the language specified by the browser. A specific language can be forced by adding `#?hl=XX` parameter to the URL when starting the app, e.g. https://web.tinode.co/#?hl=fr.

The app is currently available in the following languages:
 * English - default
 * Arabic
 * Chinese simplified
 * Chinese traditional
 * French
 * German
 * Italian
 * Korean
 * Romanian
 * Russian
 * Spanish
 * Thai
 * Ukrainian
 * Vietnamese

More translations are welcome. See [instructions](https://github.com/tinode/chat/blob/devel/docs/translations.md#webapp).


## Not done yet

* End-to-End encryption.
* Emoji support is weak.
* Mentions, hashtags.
* Previews not generated for links and docs.
* Location and contact sharing.
* Recording video messages.

## Other

* Demo avatars and some other graphics are from https://www.pexels.com/ under [CC0 license](https://www.pexels.com/photo-license/).
* Background patterns from http://subtlepatterns.com/, commercial and non-commercial use allowed with attribution.
* [Fonts](https://fonts.google.com/) and [icons](https://google.github.io/material-design-icons/#icon-font-for-the-web) from Google under [license](https://developers.google.com/terms) which permits commercial and non-commercial use.
* Push notifications built with https://firebase.google.com/.

## Responsive design

### Desktop screenshot

<p align="center">
  <img src="web-desktop.jpg" alt="Desktop web: full app" width=810 />
</p>

### Mobile screenshots

<p align="center">
  <kbd><img src="web-mob-contacts.png" alt="Mobile web: contacts" width=250 /></kbd> <kbd><img src="web-mob-chat.png" alt="Mobile web: chat" width=250 /></kbd> <kbd><img src="web-mob-chat-dark.png" alt="Mobile web: chat dark mode" width=250 /></kbd> <kbd><img src="web-mob-info.png" alt="Mobile web: topic info" width=250 /></kbd> <kbd><img src="web-mob-forward.png" alt="Mobile web: forward message" width=250 /></kbd> <kbd><img src="web-mob-video-call.png" alt="Mobile web: video call" width=250 /></kbd>
</p>


================================================
FILE: css/base.css
================================================
:root {
  color-scheme: light dark;

  /* Size of text in message bubbles */
  --message-text-size: 10pt;

  /* Height of caption panel */
  --caption-panel-height: 4rem;

  /* Wallpaper */
  --wallpaper-url: url('../img/bkg/a00.png'); /* path relative to CSS file */
  --wallpaper-repeat: repeat;
  --wallpaper-blur: 0px;
  --wallpaper-invert: 0;
  --wallpaper-brightness: 1;
  --wallpaper-size: contain;
  --wallpaper-position: center;


  /* Core Palette */
  --clr-bright: light-dark(#fff, #181818);
  --clr-dark: light-dark(#000, #fff);
  --clr-transparent: transparent;
  --clr-std-gray: #808080; /* Standard gray color */
  --clr-std-ltgray: light-dark(#c0c0c0, #3f3f3f); /* Standard silver color */
  --clr-std-teal: teal; /* Standard teal color */
  --clr-std-grey: grey; /* Standard grey color */
  --clr-std-orange: #ffa500; /* Standard orange color */

  /* Primary Accent Colors */
  --clr-primary-accent: light-dark(#2094f3, #0e6dba); /* blue 500, links, borders */
  --clr-primary-accent-hover: light-dark(#0a6ebd, #116ab4); /* hover for primary accent */
  --clr-primary-accent-focus-shadow: light-dark(rgba(33, 150, 243, 0.25), rgba(3, 7, 12, 0.25)); /* focus shadow for inputs with primary accent */
  --clr-primary-accent-transparent-medium: light-dark(rgba(33, 150, 243, 0.3), rgba(20, 70, 120, 0.3)); /* for active call shadow */
  --clr-primary-action: light-dark(#1e89e6, #1571c1); /* blue 600, primary buttons */
  --clr-primary-action-hover: light-dark(#2962ff, #0037b8); /* hover for primary action */
  --clr-secondary-accent: light-dark(#0097a8, #006570); /* Checkmark icon, unread badge bg */
  --clr-primary-light-blue: light-dark(#bcdefb, #78a0be); /* light-blue 100, side caption panel text/link */
  --clr-light-blue-accent: light-dark(#0398e2, #0379b5); /* light-blue accent, reply quote border, pinned active dot */

  /* Secondary/Neutral Grays & Backgrounds */
  --clr-body-background: var(--clr-std-ltgray); /* Main page background */
  --clr-text-primary: light-dark(#666, #999); /* Default text color */
  --clr-text-secondary: light-dark(#757575, #8a8a8a); /* Muted text, icons e.g. menu trigger */
  --clr-text-tertiary: light-dark(#999, #787878); /* Even more muted text, borders, some icons */
  --clr-text-tertiary-activated: #888; /* Activated (hover, focus) tertiary text */
  --clr-text-placeholder: light-dark(#bbb, #555); /* Placeholder text */
  --clr-text-disabled: light-dark(#888, #777); /* Disabled text e.g. in-place-edit */
  --clr-border-light: light-dark(#ccc, #555); /* Common light border, separator */
  --clr-border-muted: light-dark(#ddd, #444); /* Softer border, e.g. in-place-edit dashed */
  --clr-background-off-white: light-dark(#fafafa, #222); /* Common very light background */
  --clr-background-light-gray: light-dark(#f0f0f0, #0f0f0f); /* HR background, action button hover */
  --clr-background-extra-light-gray: light-dark(#eee, #222); /* Flat button faux bg, tabbar bg, chip bg */
  --clr-background-blue-gray-50: light-dark(#edf0f2, #202c33); /* Contact hover, messages panel, send message panel */
  --clr-background-blue-gray-75: light-dark(#e1e8eb, #182124); /* Contact pinned */
  --clr-background-blue-gray-100: light-dark(#cfd8dc, #20272a); /* Contact selected, uploader bar */
  --clr-background-blue-gray-300: light-dark(#b0bec5, #354146); /* Topic/Info caption panel bg, some lettertiles */
  --clr-blue-wash-light: light-dark(#f0f0ff, #22222d); /* bot form button bg */
  --clr-blue-wash-medium: light-dark(#d8e8ff, #123550); /* Pinned active bg */
  --clr-primary-wash: light-dark(#e3f2fd, #072f45); /* Secondary button hover, avatar upload hover, bubble meta deleted bg */
  --clr-indigo-50: light-dark(#e8eaf6, #1a2c44); /* Outline button hover */

  /* Semantic Colors: Danger, Warning, Success, Info */
  --clr-danger-text: light-dark(#d33131, #931f1f); /* Danger text, invalid label */
  --clr-danger-text-hover: light-dark(#f44034, #cc1100); /* Hover for danger text */
  --clr-error-text-muted: light-dark(#cc6666, #993333); /* For less critical errors like invalid in-place edit icon/text */
  --clr-error-bg-light: light-dark(#ffccd1, #ff6675); /* Info box error bg */
  --clr-error-border-light: light-dark(#ffbdc6, #ff334e); /* Info box error border */
  --clr-error-text-dark: light-dark(#b51c1c, #de2323); /* Info box error text, icon */
  --clr-error-icon: light-dark(#ef5552, #d81b0e); /* Info box error icon specific */
  --clr-warning-accent: light-dark(#FFC107, #808020); /* Amber, danger-color */
  --clr-warning-bg-light: light-dark(#fff9c4, #00060c); /* Info box warning bg */
  --clr-warning-border-light: light-dark(#fff59d, #000a2b); /* Info box warning border */
  --clr-warning-text-dark: light-dark(#6d4c41, #a08356); /* Info box warning text */
  --clr-warning-icon: light-dark(#fbc02d, #b48204); /* Info box warning icon specific */
  --clr-info-bg-light: light-dark(#e1f5fe, #010a0e); /* Info box info bg */
  --clr-info-border-light: light-dark(#b3e5fc, #001824); /* Info box info border */
  --clr-info-text-dark: light-dark(#0288d1, #00151f); /* Info box info text, icon */

  /* Special UI Elements Colors */
  --clr-header-stripe-bg: light-dark(#3949AB, #12152f); /* Deep-blue stripe at top */
  --clr-scrollbar-thumb: light-dark(rgba(0,0,0,0.3), rgba(255,255,255,0.3));
  --clr-scrollbar-track: light-dark(rgba(255,255,255,0.1), rgba(0,0,0,0.1));
  --clr-menu-item-hover-bg: light-dark(#f5f5f5, #0a0a0a);
  --clr-alert-overlay-bg: light-dark(rgba(240,240,240,0.85), rgba(15,15,15,0.85));
  --clr-verified-accent: light-dark(#02a6f2, #027db6); /* Verified color */
  --clr-staff-accent: light-dark(#689f38, #598830); /* Staff color */
  --clr-badge-inv: light-dark(#fffd, #cccd); /* Badge inverted text */
  --clr-cyan-50: light-dark(#e0f7fa, #2f3e43); /* Dummy view bg */
  --clr-overlay-white-strong: light-dark(rgba(255, 255, 255, 0.9), rgba(0,0,0,0.90)); /* Image preview bg, video container bg */
  --clr-gray-medium-bg: light-dark(#777, #444); /* Image preview container bg (darker gray) */
  --clr-toast-bg: #333;
  --clr-toast-text: light-dark(#eee, #aaa);
  --clr-online: #4caf50;
  --clr-offline: light-dark(#ccc, #999);

  /* Shadow Colors & Values */
  --clr-shadow-input-underline: rgba(0,0,0, 0.1);
  --clr-shadow-hr-inset: rgba(0,0,0,0.15);
  --clr-shadow-scrollbar-track-webkit: rgba(0,0,0,0.2);
  --clr-shadow-button: rgba(0,0,0, 0.25); /* General purpose shadow for buttons, spinners etc. */
  --clr-shadow-button-inset-active: rgba(0,0,0, 0.125);
  --clr-shadow-dialog: rgba(0,0,0, 0.45); /* For menus, alerts, dialogs */
  --clr-shadow-panel-divider: rgba(0,0,0,0.1); /* For subtle shadows under/above panels */
  --clr-shadow-gray-strong: light-dark(var(--clr-std-gray), #333); /* For panel box-shadows using 'gray' keyword */
  --clr-shadow-silver-subtle: light-dark(var(--clr-std-ltgray), #333); /* For panel box-shadows using 'silver' keyword */
  --clr-shadow-bubble-drop: rgba(0,0,0,0.3);

  /* Buttons */
  --clr-button-primary-bg: var(--clr-primary-action);
  --clr-button-primary-text: var(--clr-bright);
  --clr-button-primary-hover-bg: var(--clr-primary-action-hover);
  --clr-button-secondary-bg: var(--clr-bright);
  --clr-button-secondary-text: var(--clr-primary-accent);
  --clr-button-secondary-hover-bg: var(--clr-primary-wash);
  --clr-button-outline-text: var(--clr-primary-accent);
  --clr-button-outline-border: var(--clr-std-ltgray);
  --clr-button-outline-hover-bg: var(--clr-indigo-50);
  --clr-button-danger-bg: light-dark(#ec645f, #d74742);
  --clr-button-danger-text: var(--clr-bright);
  --clr-button-danger-hover-bg: light-dark(#f77, #a55);
  --clr-button-positive-bg: light-dark(#71c46f, #3f983e);
  --clr-button-positive-text: var(--clr-bright);
  --clr-button-positive-hover-bg: light-dark(#7fed7f, #6ec26e);

  /* Inputs */
  --clr-input-text: var(--clr-text-primary);
  --clr-input-border: var(--clr-border-light);
  --clr-input-border-focus: var(--clr-primary-accent);
  --clr-input-shadow: var(--clr-shadow-input-underline);
  --clr-input-shadow-focus: var(--clr-primary-accent-focus-shadow);
  --clr-input-invalid-border: light-dark(#e57171, #561010);
  --clr-input-invalid-shadow: light-dark(#e5737340, #1a0c0c40);
  --clr-input-placeholder-text: var(--clr-text-placeholder);

  /* Chat Bubbles */
  --clr-bubble-left-bg: light-dark(#c4e0a3, #3e5c1f);
  --clr-bubble-left-bg-flash: light-dark(#94a97c, #2c4517);
  --clr-bubble-right-bg: var(--clr-background-off-white);
  --clr-bubble-right-bg-flash: var(--clr-border-light);
  --clr-bubble-text: light-dark(#212121, #bbc);
  --clr-bubble-meta-text: var(--clr-text-primary);
  --clr-bubble-meta-deleted-bg: var(--clr-primary-wash);
  --clr-bubble-meta-date-bg: light-dark(rgba(255 255 255 / 80%), rgba(40 40 40 / 80%));
  --clr-bubble-timestamp-text: light-dark(#777, #888);
  --clr-bubble-author-text: light-dark(#777, #666);

  /* Reply Quotes */
  --clr-reply-quote-border: var(--clr-light-blue-accent);
  --clr-reply-quote-text: var(--clr-text-primary);
  --clr-reply-quote-left-bg: light-dark(rgba(255, 255, 255, 0.4), rgba(0, 0, 0, 0.4));
  --clr-reply-quote-right-bg: light-dark(#8080801f, #c4c4c42e);
  --clr-reply-quote-preview-bg: var(--clr-background-off-white);

  /* Badges (small inline labels) */
  --clr-badge-default-bg: light-dark(#e8e8e8, #171717);
  --clr-badge-default-text: var(--clr-text-primary);
  --clr-badge-default-border: var(--clr-std-ltgray);
  --clr-badge-green-bg: light-dark(#efe, #131);
  --clr-badge-green-text: light-dark(#383, #363);
  --clr-badge-green-border: light-dark(#aca, #242);
  --clr-badge-yellow-bg: light-dark(#ffe, #331); /* Note: #ffe is close to white, dark will be black */
  --clr-badge-yellow-text: light-dark(#660, #660);
  --clr-badge-yellow-border: light-dark(#cc9, #552);
  --clr-badge-blue-bg: light-dark(#f0f0ff, #224);
  --clr-badge-blue-text: light-dark(#339, #447);
  --clr-badge-blue-border: light-dark(#aad, #336);
  --clr-badge-red-bg: light-dark(#fee, #522);
  --clr-badge-red-text: light-dark(#933, #744);
  --clr-badge-red-border: light-dark(#c99, #633);
  --clr-badge-magenta-bg: light-dark(#fef, #535);
  --clr-badge-magenta-text: light-dark(#939, #747);
  --clr-badge-magenta-border: light-dark(#c9c, #636);

    /* Chips */
  --clr-chip-bg: var(--clr-background-extra-light-gray);
  --clr-chip-invalid-text: var(--clr-error-text-muted);
  --clr-chip-invalid-bg: var(--clr-badge-red-bg);
  --clr-chip-remove-icon-bg: light-dark(#aaa, #555);
  --clr-chip-remove-icon-text: var(--clr-background-extra-light-gray);
  --clr-chip-remove-icon-hover-bg: var(--clr-text-placeholder);
  --clr-chip-remove-icon-hover-text: var(--clr-bright);

    /* Tabbar */
  --clr-tabbar-bg: var(--clr-background-extra-light-gray);
  --clr-tabbar-inactive-text: light-dark(rgba(33,150,243,0.6), rgba(22,90,160,1));
  --clr-tabbar-active-text: var(--clr-primary-accent);
  --clr-tabbar-inactive-border: var(--clr-border-light);
  --clr-tabbar-active-border: var(--clr-primary-accent);

  /* Miscellaneous UI */
  --clr-highlight-text: var(--clr-std-teal);
  --clr-highlight-preview-text: light-dark(#5f9ea0, #205e60);
  --clr-spinner-track: light-dark(#f3f3f3, #0c0c0c);
  --clr-spinner-active: var(--clr-primary-action);
  --clr-cropper-bounding-box-border: var(--clr-primary-action);
  --clr-cropper-bounding-box-bg: var(--clr-text-tertiary);
  --clr-cropper-cutout-border: var(--clr-text-tertiary);
  --clr-cropper-cutout-shadow: light-dark(rgb(230 246 255 / 66%), rgb(25 10 0 / 66%));
  --clr-audio-bg: var(--clr-background-extra-light-gray);
  --clr-audio-icon: light-dark(rgba(102, 117, 117, 0.8), rgba(153, 138, 138, 0.8));
  --clr-audio-icon-disabled: light-dark(rgba(153  153  153 / 75%), rgba(102 102 102 / 75%));
  --clr-audio-timer-text: light-dark(rgba(102, 102, 102, 0.75), rgba(153, 153, 153, 0.75));
  --clr-pinned-menu-bg: light-dark(#f8f8f8, #1a1a1a);
  --clr-drag-n-drop-border: var(--clr-std-grey);
  --clr-drag-n-drop-text: var(--clr-std-grey);
  --clr-drag-n-drop-bg: light-dark(rgba(255,255,255,.95), rgba(0,0,0,.95));
  --clr-drag-n-drop-outline: light-dark(rgba(255,255,255,.95), rgba(0,0,0,.95));

  /* Letter Tiles Base */
  --clr-lettertile-default-text: light-dark(#fafafacc, #dcdcdccc);
  --clr-lettertile-hover-text: var(--clr-bright);

  /* Letter Tile Backgrounds (lt-bg) */
  --clr-lt-bg-0: #ef9a9a;
  --clr-lt-bg-1: #90caf9;
  --clr-lt-bg-2: #b0bec4;
  --clr-lt-bg-3: #b49edb;
  --clr-lt-bg-4: #ffa98f;
  --clr-lt-bg-5: #a4d5a6;
  --clr-lt-bg-6: #ededed;
  --clr-lt-bg-7: #e6ee9b;
  --clr-lt-bg-8: #c4e0a3;
  --clr-lt-bg-9: #f0e57f;
  --clr-lt-bg-10: #f490b1;
  --clr-lt-bg-11: #a0a8da;
  --clr-lt-bg-12: #ffdf80;
  --clr-lt-bg-13: #bcaaa4;
  --clr-lt-bg-14: #80deea;
  --clr-lt-bg-15: #cd92d8;

  /* Letter Tile Dark Backgrounds (dk-bg) */
  --clr-dk-bg-0: #c72929;
  --clr-dk-bg-1: #ad1457;
  --clr-dk-bg-2: #681b98;
  --clr-dk-bg-3: #4527a0;
  --clr-dk-bg-4: #293594;
  --clr-dk-bg-5: #1565c1;
  --clr-dk-bg-6: #0277bb;
  --clr-dk-bg-7: #00838f;
  --clr-dk-bg-8: #006b5f;
  --clr-dk-bg-9: #2f7f33;
  --clr-dk-bg-10: #54892f;
  --clr-dk-bg-11: #9e9e24;
  --clr-dk-bg-12: #f9a824;
  --clr-dk-bg-13: #ff9100;
  --clr-dk-bg-14: #f06c00;
  --clr-dk-bg-15: #d54215;

  /* Letter Tile Foreground Colors (lt-fg) */
  --clr-lt-fg-0: var(--clr-lt-bg-0); /* Use same as bg, as these are for text, will follow light-dark */
  --clr-lt-fg-1: var(--clr-lt-bg-1);
  --clr-lt-fg-2: var(--clr-lt-bg-2);
  --clr-lt-fg-3: var(--clr-lt-bg-3);
  --clr-lt-fg-4: var(--clr-lt-bg-4);
  --clr-lt-fg-5: var(--clr-lt-bg-5);
  --clr-lt-fg-6: var(--clr-lt-bg-6);
  --clr-lt-fg-7: var(--clr-lt-bg-7);
  --clr-lt-fg-8: var(--clr-lt-bg-8);
  --clr-lt-fg-9: var(--clr-lt-bg-9);
  --clr-lt-fg-10: var(--clr-lt-bg-10);
  --clr-lt-fg-11: var(--clr-lt-bg-11);
  --clr-lt-fg-12: var(--clr-lt-bg-12);
  --clr-lt-fg-13: var(--clr-lt-bg-13);
  --clr-lt-fg-14: var(--clr-lt-bg-14);
  --clr-lt-fg-15: var(--clr-lt-bg-15);

  /* Letter Tile Dark Foreground Colors (dk-fg) */
  --clr-dk-fg-0: var(--clr-dk-bg-0); /* Use same as bg, as these are for text, will follow light-dark */
  --clr-dk-fg-1: var(--clr-dk-bg-1);
  --clr-dk-fg-2: var(--clr-dk-bg-2);
  --clr-dk-fg-3: var(--clr-dk-bg-3);
  --clr-dk-fg-4: var(--clr-dk-bg-4);
  --clr-dk-fg-5: var(--clr-dk-bg-5);
  --clr-dk-fg-6: var(--clr-dk-bg-6);
  --clr-dk-fg-7: var(--clr-dk-bg-7);
  --clr-dk-fg-8: var(--clr-dk-bg-8);
  --clr-dk-fg-9: var(--clr-dk-bg-9);
  --clr-dk-fg-10: var(--clr-dk-bg-10);
  --clr-dk-fg-11: var(--clr-dk-bg-11);
  --clr-dk-fg-12: var(--clr-dk-bg-12);
  --clr-dk-fg-13: var(--clr-dk-bg-13);
  --clr-dk-fg-14: var(--clr-dk-bg-14);
  --clr-dk-fg-15: var(--clr-dk-bg-15);
}

* {
  box-sizing: border-box;
  padding: 0;
  margin: 0;
  font-family: Roboto, Arial, sans-serif;
  text-rendering: optimizeLegibility;
  scrollbar-width: thin;
  scrollbar-color: var(--clr-scrollbar-thumb) var(--clr-scrollbar-track);
}

/* Basic elements defined */

html, body {
  height: 100%;
  width: 100%;
  height: 100dvh;
  width: 100dvw;
  font-size: 10pt; /* 13.33 px/rem */
  color: var(--clr-text-primary);
  overflow: hidden;
  background-color: var(--clr-body-background);
  box-shadow: inset 0 10rem var(--clr-header-stripe-bg); /* the deep-plue stripe accross the top */
}

tt {
  font-family: 'Roboto Mono', Courier, monospace;
}

a {
  color: var(--clr-primary-accent);
  text-decoration: none;
}
a:hover,
a:focus {
  color: var(--clr-primary-accent-hover);
  text-decoration: underline;
}

a.danger {
  color: var(--clr-danger-text);
}
a.danger:hover,
a.danger:focus {
  color: var(--clr-danger-text-hover);
}

a.gray:hover,
a.gray:focus {
  color: var(--clr-text-tertiary);
}

form {
  font-size: 1.1rem;
  padding: 0.5rem 0.75rem;
  line-height: 1.5;
}

label {
  font-size: 1.1rem;
  margin-right: auto;
}

label.small {
  color: var(--clr-primary-action);
  font-size: 0.95rem;
}

label.large {
  color: var(--clr-primary-action);
  font-size: 1.1rem;
}

label.invalid {
  color: var(--clr-danger-text);
}

img.avatar {
  width: 100%;
  height: 100%;
  border-radius: 50%;
}

img.avatar.self {
  padding: 7%;
}

/* Input fields and buttons */

button {
  display: inline-block;
  font-family: inherit;
  font-size: 1.05rem;
  height: 2.2rem;
  line-height: 2.2rem;
  font-weight: normal;
  text-align: center;
  vertical-align: middle;
  touch-action: manipulation;
  cursor: pointer;
  border: 1px solid var(--clr-transparent);
  white-space: nowrap;
  padding-left: 1.2rem;
  padding-right: 1.2rem;
  border-radius: 4px;
  box-shadow: 0 1px 3px 0 var(--clr-shadow-button);
  text-transform: uppercase;
  min-width: 5rem;
  margin: 0 0.35rem 0 0.35rem;
}

button[disabled],
html input[disabled] {
  cursor: default;
  opacity: 0.65;
  box-shadow: none;
  filter: grayscale(50%);
}

button.round {
  border-radius: 50%;
  width: 3rem;
  height: 3rem;
  padding: 0;
  margin: 0;
  line-height: 3.5rem;
  outline: none; /* otherwise a square outline is shown */
  box-shadow: 0 2px 0.5rem 0 var(--clr-shadow-button);
  z-index: 2;
}

button.round.small {
  width: 2rem;
  height: 2rem;
  line-height: 2rem;
  box-shadow: 0 2px 0.35rem 0 var(--clr-shadow-button);
}

button:hover:not([disabled]), button:active:not([disabled]) {
  color: var(--clr-bright);
}
button:active {
  box-shadow: inset 0 3px 0.5rem var(--clr-shadow-button-inset-active);
}
button:active.round.small {
  box-shadow: inset 0 2px 0.35rem var(--clr-shadow-button-inset-active);
}

button.primary {
  background-color: var(--clr-button-primary-bg);
  color: var(--clr-button-primary-text);
}
button.primary:hover:not([disabled]), button.primary:active:not([disabled]) {
  background-color: var(--clr-button-primary-hover-bg);
}

button.secondary {
  background-color: var(--clr-button-secondary-bg);
  color: var(--clr-button-secondary-text);
}
button.secondary:hover:not([disabled]), button.secondary:active:not([disabled]) {
  background-color: var(--clr-button-secondary-hover-bg);
}

button.outline {
  background-color: var(--clr-transparent);
  color: var(--clr-button-outline-text);
  border: 1px solid var(--clr-button-outline-border);
  box-shadow: none;
}
button.outline:hover:not([disabled]), button.outline:active:not([disabled]) {
  color: var(--clr-button-outline-text);
  background-color: var(--clr-button-outline-hover-bg);
}

button.danger {
  background-color: var(--clr-button-danger-bg);
  color: var(--clr-button-danger-text);
}
button.danger:hover:not([disabled]), button.danger:active:not([disabled]) {
  background-color: var(--clr-button-danger-hover-bg);
}

button.positive {
  background-color: var(--clr-button-positive-bg);
  color: var(--clr-button-positive-text);
}
button.positive:hover:not([disabled]), button.positive:active:not([disabled]) {
  background-color: var(--clr-button-positive-hover-bg);
}

textarea, input {
  font-family: inherit;
  font-size: 1.1rem;
  background: var(--clr-transparent);
  border: none;
  margin: 0.25rem 0;
  padding: 0 0.125rem;
  outline: none;
  color: var(--clr-input-text);
}

input[type="text"],
input[type="email"],
input[type="password"],
input[type="search"],
input[type="tel"],
textarea {
  height: 2.5rem;
  border-bottom: 1px solid var(--clr-input-border);
  box-shadow: 0 1px 0 var(--clr-input-shadow);
  transition: all 0.1s ease-in-out, height 0s;
}

input[type="text"],
input[type="email"],
input[type="password"],
input[type="tel"],
textarea {
  width: 100%;
}

textarea:focus,
input[type="text"]:focus,
input[type="email"]:focus,
input[type="password"]:focus,
input[type="search"]:focus,
input[type="tel"]:focus {
  border-bottom: 1px solid var(--clr-input-border-focus);
  box-shadow: 0 1px 0 var(--clr-input-shadow-focus);
}

textarea.invalid,
input[type="text"].invalid,
input[type="email"].invalid,
input[type="password"].invalid,
input[type="search"].invalid,
input[type="tel"].invalid {
  border-bottom: 1px solid var(--clr-input-invalid-border);
  box-shadow: 0 1px 0 var(--clr-input-invalid-shadow);
}

input[type="text"]::placeholder,
input[type="email"]::placeholder,
input[type="password"]::placeholder,
input[type="search"]::placeholder,
input[type="tel"]::placeholder,
textarea::placeholder {
  color: var(--clr-input-placeholder-text);
  font-weight: lighter;
}

input[type="text"].with-icon-right,
input[type="password"].with-icon-right {
  margin-right:-2rem;
  padding-right:2rem;
}

input[type="text"].with-icon-left,
input[type="password"].with-icon-left {
  margin-left:-1.45rem;
  padding-left:1.75rem;
}

textarea {
  resize: none;
  padding-top: 0.45rem;
}

input[type="range"] {
  width: 90%;
}

option {
  padding: 0;
}

datalist {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  width: 100%;
}

/* END of input and buttons */

/* BEGIN scrollbar styling.  */

/* Chrome & other webkit browsers */
::-webkit-scrollbar {
  width: 0.6rem;
}

::-webkit-scrollbar-track {
  -webkit-box-shadow: inset 0 0 6px var(--clr-shadow-scrollbar-track-webkit);
  box-shadow: inset 0 0 6px var(--clr-shadow-scrollbar-track-webkit);
  background-color: var(--clr-scrollbar-track);
}

::-webkit-scrollbar-thumb {
  background-color: var(--clr-scrollbar-thumb);
}

/* END of Scrollbar styling.  */

/* BEGIN Popup/dropdown menu */

ul.menu {
  position: absolute;
  list-style: none;
  width: 12rem;
  border-radius: 0.2rem;
  padding-top: 0.35rem;
  padding-bottom: 0.35rem;
  box-shadow: 0 1px 6px var(--clr-shadow-dialog);
  background-color: var(--clr-bright);
  z-index: 4;
}

ul.menu > li {
  padding: 0.75rem 0.75rem 0.75rem 1.25rem;
  cursor: pointer;
}

ul.menu > li:hover {
  background-color: var(--clr-menu-item-hover-bg);
}

ul.menu > li.separator {
  padding: 0;
  margin: 2px;
  height: 1px;
  background-color: var(--clr-border-light);
}

ul.menu > li.separator:hover {
  background-color: var(--clr-border-light);
}

ul.menu > li.disabled {
  pointer-events: none;
  opacity: 0.6;
}

/* The down arrow head - trigger for context menu */
.menuTrigger {
  position: absolute;
  right: 0.25rem;
  width: 1.4rem;
  height: 1.4rem;
  line-height: 1.4rem;
  border-radius: 0.7rem;
  text-align: center;
  opacity: 0;
  background-color: inherit;
  user-select: none;
}
.menuTrigger a {
  color: var(--clr-text-secondary);
}

li .menuTrigger {
  top: 0.25rem;
}
li:hover .menuTrigger {
  opacity: 0.9;
}
li:hover .menuTrigger a {
  color: var(--clr-text-secondary);
}

/* END popup/dropdown menu */

/* Begin Alert: modal window with message and buttons. */
div.alert-container {
  position: absolute;
  display: flex;
  padding: 1rem;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: var(--clr-alert-overlay-bg);
  z-index: 3;
}

div.alert {
  position: relative;
  background-color: var(--clr-bright);
  box-shadow: 0.15rem 0.15rem 1.5rem var(--clr-shadow-dialog);
  padding: 1rem;
  border-radius: 0.3rem;
  margin: auto 2rem auto 2rem;
  width: fit-content;
  height: min-content;
  min-width: 16rem;
  max-width: 24rem;
  max-height: 40rem;
  overflow: hidden;
}

div.alert-container .title {
  position: relative;
  color: var(--clr-primary-accent);
  font-size: 1.2rem;
  font-weight: 500;
  width: 100%;
  padding: 0 0 0.35rem 0;
}

div.alert-container .title.with-control {
  position: relative;
  display: flex;
  padding: 0.5rem 0.5rem 0 0.5rem;
  align-items: center;
  flex: none;
  justify-content: space-between;
}

div.alert-container .content {
  position: relative;
  padding: 0.5rem 0 0.5rem 0;
}
/* END Alert */

/* BEGIN trusted badges with legend */
div.trusted-badge {
  margin: 0.25rem 0;
}
/* END trusted badges */

/* Generic text colors */
.blue {
  color: var(--clr-primary-accent)!important; /* blue 500 */
}
.lt-blue {
  color: var(--clr-lt-fg-1)!important; /* blue 300, using lt-fg-1 which is #90caf9 */
}

.orange {
  color: var(--clr-std-orange)!important;
}

.verified-color {
  color: var(--clr-verified-accent)!important; /* lt-blue 500 */
}

.staff-color {
  color: var(--clr-staff-accent)!important; /* light green 700 */
}

.danger-color {
  color: var(--clr-warning-accent)!important; /* amber 500 */
}

.green {
  color: light-dark(#388e3c, #1a9a1d); /* green 700 */
}

.white {
  color: var(--clr-bright)!important; /* 100% white */
}

.red {
  color: var(--clr-danger-text)!important; /* red 700 */
}

/* Color of an inverted icon badges */
.badge-inv {
  color: var(--clr-badge-inv)!important;
}

.gray {
  color: var(--clr-text-secondary)!important;
}

.light-gray {
  color: var(--clr-text-placeholder)!important;
}

.large {
  font-size: 120%;
}

/* Other universal style components */
.small {
  font-size: 90%;
}

.float-right {
  position: absolute;
  right: 0.5rem;
}

.hr {
  display: block;
  width: 100%;
  height: 0.45rem;
  min-height: 0.3rem;
  background-color: var(--clr-background-light-gray);
  box-shadow: inset 0 0.25rem 0.25rem -0.25rem var(--clr-shadow-hr-inset),
    inset 0 -0.25rem 0.25rem -0.25rem var(--clr-shadow-hr-inset);
}

.hr.thin {
  height: 0.015rem;
}

/* Vertical divider line */
.divider {
  display: inline-block;
  width: 1px;
  margin: 0 0.25rem;
  border-left: var(--clr-border-muted) 1.5px groove;
}

.ellipsized {
  overflow-x: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.flat-button {
  display: flex;
  align-items: center;
  margin: 0.15rem 0.35rem;
  height: 2em;
  line-height: 2em;
  font-weight: normal;
  text-align: center;
  vertical-align: middle;
  touch-action: manipulation;
  white-space: nowrap;
  text-transform: uppercase;
  background-color: var(--clr-bright);
  z-index: 1;
}
.flat-button:hover,
.flat-button:focus {
  text-decoration: none;
}

.flat-button.disabled,
.flat-button.disabled:hover,
.flat-button.disabled:focus {
  color: var(--clr-primary-accent);
  cursor: default;
  opacity: 0.75;
  filter: grayscale(75%);
}

.flat-button.faux {
  display: inline-block;
  height: 1.4em;
  line-height: 1.4em;
  text-transform: none;
  padding: 0 .35rem;
  margin: 0.15rem;
  border: 1px solid var(--clr-text-tertiary);
  border-radius: 3px;
  background-color: var(--clr-background-extra-light-gray);
}

.action-button {
  display: block;
  position: absolute;
  color: var(--clr-text-secondary);
  font-size: 1.8rem;
  background-color: var(--clr-background-off-white);
  border-radius: 50%;
  width: 3.25rem;
  height: 3.25rem;
  min-width: unset;
  min-height: unset;
  padding: 0;
  margin: 0;
  outline: none; /* otherwise a square outline is shown */
  box-shadow: 0 2px 0.5rem 0 var(--clr-shadow-button);
  transition: all 150ms;
  z-index: 2;
}

.action-button:focus,
.action-button:hover,
.action-button:hover:not([disabled]),
.action-button:active:not([disabled]) {
  color: var(--clr-text-tertiary-activated);
  background-color: var(--clr-primary-action-hover);
}
.action-button:active {
  color: var(--clr-text-tertiary-activated);
  background-color: var(--clr-primary-action);
}

.action-button.hidden {
  width: 1px;
  height: 1px;
  font-size: 1px;
  line-height: 1px;
  right: 2.625rem;
  bottom: 2.625rem;
  opacity: 0;
}

/* Element which can take focus but shows no outline */
.group-focus {
  outline: none;
}

/* END generic text colors */

/* END of basic elements */

#mountPoint {
  height: 100%;
  padding-top: 1rem;
  padding-bottom: 1rem;
}

/* Top-level application layout style: sidepanel + main view */
#noscript-message {
  position: relative;
  display: flex;
  flex-direction: column;
  max-width: 30rem;
  overflow: hidden;
  margin-top: 5rem;
  margin-left: auto;
  margin-right: auto;
  border-radius: 0.25rem;
  box-shadow: 1px 2px 0.3rem var(--clr-shadow-gray-strong);
  background-color: var(--clr-bright);
}

#noscript-title {
  padding: 1rem;
  font-size: 120%;
  font-weight: bolder;
  background-color: var(--clr-primary-accent); /* blue 500 */
  color: var(--clr-primary-light-blue); /* light-blue 100 */
}

#noscript-content {
  padding: 1rem;
}

#app-container {
  position: relative;
  display: flex;
  height: 100%;
  max-width: 84rem;
  overflow: hidden;
  margin-left: auto;
  margin-right: auto;
  border-radius: 0.25rem;
  box-shadow: 1px 2px 0.3rem var(--clr-shadow-gray-strong);
  background-color: var(--clr-bright);
}

#sidepanel {
  position: relative;
  display: flex;
  flex-direction: column;
  flex-grow: 0;
  flex-shrink: 0.3;
  width: 24rem;
  min-width: 18rem;
  height: 100%;
}

#topic-view {
  position: relative;
  display: flex;
  overflow-x: hidden;
  flex-direction: column;
  width: 100%;
  height: 100%;
}

#info-view {
  position: relative;
  display: flex;
  flex-direction: column;
  flex-grow: 0;
  flex-shrink: 0.3;
  width: 24rem;
  min-width: 18rem;
  height: 100%;
}

/* Generic announcement text, centered vertically and horizontally */
.center-medium-text {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  font-size: 1.4rem;
}

/* Class to alternatively hide sidepanel/topic-view/info-view */
.nodisplay {
  display: none!important;
}

/* Quoted div */
.quoted {
  margin-left: 1rem;
}

/* Extra space on the right */
.space-right {
  margin-right: 0.25rem;
}

/* Container with whitish background and rounded corners */
.rounded-container {
  position: relative;
  background-color: var(--clr-background-off-white);
  border-radius: 0.1rem;
  padding: 0.25rem;
  margin: 0.25rem;
}

/* BEGIN InPlaceEdit styles */
span.in-place-edit, div.in-place-edit {
  display: inline-block;
  font-family: inherit;
  font-size: 1rem;
  margin: 0.25rem 0.125rem 0 0.125rem;
  width: 100%;
  vertical-align: baseline;
  border-bottom: 1px dashed var(--clr-border-muted);
  cursor: pointer;
}

.in-place-edit.short {
  display: inline-flex;
  align-items: center;
  font-size: 1.1rem;
  height: 2.5rem;
  line-height: 2.25;
  white-space: nowrap;
}

.in-place-edit.disabled {
  border-bottom: none;
  cursor: default;
  color: var(--clr-text-disabled);
}

.in-place-edit.placeholder {
  color: var(--clr-text-placeholder);
}

.in-place-edit span {
  display: inline-block;
}

.in-place-edit.short span {
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow-x: hidden;
  width: 100%;
}

.in-place-edit .material-icons {
  display: inline-block;
}

.material-icons.invalid {
  color: var(--clr-error-text-muted);
}

textarea.in-place-edit {
  height: unset;
  font-size: unset;
}

input.in-place-edit.invalid {
  color: var(--clr-error-text-muted);
}

/* END of InPlaceEdit styles */

table.permission-editor {
  width: 100%;
}

table.permission-editor td {
  margin: 0.35rem 0;
  font-size: 1.1rem;
  vertical-align: middle;
}

table.permission-editor td.checkbox {
  text-align: center;
  color: var(--clr-text-tertiary);
}

.permission-editor .material-icons {
  font-size: 1.3rem;
  line-height: 1.3rem;
}

.material-icons.clickable {
  cursor: pointer;
  border-bottom: none;
}

.clickable {
  border-bottom: 1px dashed var(--clr-border-muted);
  cursor: pointer;
}

.image-clickable {
  cursor: pointer;
}

.clean-clickable {
  cursor: pointer;
}


/* END of top-level layout */

/* Sidepanel styles */
.panel-title {
  font-size: 1.4rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.panel-title.deleted {
  text-decoration: line-through;
}

.caption-panel {
  display: flex;
  align-items: center;
  flex: none;
  padding: 0.5rem;
  height: var(--caption-panel-height);
  white-space: nowrap;
  box-shadow: 0 1px 2px var(--clr-shadow-gray-strong);
  overflow-x: hidden;
  z-index: 1; /* otherwise the shadow becomes invisible */
}

.dialog-buttons {
  display: flex;
  padding: 0.5rem;
  justify-content: flex-end;
  align-items: center;
}

.dialog-buttons button {
  margin: 0 0.5rem;
}

.avatar-box {
  position: relative;
  flex-grow: 0;
  flex-shrink: 0;
}

.bot-form {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  min-width: 8rem;
  line-height: 2rem;
}
.bot-form div {
  min-height: 2rem;
  vertical-align: middle;
}
.bot-form button {
  display: inline-block;
  margin: 0.15rem;
  background-color: var(--clr-blue-wash-light);
  color: var(--clr-primary-accent); /* blue 500 */
  font-size: inherit;
  text-transform: none;
  height: 2rem;
  line-height: 2rem;
}
.bot-form > div > button {
  width: auto;
}
.bot-form button:focus,
.bot-form button:hover,
.bot-form button:active {
  outline: 0;
  color: var(--clr-dk-fg-5); /* #1565C0, a darker blue */
  background-color: var(--clr-primary-wash);
}

#side-caption-panel {
  background-color: var(--clr-primary-accent); /* blue 500 */
  color: var(--clr-primary-light-blue); /* light-blue 100 */
}

#side-caption-panel a {
  color: var(--clr-primary-light-blue); /* blue 100 */
  padding-left: 0.5rem;
  line-height: 1;
}

#side-caption-panel :hover {
  color: var(--clr-bright);
}

#sidepanel-title {
  margin-right: auto;
  margin-left: 0.5rem;
}

#self-avatar {
  width: 3rem;
  min-width: 3rem;
  height: 3rem;
  flex: none;
  border-radius: 50%;
}

#self-avatar.avatar-box {
  font-size: 1.8rem;
}

/* Application settings */
#settings-form ul {
  list-style: none;
}

#settings-form li {
  vertical-align: middle;
}
#settings-form label {
  display: inline-block;
  padding-left: 0.5rem;
}

input#host-name {
  width: 100%;
}

/* Input with a search icon on the left */
input.search {
  text-indent: 1.4rem;
}
i.search {
  position: absolute;
  left: .6rem;
}

/* Area which displays an error message */
.info-box {
  position: relative;
  display: none;
  overflow: hidden;
  padding: 1rem 1.5rem 0.75rem 0.5rem;
}

.info-box > span {
  line-height: 1.35rem;
}

.info-box .cancel {
  position: absolute;
  right: 0.25rem;
  top: 0.5rem;
}

.info-box.error {
  display: flex;
  background-color: var(--clr-error-bg-light);
  border-bottom: 1px solid var(--clr-error-border-light);
  color: var(--clr-error-text-dark);
}
.info-box.warning {
  display: flex;
  background-color: var(--clr-warning-bg-light);
  border-bottom: 1px solid var(--clr-warning-border-light);
  color: var(--clr-warning-text-dark);
}
.info-box.info {
  display: flex;
  background-color: var(--clr-info-bg-light);
  border-bottom: 1px solid var(--clr-info-border-light);
  color: var(--clr-info-text-dark);
}

.info-box .cancel .material-icons {
  font-size: 1rem;
  color: var(--clr-text-secondary);
}
.info-box.error .cancel .material-icons {
  color: var(--clr-error-text-dark);
}
.info-box .icon {
  display: block;
  margin-right: 0.5rem;
}
.info-box .icon .material-icons {
  font-size: 1.5rem;
}
.info-box.warning .icon .material-icons {
  color: var(--clr-warning-icon);
}
.info-box.error .icon .material-icons {
  color: var(--clr-error-icon);
}
.info-box.info .icon .material-icons {
  color: var(--clr-info-text-dark);
}
/* List of contacts */
.flex-column {
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow-x: hidden;
}

.flex-column.narrow {
  height: auto;
}

.scrollable-panel {
  overflow-x: hidden;
  overflow-y: auto;
  margin-top: 0.25rem;
  margin-bottom: auto;
  height: 100%;
  scroll-behavior: smooth;
}

.contact-box {
  list-style: none;
  overflow-x: hidden;
}

.contact-box > li {
  position: relative;
  display: flex;
  padding: 0.35rem 0.25rem 0.5rem 0.35rem;
  min-height: 3.75rem;
  flex-grow: 0;
  flex-shrink: 0;
  /* partial bottom border */
  background: linear-gradient(to right, var(--clr-transparent) 3.5rem, var(--clr-background-extra-light-gray) 1px, var(--clr-background-extra-light-gray) 100%) 0 100% / 100% 1px no-repeat, var(--clr-bright);
  overflow-x: hidden;
  cursor: pointer;
}

.contact-box.small > li {
  padding: 0.25rem 0.25rem 0.35rem 0.35rem;
  min-height: 2.5rem;
}

.contact-box > li:last-child {
  /* remove border from the last contact */
  background: var(--clr-bright);
}
.contact-box > li:hover {
  background-color: var(--clr-background-blue-gray-50); /* blue-gray 50 highlight */
}
.contact-box > li.selected {
  background-color: var(--clr-background-blue-gray-100); /* blue-gray 100 highlight */
}
.contact-box > li.tpinned {
  border-right: 1.5px solid var(--clr-secondary-accent);
  background-color: var(--clr-background-blue-gray-75); /* blue-gray 75 highlight */
}
.contact-box > li.action {
  min-height: 2.5rem;
  border-bottom: none;
}

.contact-box .text-box {
  overflow-x: hidden;
}

.contact-box .contact-title {
  font-size: 1.05rem;
  text-overflow: ellipsis;
  overflow-x: hidden;
  white-space: nowrap;
}

.contact-box .contact-title.deleted {
  opacity: 0.66;
  text-decoration: line-through;
  text-decoration-thickness: 0.5px;
}

.contact-box .contact-comment {
  text-overflow: ellipsis;
  overflow-x: hidden;
  white-space: nowrap;
  font-weight: lighter;
}

.contact-box .contact-comment > span {
  overflow-x: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.contact-box .contact-comment b {
  font-weight: bolder;
}

.contact-box .contact-comment .material-icons {
  margin-bottom: 0.2rem;
  color: light-dark(#777, #666); /* #777 */
}

/* Avatar and online-offline indicator */
.contact-box .avatar-box {
  position: relative;
  margin-right: 0.35rem;
  width: 3rem;
  min-width: 3rem;
  height: 3rem;
  min-height: 3rem;
  font-size: 1.8rem;
  overflow: hidden;
  padding: 0;
}
.contact-box .avatar {
  width: 3rem;
  height: 3rem;
  border-radius: 50%;
}

.contact-box.small .avatar-box {
  width: 2rem;
  min-width: 2rem;
  height: 2rem;
  min-height: 2rem;
  font-size: 1.2rem;
}
.contact-box.small .avatar {
  width: 2rem;
  height: 2rem;
}

.avatar.deleted {
  opacity: 0.75;
  filter: grayscale(1);
}

.contact-box .avatar-box > .material-icons {
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  font-size: 2.4rem;
  line-height: 3rem;
}
.contact-box .avatar-box > .checkmark.material-icons {
  line-height: unset;
}
.contact-box.small .avatar-box > .material-icons {
  font-size: 1.6rem;
  line-height: 2rem;
}
.contact-box .text-box {
  display: flex;
  flex-direction: column;
  justify-content: space-around;
}
.contact-box .text-box > div {
  display: flex;
  flex-direction: row;
  align-items: center;
}

.contact-box .action-text {
  text-align: center;
  font-size: 0.95rem;
  line-height: 2.5rem;
  margin: 0 auto 0 auto;
  cursor: pointer;
}

img.channel {
  width: 1.25rem;
  height: 1.25rem;
  vertical-align: middle;
  margin-left: 0.3rem;
}

.large img.channel {
  width: 1.45rem;
  height: 1.45rem;
  margin-left: 0.5rem;
  margin-bottom: 0.15rem;
}

/* Online-offline indicator positioned inside avatar-box */
.avatar-box .online, .offline {
  position: absolute;
  width: 0.75rem;
  min-width: 0.75rem;
  height: 0.75rem;
  min-height: 0.75rem;
  flex-shrink: 0;
  border-radius: 50%;
  right: 0;
  bottom: 0.1rem;
}
.avatar-box .online {
  background-color: var(--clr-online); /* Specific green for online status */
}
.avatar-box .offline {
  background-color: var(--clr-offline); /* #C0C0C0 (silver) or #ccc */
}

/* Typing indicator: animation of the online dot */
.online.typing {
  animation: typing 0.5s infinite;
}
@keyframes typing {
  0%, 100% {
    transform: translateX(0);
  }
  50% {
    transform: translateX(-0.3rem);
  }
}

.contact-box .checkmark.material-icons {
  width: 1.5rem;
  height: 1.5rem;
  font-size: 1.5rem;
  color: var(--clr-secondary-accent);
  position: absolute;
  right: 0;
  bottom: 0;
  background-color: var(--clr-bright);
  overflow: visible;
  border: 0.0px solid var(--clr-transparent);
  padding-left: 0.5px;
}

.contact-box .deleted.material-icons {
  width: 1.5rem;
  height: 1.5rem;
  font-size: 1.5rem;
  color: var(--clr-text-tertiary);
  position: absolute;
  right: 0;
  bottom: 0;
  background-color: var(--clr-bright);
}

/* END of avatar box */

#add-topic {
  position: absolute;
  right: 1rem;
  bottom: 1rem;
}

/* Various forms inside a panel (signup form, new topic form) */
.panel-form {
  display: flex;
  position: relative;
  flex-direction: column;
  padding: 0;
}

.panel-form-row {
  display: flex;
  position: relative;
  align-items: center;
  padding: 0.5rem 0.75rem;
  line-height: 1.5;
  flex-grow: 0;
  flex-shrink: 0;
}

.panel-form-column {
  display: flex;
  position: relative;
  flex-direction: column;
  flex-grow: 0;
  padding: 0.5rem 0.75rem;
  line-height: 1.5;
  overflow-x: clip;
}

/* Make sure padding is only applied at the top level panel */
.panel-form-row > .panel-form-column,
.panel-form-column > .panel-form-column {
  padding: 0!important;
  flex-grow: 1;
}
.panel-form-column > .panel-form-row,
.panel-form-row > .panel-form-row {
  padding: 0!important;
}

.panel-form-column > .group {
  margin-top: 0.25rem;
  margin-bottom: 0.25rem;
}

/* Styling of avatar upload control */
.avatar-upload {
  position: relative;
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
  width: 10rem;
  height: 10.5rem;
  font-size: 4.5rem;
  padding: 0;
  margin: 0.25rem;
}

.avatar-upload.read-only {
  height: auto;
}

.avatar-upload .clear-avatar {
  position: absolute;
  font-size: 1rem;
  top: 0;
  right: 0;
  opacity: 0;
  background-image: radial-gradient(var(--clr-bright) 40%, var(--clr-transparent) 75%);
}

.avatar-upload:hover .clear-avatar {
  opacity: 1;
}

.avatar-upload .avatar-box {
  position: relative;
  width: 10rem;
  height: 10rem;
}

.avatar-upload .avatar-box > .material-icons {
  position: relative;
  font-size: 4rem;
  line-height: 10rem;
  vertical-align: middle;
}

/* Clearfix */
.avatar-upload:after {
  content: ".";
  display: block;
  height: 0;
  clear: both;
  visibility: hidden;
}

.avatar-upload .blank {
  text-align: center;
  vertical-align: middle;
  border: 1px dashed var(--clr-text-tertiary);
  font-size: 1rem;
  flex-shrink: 0;
  width: 10rem;
  height: 10rem;
  overflow: hidden;
  color: var(--clr-text-tertiary);
  line-height: 10rem;
  border-radius: 50%;
}

.avatar-upload img.preview {
  width: 10rem;
  height: 10rem;
  overflow: hidden;
  border-radius: 50%;
}

.avatar-upload img.preview::before {
  position: absolute;
  content: " ";
  display: flex;
  font-size: 0.9rem;
  font-weight: lighter;
  color: var(--clr-text-primary);
  top: 0;
  left: 0;
  width: 10rem;
  height: 10rem;
  justify-content: center;
  background: center no-repeat url("../img/broken_image.png");
  border-radius: 50%;
}

.avatar-upload .inputfile.hidden {
  width: 0.1px;
  height: 0.1px;
  opacity: 0;
  overflow: hidden;
  position: absolute;
}

.avatar-upload .inputfile + label.round {
  display: flex;
  position: absolute;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  width: 3rem;
  height: 3rem;
  line-height: 3rem;
  border-radius: 50%;
  box-shadow: 0 1px 4px var(--clr-shadow-dialog); /* rgba(0,0,0,0.4) similar to menu */
  bottom: 0;
  right: 0;
  background-color: var(--clr-background-off-white);
  z-index: 1;
}

.avatar-upload .inputfile:focus + label.round {
  outline: none;
}

.avatar-upload .inputfile:focus + label,
.avatar-upload .inputfile + label:hover {
  background-color: var(--clr-primary-wash);
  color: var(--clr-primary-accent);
}
/* END of avatar upload */
/* END of new account panel */
/* END of sidepanel styles */

/* Topic/messages view */
#topic-caption-panel {
  background-color: var(--clr-background-blue-gray-300);
}
#topic-caption-panel a {
  color: var(--clr-text-secondary);
  text-decoration: none;
}

#topic-caption-panel :hover {
  color: var(--clr-dark);
}

#topic-caption-panel .avatar-box {
  position: relative;
  width: 3rem;
  min-width: 3rem;
  height: 3rem;
  font-size: 1.8rem;
  margin-right: 0.35rem;
}

#topic-caption-panel .avatar-box > .material-icons {
  font-size: 2.4rem;
  line-height: 3rem;
}

#topic-title-group {
  overflow-x: hidden;
}

#hide-message-view {
  display: block;
  margin-right: 0.35rem;
}

#topic-users {
  margin-left: auto;
  margin-right: 1rem;
  width: min-content;
}

#topic-users .avatar-box {
  display: inline-block;
  width: 1.8rem;
  min-width: 1.8rem;
  height: 1.8rem;
  min-height: 1.8rem;
  font-size: 1rem;
  margin-right: 0.2rem;
}

#topic-users .avatar-box > .material-icons {
  font-size: 1.4rem;
  line-height: 1.8rem;
}

/* Overflow span "+18 more" */
#topic-users > span {
  line-height: 2rem;
  vertical-align: top;
}

/* Div holding QR code */
.qr-code {
  align-self: center;
}

#messages-container {
  position: relative;
  overflow-y: hidden;
  height: 100%;
}


#messages-container::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 100%;
  background-color: var(--clr-background-blue-gray-50);
  background-image: var(--wallpaper-url);
  background-repeat: var(--wallpaper-repeat);
  background-size: var(--wallpaper-size);
  background-position: var(--wallpaper-position);
  filter: blur(var(--wallpaper-blur))
    invert(var(--wallpaper-invert))
    brightness(var(--wallpaper-brightness));
  pointer-events: none;
  z-index: 0;
}

/* Dark mode wallpaper adjustments: image wallpaper *
#messages-container.dark.wpimg::before {
  filter: brightness(50%);
}
/* Dark mode wallpaper adjustments: pattern wallpaper *
#messages-container.dark.wppatt::before {
  filter: invert(1);
}
*/

/* Scrollable panel where the messages are shown */
#messages-panel {
  position: relative;
  padding: 0.75rem;
  overflow-y: scroll;
  height: 100%;
}

#write-only-background {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 100%;
  background-image: repeating-linear-gradient(45deg, rgba(255,255,255,0.5), rgba(255,255,255,.5) 0.5rem,
    rgba(255,255,255,.8) 0.5rem, rgba(255,255,255,.8) 1rem); /* Specific gradient, keep as is or break down further if these opacities are common */
}

#write-only-note {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background-color: var(--clr-bright);
  color: var(--clr-text-primary);
  height: auto;
  width: auto;
  line-height: 2rem;
  text-align: center;
  padding: 0.75rem 1.25rem 0.75rem 1.25rem;
  border-radius: 0.5rem;
  box-shadow: 0 1px 0.5px var(--clr-shadow-button-inset-active); /* rgba(0, 0, 0, 0.12) */
}

#peer-messaging-disabled-note {
  position: absolute;
  left: 50%;
  bottom: 4.3rem;
  transform: translate(-50%);
  background-color: var(--clr-bright);
  color: var(--clr-text-primary);
  width: fit-content;
  line-height: 2rem;
  text-align: center;
  padding: 0.75rem 1.25rem 0.75rem 1.25rem;
  border-radius: 0.5rem;
  box-shadow: 0 1px 0.5px var(--clr-shadow-button-inset-active); /* rgba(0, 0, 0, 0.12) */
}

/* Footer-panel with the input for the new message */
#send-message-panel {
  display: flex;
  align-items: center;
  flex: none;
  padding: 0.4rem 0.4rem 0.4rem 0.6rem;
  background-color: var(--clr-background-blue-gray-50);
  z-index: 2;
  min-height: 4rem;
}

#send-message-panel #writing-disabled {
  width: 100%;
  text-align: center;
  font-size: 1.2rem;
}

#send-message-wrapper {
  background-color: var(--clr-background-blue-gray-50);
  box-shadow: 0px -2px 3px -1px var(--clr-shadow-panel-divider); /* Faint shadow above panel */
  z-index: 2;
}

#sendMessage {
  overflow: hidden;
  overflow-wrap: break-word;
}

#send-message-panel .material-icons {
  min-width: 2rem;
  font-size: 1.6rem;
}

#send-message-panel .material-icons.secondary, .material-icons.disabled {
  color: var(--clr-text-tertiary)!important;
}

#send-message-panel .material-icons.secondary:hover {
  color: var(--clr-primary-accent)!important;
}

/* The textarea where the message is entered. */
#send-message-input {
  overflow: hidden auto;
  min-height: 2.5rem;
  max-height: 6rem;
}

/* New chat invitation panel */

.accept-invite-panel {
  background-color: var(--clr-background-blue-gray-50);
  box-shadow: 0px -2px 3px -1px var(--clr-shadow-panel-divider); /* Faint shadow above panel */
  width: 100%;
  z-index: 1;
}

.accept-invite-panel .title {
  font-size: 1.2rem;
  padding: 0.75rem;
}

.accept-invite-panel .footer {
  background-color: var(--clr-background-off-white);
  white-space: nowrap;
  padding-bottom: 0.35rem;
  text-align: center;
}

.accept-invite-panel button {
  font-size: 1rem;
  height: 2em;
  line-height: 2em;
  border: 1px solid var(--clr-transparent);
  margin: 0.25rem;
  box-shadow: 0 1px 2px 0 var(--clr-shadow-button);
}

/* END of chat invitation panel */

/* A static panel shown when no topic is selected */
#dummy-view {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: var(--clr-cyan-50);
}
#dummy-view a {
  text-decoration: none;
  display: block;
  text-align: center;
}

#image-preview {
  position: absolute;
  display: flex;
  flex-direction: column;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 2;
  background-color: var(--clr-overlay-white-strong);
}


#preview-caption-panel {
  display: flex;
  justify-content: space-between;
  background-color: var(--clr-background-blue-gray-50);
  box-shadow: 0 1px 2px var(--clr-shadow-silver-subtle); /* Faint shadow under the panel */
  line-height: 2rem;
  flex-shrink: 0;
  flex-grow: 0;
  height: var(--caption-panel-height);
  padding: 1rem 0.75rem 0 0.75rem;
  font-size: 120%;
  z-index: 3;
}

#preview-caption-panel a {
  color: var(--clr-text-secondary);
  text-decoration: none;
}

#preview-caption-panel a:hover {
  color: var(--clr-dark);
}

#image-preview-container {
  display: flex;
  justify-content: space-around;
  align-items: center;
  overflow: hidden;
  background-color: var(--clr-gray-medium-bg);
  width: 100%;
  height: 100%;
}

#image-preview-footer {
  display: flex;
  justify-content: space-around;
  height: 3.2rem;
  line-height: 1.5rem;
  background-color: var(--clr-background-blue-gray-50);
  box-shadow: 0px -2px 3px -1px var(--clr-shadow-panel-divider); /* Faint shadow above panel */
  flex-grow: 0;
  flex-shrink: 0;
  z-index: 1;
}

#image-preview-container .material-icons {
  font-size: 6rem;
}

#image-preview-container .doc-card {
  display: flex;
  flex-direction: column;
  overflow-x: hidden;
  background-color: var(--clr-std-ltgray);
  padding: 1rem;
  border-radius: 0.5rem;
  max-width: 30rem;
}

.doc-card .avatar-box {
  width: 10rem;
  height: 10rem;
  font-size: 4.5rem;
}

.doc-card .avatar-box .material-icons {
  line-height: 10rem;
}

/* Video-call related styles */

#video-container {
  position: absolute;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: var(--clr-overlay-white-strong);
  z-index: 3;
}

#video-container.minimized {
  left: auto;
  top: 1rem;
  right: 1rem;
  width: 18rem;
  height: 18rem;
  background-color: unset;
  user-select: none;
  cursor: grab;
  box-shadow: 0.15rem 0.15rem 1.5rem var(--clr-shadow-dialog);
  border-radius: 0.5rem;
}

#controls {
  position: absolute;
  display: flex;
  column-gap: 1rem;
  align-items: center;
  align-self: center;
  justify-content: center;
  bottom: 2.5rem;
  z-index: 1;
}

#controls.minimized {
  column-gap: 0.5rem;
  bottom: 1.75rem;
}

.incoming-call #controls {
  bottom: 1rem;
}

#controls button {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  width: 4rem;
  height: 4rem;
  min-width: initial;
  box-shadow: 0 3px 6px 0 var(--clr-shadow-button);
}

#controls.minimized button {
  width: 2.75rem;
  height: 2.75rem;
  box-shadow: 0 2px 4px 0 var(--clr-shadow-button);
}

#controls button .material-icons {
  font-size: 1.8rem;
}

#controls.minimized button .material-icons {
  font-size: 1.4rem;
}

button.full-screen {
  position: absolute;
  top: 2rem;
  left: 2rem;
  z-index: 1;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 0.5rem;
  padding: 0;
  box-shadow: none;
  background-color: transparent;
  min-width: unset;
}

.minimized button.full-screen {
  top: 1rem;
  left: 1rem;
  width: 2rem;
  height: 2rem;
}

button.full-screen:hover:not([disabled]), button:active:not([disabled]) {
  color: var(--clr-text-secondary);
}

button.full-screen .material-icons {
  font-size: x-large;
}

.minimized button.full-screen .material-icons {
  font-size: large;
}

#video-container-panel {
  position: relative;
  height: 100%;
  width: 100%;
}

.call-party {
  background-color: var(--clr-background-extra-light-gray);
  border-radius: 0.5rem;
  border: 2px solid var(--clr-border-light);
  overflow: hidden;
}

.call-party:hover {
  border-color: var(--clr-primary-accent);
}

.minimized .call-party {
  border-width: 1px;
}

.call-party.peer {
  position: absolute;
  top: 1rem;
  left: 1rem;
  right: 1rem;
  bottom: 1rem;
  z-index: 1;
}

.minimized .call-party.peer {
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}

.call-party.self {
  position: absolute;
  right: 0.5rem;
  bottom: 0.5rem;
  width: 10rem;
  height: 10rem;
  z-index: 2;
}

.call-party.self[disabled] {
  display: none;
}

video {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.call-party.self video {
  transform: scaleX(-1);
}

.call-party[disabled] video {
  display: none;
}

.caller-card {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
}

.caller-card .avatar-box {
  width: 10rem;
  height: 10rem;
  font-size: 6rem;
}

.caller-card.pulse img.avatar,
.caller-card.pulse .lettertile {
  animation: active-call 1.5s linear infinite;
}

.caller-card .avatar-box .material-icons {
  font-size: 6rem;
  line-height: 1.6;
}

.minimized .caller-card .avatar-box {
  width: 6rem;
  height: 6rem;
  font-size: 3.6rem;
}

/* Badge with "You" for current user or peer's name. */
.call-party .caller-name {
  max-width: 12rem;
  padding: 0.15rem 0.5rem;
  border-radius: 0.35rem;
  z-index: 1;
  text-shadow: 0 0 1px var(--clr-bright);
  background-color: var(--clr-background-off-white);
  text-overflow: ellipsis;
  overflow-x: hidden;
  white-space: nowrap;
}

.call-party.self .caller-name.inactive {
  position: absolute;
  bottom: 0.25rem;
  right: 0.25rem;
}

.caller-card .caller-name {
  font-size: larger;
  margin-top: 0.5rem;
}

.caller-card .trusted-badge {
  display: inline-block;
}

.call-party.peer .caller-name.inactive {
  position: absolute;
  font-size: larger;
  left: 1rem;
  bottom: 0.5rem;
  margin: 0 auto;
}

.minimized .caller-name {
  padding: 0.1rem 0.35rem;
  border-radius: 0.25rem;
  font-weight: lighter;
}

.incoming-call {
  position: relative;
  display: flex;
  flex-direction: column;
  background-color: var(--clr-bright);
  box-shadow: 0.15rem 0.15rem 1.5rem var(--clr-shadow-dialog);
  border-radius: 0.3rem;
  margin: auto 2rem auto 2rem;
  width: fit-content;
  min-width: 16rem;
  max-width: 24rem;
}

.incoming-call .caller-card {
  position: relative;
  top: initial;
  left: initial;
  width: 100%;
  height: 100%;
  padding: 4rem 3.5rem 5.5rem 3.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
}

.incoming-call .caller-name {
  padding: 0.15rem 0.5rem;
  border-radius: 0.35rem;
  z-index: 1;
  text-shadow: 0 0 1px var(--clr-bright);
  background-color: var(--clr-background-off-white);
  text-overflow: ellipsis;
  overflow-x: hidden;
  white-space: nowrap;
}

.call-message {
  display: flex;
  flex-direction: row;
}

.call-message .duration {
  font-weight: lighter;
}

#go-to-latest {
  right: 1.5rem;
  bottom: 1rem;
}

@keyframes active-call {
  0% {
    box-shadow:
      0 0 0 0.1rem var(--clr-primary-accent-transparent-medium),
      0 0 0 0.3rem var(--clr-primary-accent-transparent-medium),
      0 0 0 0.5rem var(--clr-primary-accent-transparent-medium);
  }
  100% {
    box-shadow:
      0 0 0 0.4rem var(--clr-primary-accent-transparent-medium),
      0 0 0 2rem rgba(33, 150, 243, 0), /* End with transparent */
      0 0 0 3rem rgba(33, 150, 243, 0); /* End with transparent */
  }
}

/* Talk bubbles */
.chat-box {
  list-style: none;
  padding: 0 0 3.5rem 0;
  margin: 0 0.5rem;
  scroll-behavior: smooth;
}

/* Group chats have avatars on the left. Make left margin smaller */
.chat-box.group {
  margin-left: -0.4rem;
}

.chat-box li {
  display: flex;
  margin: 0;
  padding: 0;
  align-items: flex-end;
}

.chat-box .right {
  justify-content: flex-end;
}

.bubble {
  position: relative;
  display: flex;
  max-width: 36rem;
  min-width: 9rem;
  height: auto;
  padding: 0.75rem 0.5rem 0.75rem 0.5rem;
  margin: 0;
  text-align: left;
  color: var(--clr-bubble-text);
  border-radius: 0.5rem;
  transition: ease-out background-color 0.5s;
  transition-delay: 0.3s;
  filter: drop-shadow(0.5px 0.5px 0.7px var(--clr-shadow-bubble-drop));
}

.chat-box li.single {
  margin-top: 0.25rem;
  margin-bottom: 0.75rem;
}

.chat-box li.first {
  margin-top: 0.25rem;
  margin-bottom: 0.15rem;
}

.chat-box li.middle {
  margin-top: 0.15rem;
  margin-bottom: 0.15rem;
}

.chat-box li.last {
  margin-top: 0.15rem;
  margin-bottom: 0.75rem;
}

.left .bubble {
  background-color: var(--clr-bubble-left-bg);
  margin-right: 0.5rem;
}

.left.flash .bubble {
  background-color: var(--clr-bubble-left-bg-flash);
}

.left .bubble.tip {
  border-bottom-left-radius: 0;
}

.right .bubble {
  background-color: var(--clr-bubble-right-bg);
  margin-left: 1.75rem;
}

.right.flash .bubble {
  background-color: var(--clr-bubble-right-bg-flash);
}

.right .bubble.tip {
  border-bottom-right-radius: 0;
}

.chat-box .meta {
  justify-content: center;
  margin-top: 0.5rem;
  margin-bottom: 0.5rem;
}

.chat-box .meta .bubble {
  color: var(--clr-bubble-meta-text);
  min-width: unset;
}

.meta .bubble.deleted {
  background-color: var(--clr-bubble-meta-deleted-bg);
  padding: 0.75rem 0.75rem 0.5rem 0.75rem;
}

.meta .bubble.date {
  font-size: smaller;
  padding: 0.5rem 0.5rem 0.5rem 0.5rem;
  background-color: var(--clr-bubble-meta-date-bg);
  text-transform: uppercase;
  user-select: none;
}

/* Left triangle placed bottom left flush. */
.left .bubble.tip::before {
  content: '';
  position: absolute;
  width: 0.85rem;
  height: 0.85rem;
  left: -0.8rem;
  bottom: 0;
  background-color: var(--clr-bubble-left-bg);
  clip-path: polygon(100% 0, 0 110%, 100% 110%);
  -webkit-clip-path: polygon(100% 0, 0 110%, 100% 110%);
  border-bottom-left-radius: 0.3rem;
  transition: ease-out background-color 0.5s;
  transition-delay: 0.3s;
}

.left.flash .bubble.tip::before {
  background-color: var(--clr-bubble-left-bg-flash);
}

/* Right triangle placed bottom right flush. */
.right .bubble.tip::before {
  content: '';
  position: absolute;
  width: 0.85rem;
  height: 0.85rem;
  left: 99.8%;
  bottom: 0;
  background-color: var(--clr-bubble-right-bg);
  clip-path: polygon(0 0, 100% 110%, 0 110%);
  -webkit-clip-path: polygon(0 0, 100% 110%, 0 110%);
  border-bottom-right-radius: 0.3rem;
  transition: ease-out background-color 0.5s;
  transition-delay: 0.3s;
}

.right.flash .bubble.tip::before {
  background-color: var(--clr-bubble-right-bg-flash);
}

.chat-box .avatar-box {
  position: relative;
  width: 1.4rem;
  min-width: 1.4rem;
  height: 1.4rem;
  min-height: 1.4rem;
  font-size: 0.8rem;
  margin-bottom: 0.8rem;
  margin-right: 0.8rem;
}

/* Message text + timestamp and delivery marker */
.bubble div.content-meta {
  width: 100%;
}

.bubble div.message-content {
  position: relative;
  margin: 0;
  width: 100%;
  max-width: 36rem;
  overflow-wrap: anywhere;
  padding: 0 0.75rem 0 0.75rem;
  font-size: var(--message-text-size);
}

/* Increase font size when the message contains only emojis.
Font from 3x to almost normal, from 1 to 5 emojis in a message */
.bubble div.message-content.emoji-1 {
  font-size: 300%;
}
.bubble div.message-content.emoji-2 {
  font-size: 241%;
}
.bubble div.message-content.emoji-3 {
  font-size: 193%;
}
.bubble div.message-content.emoji-4 {
  font-size: 155%;
}
.bubble div.message-content.emoji-5 {
  font-size: 125%;
}

/* The timestamp is a floating element. Need to ensure div.message-content is expanded
 * to accomodate it. It's usually called clearfix. */
.bubble div.message-content:after {
  content: ".";
  display: block;
  height: 0;
  clear: both;
  visibility: hidden;
}

.chat-box .timestamp-padding {
  display: inline-block;
  width: 4rem;
  height: 0;
}

.chat-box .timestamp {
  position: relative;
  font-size: 80%;
  color: var(--clr-bubble-timestamp-text);
  top: 0.35rem;
  float: right;
  white-space: nowrap;
  user-select: none;
}

/* The name of the person who sent the message
 * (group chat only)
 */
.chat-box .author {
  font-size: 80%;
  color:var(--clr-bubble-author-text);
  max-width: 12em;
  text-overflow: ellipsis;
  white-space: nowrap;
  overflow-x: hidden;
}

/* Inline and preview image styles */
.inline-image, .image-preview {
  position: relative;
  overflow: hidden;
  border-radius: 0.1rem;
}

.inline-image {
  max-width: 36rem;
  max-height: 24rem;
}

/* Container with upload progress */
.inline-image > .rounded-container {
  position: relative;
  margin: 0.25rem auto;
  bottom: 2rem;
  /* Imitating minimum margins on the left and right */
  border-left: 0.25rem solid var(--clr-transparent);
  border-right: 0.25rem solid var(--clr-transparent);
}

/* Broken image graphics which replaces the stock graphics. */
img.inline-image::before, img.image-preview::before {
  position: absolute;
  display: flex;
  font-size: 0.9rem;
  font-weight: lighter;
  color: var(--clr-text-primary);
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  justify-content: center;
  background: center no-repeat var(--clr-border-light) url("../img/broken_image.png");
}

img.inline-image::before {
  content: attr(alt);
  background-size: 3rem 3rem;
}

img.image-preview::before {
  content: " ";
  background-size: 10rem 10rem;
}

.inline-image.video > img.inline-image::before, img.image-preview.video::before {
  background: center no-repeat var(--clr-border-light) url("../img/broken_video.png");
}

.inline-image.video > img.inline-image::before {
  background-size: 3rem 3rem;
}

.inline-video {
  display: flex;
  position: relative;
  align-items: center;
  justify-content: center;
}

.inline-video > img.inline-image::before {
  background: var(--clr-border-light);
}

.inline-video .duration {
  padding: 0.25rem 0.5rem;
  color: var(--clr-toast-bg); /* #333 */
  background-color: rgba(255, 255, 255, 0.5); /* Specific rgba */
  position: absolute;
  bottom: 0.25rem;
  left: 0.25rem;
  font-size: 80%;
  border-radius: 0.3rem;
}

.inline-video .play-control {
  display: flex;
  position: absolute;
  align-items: center;
  justify-content: center;
  width: 4rem;
  height: 4rem;
  background-color: rgba(0, 0, 0, 0.4); /* Specific rgba */
  border-radius: 50%;
  pointer-events: none;
  cursor: pointer;
}

/* Attachment styles */
.attachment {
  display: flex;
}
.attachment:last-of-type {
  margin-bottom: -0.45rem;
}

/* END of talk bubbles */
/* END of topic/mesages view */

/* InfoView styles */
#info-caption-panel {
  background-color: var(--clr-background-blue-gray-300);
}
#info-caption-panel a {
  color: var(--clr-text-secondary);
  line-height: 1;
  text-decoration: none;
}
#info-caption-panel :hover {
  color: var(--clr-dark);
}

#info-title {
  margin-right: auto;
}

#group-manager {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow-y: hidden;
}

#group-manager-buttons {
  display: flex;
  background-color: var(--clr-background-blue-gray-50);
  box-shadow: 0 -1px var(--clr-shadow-panel-divider); /* Faint shadow above panel */
  z-index: 2;
  justify-content: space-around;
  padding: 0.4rem;
  height: 4rem;
  border-left: 1px solid var(--clr-border-light);
}

/* END of InfoView */

/* BEGIN Tabs */

ul.tabbar {
  display: flex;
  flex-grow: 0;
  flex-shrink: 0;
  background: var(--clr-tabbar-bg);
  list-style:none;
  margin: 0;
  width: 100%;
  overflow: hidden;
  padding: 0;
  padding-left: 1rem;
}

ul.tabbar > li {
  position: relative;
  height: 2.4rem;
  box-shadow: inset 0 -2px 2.5px -1px var(--clr-shadow-button); /* rgba(0,0,0,0.25) */
}

ul.tabbar li.active {
  background: var(--clr-bright);
}

ul.tabbar li:after {
  height: 0.10rem;
  width: 100%;
  content: "";
  bottom: 0;
  left: 0;
  position: absolute;
  background: var(--clr-tabbar-inactive-border);
}

ul.tabbar li.active:after {
  height: 0.15rem;
  content: "";
  bottom: 0;
  left: 0;
  position: absolute;
  background: var(--clr-tabbar-active-border);
  animation: tabbar-border-expand 0.2s cubic-bezier(0.4, 0.0, 0.4, 1) 0s alternate forwards;
}

@keyframes tabbar-border-expand {
  0% {
    opacity: 0;
    width: 0;
  }
  100% {
    opacity: 1;
    width: 100%;
  }
}

ul.tabbar > li > a {
  position: relative;
  padding-left: 1rem;
  padding-right: 1rem;
  text-align: center;
  line-height: 2.4rem;
  font-weight: 400;
  font-size: 1.3rem;
  font-variant: small-caps;
  text-decoration: none;
  color: var(--clr-tabbar-inactive-text);
  overflow: hidden;
}

ul.tabbar li.active > a {
  color: var(--clr-tabbar-active-text);
}

/* END Tabs */

/* Miscellaneous */

/* Badge with the number of unread messages */
.unread {
  display: inline-block;
  font-size: 0.75rem;
  font-weight: bolder;
  background-color: var(--clr-secondary-accent);
  color: var(--clr-bright);
  border-radius: 50%;
  width: 1.35rem;
  height: 1.35rem;
  margin-left: 0.5rem;
  line-height: 1.45rem;
  text-align: center;
  vertical-align: middle;
}

.material-icons.as-badge {
  padding-left: 0.2rem;
  font-size: 1.15rem;
  color: var(--clr-chip-remove-icon-bg); /* #aaa */
}

/* Badge with a label, like [you], [muted], etc */
.badge {
  font-family: 'Roboto Mono', Courier, monospace, sans-serif;
  font-size: 0.8rem;
  border: 1px solid var(--clr-badge-default-border);
  background-color: var(--clr-badge-default-bg);
  color: var(--clr-badge-default-text);
  padding: 0.05rem 0.25rem 0.05rem 0.25rem;
  margin: 0.05rem 0.1rem 0.05rem 0.1rem;
  border-radius: 0.2rem;
  display: inline-block;
  align-self: flex-start;
}

.badge.green {
  border-color: var(--clr-badge-green-border);
  background-color: var(--clr-badge-green-bg);
  color: var(--clr-badge-green-text);
}

.badge.yellow {
  border-color: var(--clr-badge-yellow-border);
  background-color: var(--clr-badge-yellow-bg);
  color: var(--clr-badge-yellow-text);
}

.badge.blue {
  border-color: var(--clr-badge-blue-border);
  background-color: var(--clr-badge-blue-bg);
  color: var(--clr-badge-blue-text);
}

.badge.red {
  border-color: var(--clr-badge-red-border);
  background-color: var(--clr-badge-red-bg);
  color: var(--clr-badge-red-text);
}

.badge.magenta {
  border-color: var(--clr-badge-magenta-border);
  background-color: var(--clr-badge-magenta-bg);
  color: var(--clr-badge-magenta-text);
}

/* Letter tile base style, responsive square box */
.lettertile {
  width: 100%;
  padding-bottom: 100%;
  border-radius: 50%;
  user-select: none;
}

/* Div with letter tile content */
.lettertile > div {
  position: absolute;
  display: flex;
  flex-shrink: 0;
  flex-grow: 0;
  top: 0; bottom: 0; left: 0; right: 0;
  text-transform: uppercase;
  align-items: center;
  justify-content: center;
  text-align: center;
  border-radius: 50%;
  line-height: 1;
  padding-top: 0.1em;
  color: var(--clr-lettertile-default-text); /* default text color #FAFAFA, gray 50 */
}

.lettertile:hover {
  color: var(--clr-lettertile-hover-text);
}

.lettertile.disabled {
  opacity: 0.5;
}

/* Colors of letter tiles */
.lt-bg-0 { background-color: var(--clr-lt-bg-0); }
.lt-bg-1 { background-color: var(--clr-lt-bg-1); }
.lt-bg-2 { background-color: var(--clr-lt-bg-2); }
.lt-bg-3 { background-color: var(--clr-lt-bg-3); }
.lt-bg-4 { background-color: var(--clr-lt-bg-4); }
.lt-bg-5 { background-color: var(--clr-lt-bg-5); }
.lt-bg-6 { background-color: var(--clr-lt-bg-6); }
.lt-bg-7 { background-color: var(--clr-lt-bg-7); }
.lt-bg-8 { background-color: var(--clr-lt-bg-8); }
.lt-bg-9 { background-color: var(--clr-lt-bg-9); }
.lt-bg-10 { background-color: var(--clr-lt-bg-10); }
.lt-bg-11 { background-color: var(--clr-lt-bg-11); }
.lt-bg-12 { background-color: var(--clr-lt-bg-12); }
.lt-bg-13 { background-color: var(--clr-lt-bg-13); }
.lt-bg-14 { background-color: var(--clr-lt-bg-14); }
.lt-bg-15 { background-color: var(--clr-lt-bg-15); }

/* Darker version of letter tile colors */
.dk-bg-0 { background-color: var(--clr-dk-bg-0); }
.dk-bg-1 { background-color: var(--clr-dk-bg-1); }
.dk-bg-2 { background-color: var(--clr-dk-bg-2); }
.dk-bg-3 { background-color: var(--clr-dk-bg-3); }
.dk-bg-4 { background-color: var(--clr-dk-bg-4); }
.dk-bg-5 { background-color: var(--clr-dk-bg-5); }
.dk-bg-6 { background-color: var(--clr-dk-bg-6); }
.dk-bg-7 { background-color: var(--clr-dk-bg-7); }
.dk-bg-8 { background-color: var(--clr-dk-bg-8); }
.dk-bg-9 { background-color: var(--clr-dk-bg-9); }
.dk-bg-10 { background-color: var(--clr-dk-bg-10); }
.dk-bg-11 { background-color: var(--clr-dk-bg-11); }
.dk-bg-12 { background-color: var(--clr-dk-bg-12); }
.dk-bg-13 { background-color: var(--clr-dk-bg-13); }
.dk-bg-14 { background-color: var(--clr-dk-bg-14); }
.dk-bg-15 { background-color: var(--clr-dk-bg-15); }

/* Same colors as above but for text as opposite to background */
.lt-fg-0 { color: var(--clr-lt-fg-0)!important; }
.lt-fg-1 { color: var(--clr-lt-fg-1)!important; }
.lt-fg-2 { color: var(--clr-lt-fg-2)!important; }
.lt-fg-3 { color: var(--clr-lt-fg-3)!important; }
.lt-fg-4 { color: var(--clr-lt-fg-4)!important; }
.lt-fg-5 { color: var(--clr-lt-fg-5)!important; }
.lt-fg-6 { color: var(--clr-lt-fg-6)!important; }
.lt-fg-7 { color: var(--clr-lt-fg-7)!important; }
.lt-fg-8 { color: var(--clr-lt-fg-8)!important; }
.lt-fg-9 { color: var(--clr-lt-fg-9)!important; }
.lt-fg-10 { color: var(--clr-lt-fg-10)!important; }
.lt-fg-11 { color: var(--clr-lt-fg-11)!important; }
.lt-fg-12 { color: var(--clr-lt-fg-12)!important; }
.lt-fg-13 { color: var(--clr-lt-fg-13)!important; }
.lt-fg-14 { color: var(--clr-lt-fg-14)!important; }
.lt-fg-15 { color: var(--clr-lt-fg-15)!important; }

.dk-fg-0 { color: var(--clr-dk-fg-0)!important; }
.dk-fg-1 { color: var(--clr-dk-fg-1)!important; }
.dk-fg-2 { color: var(--clr-dk-fg-2)!important; }
.dk-fg-3 { color: var(--clr-dk-fg-3)!important; }
.dk-fg-4 { color: var(--clr-dk-fg-4)!important; }
.dk-fg-5 { color: var(--clr-dk-fg-5)!important; }
.dk-fg-6 { color: var(--clr-dk-fg-6)!important; }
.dk-fg-7 { color: var(--clr-dk-fg-7)!important; }
.dk-fg-8 { color: var(--clr-dk-fg-8)!important; }
.dk-fg-9 { color: var(--clr-dk-fg-9)!important; }
.dk-fg-10 { color: var(--clr-dk-fg-10)!important; }
.dk-fg-11 { color: var(--clr-dk-fg-11)!important; }
.dk-fg-12 { color: var(--clr-dk-fg-12)!important; }
.dk-fg-13 { color: var(--clr-dk-fg-13)!important; }
.dk-fg-14 { color: var(--clr-dk-fg-14)!important; }
.dk-fg-15 { color: var(--clr-dk-fg-15)!important; }

/* Material icons resized from the default 24pt */
.material-icons {
  font-size: 1.4rem;
  line-height: 1;
  vertical-align: middle;
  text-align: center;
  user-select: none;
}
.material-icons.small {
  font-size: 1rem;
}
.material-icons.medium {
  font-size: 1.2rem;
}
.material-icons.large {
  font-size: 1.6rem;
}
.material-icons.big {
  font-size: 2.2rem;
}
.material-icons.x-big {
  font-size: 3rem;
}
.material-icons.huge {
  font-size: 4rem;
}
.composed-material {
  display: inline-block;
  position: relative;
}
.composed-material .second {
  position: absolute;
  font-size: 85%;
  top: 7%;
  left: 39%;
  font-weight: bold;
}
.composed-material .second-small {
  position: absolute;
  font-size: 62%;
  top: 14%;
  left: 30%;
  font-weight: bold;
}

/* White outline */
.material-icons.outline {
  position: relative;
  text-shadow: -1px 1px var(--clr-bright), 1px 1px var(--clr-bright), 1px -1px var(--clr-bright), -1px -1px var(--clr-bright);
}

#self-avatar .material-icons {
  font-size: 2.4rem;
  line-height: 3rem;
}
.avatar-box .material-icons {
  color: var(--clr-lettertile-default-text); /* #fafafa, gray 50 */
  border-radius: 50%;
  width: inherit;
  height: inherit;
}

.chip-input {
  display: flex;
  flex-wrap: wrap;
  flex-grow: 1;
  cursor: text;
  font-size: 1.1rem;
  font-weight: normal;
  background: var(--clr-transparent);
  border-bottom: 1px solid var(--clr-input-border);
  box-shadow: 0 1px 0 var(--clr-input-shadow);
  transition: all 0.1s ease-in-out;
  max-height: 10rem;
  min-height: 4rem;
  overflow-y: scroll;
  margin: 0.25rem 0 0.25rem 0;
  outline: none;
  color: var(--clr-input-text);
  align-items: center;
  justify-content: flex-start;
  text-align: center;
}

.chip-input.focused {
  border-bottom: 1px solid var(--clr-input-border-focus);
  box-shadow: 0 1px 0 var(--clr-input-shadow-focus);
}

.chip-input > input[type="text"] {
  display: inline-block;
  width: auto;
  border: none;
  line-height: 1.8;
  box-shadow: none;
  min-width: 4rem;
  flex: 1 0 auto;
  height: 1.8rem;
  margin: 0.125rem;
}

.chip {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  height: 1.8rem;
  line-height: 1.8;
  border-radius: 0.9rem;
  margin: 0.125rem;
  background-color: var(--clr-chip-bg);
  white-space: nowrap;
  font-size: 90%;
  max-width: 12rem;
  overflow: hidden;
  text-overflow: ellipsis;
}

.chip > span {
  white-space: nowrap;
  overflow-x: hidden;
  text-overflow: ellipsis;
}

.chip.invalid {
  color: var(--clr-chip-invalid-text);
  background-color: var(--clr-chip-invalid-bg);
}

.chip > a {
  display: inline-block;
  color: var(--clr-chip-remove-icon-text);
  background-color: var(--clr-chip-remove-icon-bg);
  border-radius: 50%;
  margin: 0.3rem;
  width: 1.175rem;
  min-width: 1.175rem;
  height: 1.175rem;
  line-height: 1.15;
  text-decoration: none;
}

.chip > a:focus,
.chip > a:hover {
  text-decoration: none;
  color: var(--clr-chip-remove-icon-hover-text);
  background-color: var(--clr-chip-remove-icon-hover-bg);
}

.chip .avatar-box {
  position: relative;
  width: 1.8rem;
  min-width: 1.8rem;
  height: 1.8rem;
  min-height: 1.8rem;
  font-size: 1rem;
  margin-right: 0.2rem;
}

.chip .avatar-box .material-icons {
  font-size: 1.4rem;
  line-height: 1.8rem;
}

.chip .spacer {
  display: inline-block;
  margin: 0.3rem;
  width: 0.25rem;
  height: 1.175rem;
}

.load-spinner-box {
  --size-small: 2.5rem;
  --size-large: 4rem;
  position: absolute;
  box-shadow: 0.1rem 0.1rem 0.15rem 1px var(--clr-shadow-button);
  border-radius: 50%;
  padding: 0.25rem;
  width: var(--size-small);
  height: var(--size-small);
  left: 0;
  right: 0;
  top: 5rem;
  margin-left: auto;
  margin-right: auto;
  background-color: var(--clr-bright);
  z-index: 2;
}

.load-spinner-box.large {
  width: var(--size-large);
  height: var(--size-large);
}

.load-spinner-box.clear {
  box-shadow: 0.1rem 0.1rem 0.15rem 1px var(--clr-shadow-button-inset-active); /* rgba(0,0,0,0.12) */
  background-color: rgba(255,255,255,0.5); /* Specific rgba */
}

.load-spinner-box.centered {
  top: calc(var(--size-small)/2 - 0.25rem);
}

.load-spinner-box.large.centered {
  top: calc(var(--size-large)/2 - 0.25rem);
}

.loader-spinner {
  border: 0.35rem solid var(--clr-spinner-track);
  border-radius: 50%;
  border-top: 0.35rem solid var(--clr-spinner-active);
  width: 2rem;
  height: 2rem;
  animation: spin 1.5s linear infinite;
}

.load-spinner-box.large .loader-spinner {
  width: 3.5rem;
  height: 3.5rem;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

/* File upload styles */
.uploader {
  display: flex;
}
/* Gray uploader bar of fixed length (background) */
.uploader > div {
  position: relative;
  height: 0.6rem;
  padding: 0.15rem;
  margin: 0.35rem;
  width: 6rem;
  line-height: 0;
  border-radius: 0.1rem;
  background-color: var(--clr-background-blue-gray-100);
}
/* Colored uploader progress bar of variable length */
.uploader > div > span {
  display: inline-block;
  height: 0.3rem;
  background-color: var(--clr-primary-action);
  border-radius: 0.08rem;
}

/* Highlighted text */
.highlight {
  color: var(--clr-highlight-text);
  font-weight: bolder;
}

.highlight .preview {
  color: var(--clr-highlight-preview-text);
  font-weight: inherit;
}

/* Image cropping widget */

.cropper {
  position: relative;
  width: 18rem;
  height: 21rem;
  margin: auto;
  margin-top: 1rem;
  align-self: center;
  transform: translateZ(0);
  border-radius: 0.25rem;
}

.cropper .bounding-box {
  position: relative;
  width: 18rem;
  height: 18rem;
  overflow: hidden;
  z-index: 1;
  border-radius: 0.25rem;
  border: solid 2px var(--clr-cropper-bounding-box-border);
  box-shadow: 1px 1px 3px var(--clr-shadow-cropper-gray);
  background-color: var(--clr-cropper-bounding-box-bg);
}

.cropper .preview {
  position: absolute;
  max-height: none;
  max-width: none;
  z-index: -1;
}

.cropper .cutout {
  position: absolute;
  width: 17.8rem;
  height: 17.8rem;
  border: 1px dashed var(--clr-cropper-cutout-border);
  margin: auto;
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
  box-shadow: 0 0 150rem 150rem var(--clr-cropper-cutout-shadow);
  z-index: 0;
}

.cropper .cutout.circle {
  border-radius: 50%;
}

.cropper .overlay {
  position: absolute;
  cursor: move;
  touch-action: none;
  z-index: 1;
}

.cropper .zoom-wrapper {
  height: 2rem;
  width: 80%;
  margin: 1rem auto;
  text-align: center;
}

.cropper .zoom {
  box-shadow: none;
  pointer-events: none;
  z-index: 2;
}

.cropper .zoom:focus {
  outline: none;
}

/* Quoted (cited) content */
.reply-quote {
  position: relative;
  padding: 0.15rem 0.5rem 0.25rem 0.5rem;
  border-left: 0.25rem solid var(--clr-reply-quote-border);
  line-height: 1.5em;
  font-weight: lighter;
  border-radius: 0.25rem;
  color: var(--clr-reply-quote-text);
  cursor: pointer;
}

.chat-box .bubble .reply-quote {
  margin: 0.15rem -0.75rem 0.3rem -0.75rem;
}

.chat-box .bubble .reply-quote:first-child {
  margin-top: -0.25rem;
}

.chat-box .left .reply-quote {
  background-color: var(--clr-reply-quote-left-bg);
}

.chat-box .right .reply-quote {
  background-color: var(--clr-reply-quote-right-bg);
}

.reply-quote .inline-image {
  vertical-align: middle;
  margin-bottom: 0.1rem;
}

.reply-quote img.inline-image::before {
  content: '';
}

#reply-quote-preview {
  display: flex;
  align-items: center;
}

#reply-quote-preview .reply-quote {
  width: 100%;
  background-color: var(--clr-reply-quote-preview-bg);
  margin: 0.35rem 0.5rem 0 0;
  cursor: initial;
}

#reply-quote-preview .cancel {
  min-width: 2.4rem;
  text-align: center;
}

#reply-quote-preview .inline-image {
  background-color: var(--clr-border-light);
}

#reply-quote-preview img.inline-image::before {
  content: '';
}

#send-message-panel #reply-quote-preview {
  width: 100%;
}
#send-message-panel #reply-quote-preview .reply-quote {
  margin-bottom: 0.35rem;
}

.forwarding-quote {
  font-size: 200%;
  line-height: 200%;
}

.mention {
  font-weight: 500;
}

/* Message forwarding. */
.forward-dialog {
  position: relative;
  overflow: hidden;
  background-color: var(--clr-bright);
  box-shadow: 0.15rem 0.15rem 1.5rem var(--clr-shadow-dialog);
  padding: 0.5rem;
  border-radius: 0.3rem;
  margin: auto 1rem auto 1rem;
  width: 24rem;
  height: 80%;
}

.forward-dialog .scrollable-panel {
  height: 80%;
}

.audio {
  display: flex;
  margin-left: auto;
  align-items: center;
  flex: none;
  background-color: var(--clr-audio-bg);
  height: 3rem;
  border-radius: 1.5rem;
}

.audio canvas {
  width: 14rem;
  height: 2.6rem;
  margin-right: 2rem;
}

.audio canvas.playback {
  margin-right: 0;
}

.audio .duration {
  font-size: large;
}

.audio-player {
  display: flex;
  align-items: center;
}

.audio-player .material-icons.large {
  font-size: 2.4rem;
  color: var(--clr-audio-icon);
}

.audio-player .material-icons.disabled {
  color: var(--clr-audio-icon-disabled);
  cursor: default;
}

.audio-player .playback {
  width: 14rem;
  height: 2.6rem;
}

.audio-player canvas.playback {
  display: block;
}

.audio-player div.playback {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--clr-audio-icon);
  font-size: small;
}

.audio-player .timer {
  font-size: smaller;
  color: var(--clr-audio-timer-text);
}

/* Pinned messages */
#pinned-wrapper {
  position: relative;
  display: flex;
  align-items: center;
  height: 100%;
  margin-right: 0.5rem;
}

.pinned {
  position: relative;
  display: flex;
  align-items: center;
  padding: 0.15rem 0.5rem 0.25rem 0.5rem;
  background-color: var(--clr-background-off-white);
  background-position: center;
  font-weight: lighter;
  border-radius: 0 0.25rem 0.25rem 0;
  color: var(--clr-text-primary);
  height: 100%;
  width: 24rem;
  min-width: 0;
  cursor: pointer;
  transition: background 0.4s;
}

.pinned > p {
  overflow-x: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.pinned:hover {
  background-color: var(--clr-bright); /* #fafdff is very close to white */
}

.pinned:active {
  background-color: var(--clr-blue-wash-medium);
  transition: background 0s;
}

.pinned-scroll {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  border-radius: 0.25rem 0 0 0.25rem;
  background-color: var(--clr-background-extra-light-gray);
  justify-content: space-evenly;
  height: 100%;
  padding: 0.2rem;
  margin-left: 0.35rem;
  user-select: none;
}

.pinned-scroll .dot {
  width: 0.3rem;
  height: 0.3rem;
  border-radius: 50%;
  background-color: var(--clr-text-tertiary);
  user-select: none;
}

.pinned-scroll .adot {
  width: 0.45rem;
  height: 0.45rem;
  border-radius: 50%;
  background-color: var(--clr-light-blue-accent);
  user-select: none;
}

#pinned-wrapper:hover .menuTrigger {
  opacity: 0.9;
}
#pinned-wrapper:hover .menuTrigger a {
  color: var(--clr-text-secondary);
}

.pinned-menu {
  position: absolute;
  display: flex;
  flex-direction: column;
  background-color: var(--clr-pinned-menu-bg);
  border-radius: 0 0.25rem 0.25rem 0;
  justify-content: space-evenly;
  top: 0;
  bottom: 0;
  right: 0;
}

.pinned-menu .menuTrigger {
  position: relative;
  right: 0;
}
/* END of pinned messages */

/* Contact attachments */
.contact-card {
  position: relative;
  background-color: var(--clr-background-off-white);
  border-radius: 0.5rem;
  display: flex;
  flex-direction: column;
  min-width: 14rem;
}

.contact-card .avatar-box {
  position: relative;
  width: 1.8rem;
  height: 1.8rem;
  font-size: 1rem;
  margin-right: 0.75rem;
  margin-bottom: 0;
}

.contact-card .contact-body {
  align-items: center;
  background-color: var(--clr-background-blue-gray-50);
  display: flex;
  padding: 0.75rem;
  border-radius: 0.5rem 0.5rem 0 0;
  border-bottom: none;
}

.contact-card .contact-body .name-box {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.contact-card .contact-body .name-box .name {
  color: var(--clr-text-primary);
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.contact-card .contact-body .name-box .org {
  color: var(--clr-text-secondary);
  font-size: 90%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 300;
}

.contact-card .contact-actions {
  display: flex;
  justify-content: space-evenly;
  align-items: center;
  padding: 0 0.5rem;
  border-radius: 0 0 0.5rem 0.5rem;
  border-top: none;
  background-color: var(--clr-bright);
}

.contact-card .contact-actions a {
  cursor: pointer;
}

.contact-card .contact-actions .divider {
  height: 1.8rem;
  opacity: 0.5;
}

/* END of contact attachments */

/*
 Drag-and-drop area.
 */
.drag-n-drop {
  display: flex;
  border: dashed var(--clr-drag-n-drop-border) 0.15rem;
  border-radius: 1rem;
  background-color: var(--clr-drag-n-drop-bg);
  position: absolute;
  top: 1.5rem;
  bottom: 1.5rem;
  left: 1.5rem;
  right: 1.5rem;
  z-index: 3;
  justify-content: center;
  align-items: center;
  font-size: 2rem;
  color: var(--clr-drag-n-drop-text);
  outline: 0.5rem solid var(--clr-drag-n-drop-outline);
}

.country-flag {
  display: inline-block;
  font-size: larger;
}

.dial-code {
  white-space: nowrap;
  display: inline-block;
  cursor: pointer;
  vertical-align: middle;
  margin-bottom: 0.15rem;
}

ul.phone-country-selector {
  list-style: none;
  overflow-x: hidden;
}

ul.phone-country-selector > li {
  position: relative;
  font-weight: lighter;
  padding: 0.25rem 0.5rem 0.15rem 0.5rem;
  cursor: pointer;
  width: 100%;
}

ul.phone-country-selector > li:hover {
  background-color: var(--clr-background-blue-gray-50); /* blue-gray 50 highlight */
}
ul.phone-country-selector > li.selected {
  background-color: var(--clr-background-blue-gray-100); /* blue-gray 100 highlight */
}

ul.phone-country-selector .dial-code {
  position: absolute;
  right: 0.5rem;
  color: var(--clr-primary-action);
  font-weight: normal;
}

ul.phone-country-selector span {
  display: inline-block;
}

ul.phone-country-selector span.country {
  text-overflow: ellipsis;
  overflow-x: hidden;
}

.image-grid {
  position: relative;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(7rem, 1fr));
  gap: 0.35rem;
  padding: 0.25rem;
}

.image-grid-cell {
  padding: 0;
  margin: 0;
  width: 100%;
  height: 7rem;
  overflow: hidden;
  border-radius: 0.25rem;
  border: 1.5px solid transparent;
  cursor: pointer;
  box-shadow: 0 0 0.2rem var( --clr-shadow-hr-inset); /* gray */
}

.image-grid-cell img {
  object-fit: cover;
}

.image-grid-cell.selected {
  border: 1.5px solid var(--clr-secondary-accent);
}

img.inverted {
  filter: invert(1);
}

div.toast {
  visibility: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  position: absolute;
  min-width: 10rem;
  padding: 0.5rem 1rem;
  height: 3rem;
  z-index: 3;
  font-weight: lighter;
  color: var(--clr-toast-text);
  background-color: var(--clr-toast-bg);
  border-radius: 0.5rem;
  box-shadow: 1px 2px 0.3rem var(--clr-shadow-gray-strong); /* gray */
  bottom: 2rem;
  left: 50%;
  translate: -50%;
}

div.toast.show {
  visibility: visible;
  animation: fadein 0.5s, fadeout 0.5s 2.5s;
}

@keyframes fadein {
  from {
    bottom: 0;
    opacity: 0;
  }
  to {
    bottom: 2rem;
    opacity: 1;
  }
}

@keyframes fadeout {
  from {
    bottom: 2rem;
    opacity: 1;
  }
  to {
    bottom: 0;
    opacity: 0;
  }
}

/*
 Very wide monitor.
 */
@media (min-width: 1440px){
  #app-container {
    max-width: 114rem;
  }
}

/*
 Mobile styles.
 */

@media (max-width: 960px) {
  #mountPoint {
    padding: 0;
  }

  .pinned {
    width: 16rem;
  }
}

@media (max-width: 640px) {
  #app-container {
    width: 100%;
    border-radius: 0;
    box-shadow: none;
  }

  #sidepanel {
    width: 100%;
  }

  #info-view {
    width: 100%;
  }

  /* Bottom sheet rather than a dialog */
  .forward-dialog {
    border-radius: 0.3rem 0.3rem 0 0;
    margin: auto 0 0 0;
    width: 100%;
  }

  /* Must make it a bit visible on mobile because there is no :hover */
  .menuTrigger {
    opacity: 0.3;
  }

  #send-message-input {
    /* Just an indicator that the screen is in mobile mode */
    transition-property: -tinode-mobile;
  }

  #pinned-wrapper {
    height: 3.5rem;
    margin: 0.25rem;
  }

  .pinned {
    width: unset;
  }

  #video-container.minimized {
    flex-direction: row;
    left: 0;
    top: var(--caption-panel-height);
    width: 100%;
    height: 11rem;
    border-radius: unset;
    box-shadow: 0 0 0.5rem var(--clr-shadow-gray-strong);
  }

  #controls.minimized {
    flex-direction: column;
    row-gap: 0.5rem;
    bottom: auto;
    column-gap: unset;
    right: 1rem;
  }

  .minimized .call-party {
    border-radius: unset;
    box-shadow: unset;
  }

  .call-party.self {
    bottom: 8.5rem;
    border-radius: unset;
  }
}


================================================
FILE: firebase-init.js
================================================
// Get these values for your project from the https://console.firebase.google.com/
const FIREBASE_INIT = {
  // Set up a web application in console then get the config object.
  // The following keys are copied from the object:
  apiKey: "AIzaSyD6X4ULR-RUsobvs1zZ2bHdJuPz39q2tbQ",
  messagingSenderId: "114126160546",
  projectId: "tinode-1000",
  appId: "1:114126160546:web:aca6ea2981feb81fb44dfb",
  // Project Settings -> Cloud Messaging -> Web configuration -> Web Push certificates.
  // This value IS NOT included in the generated js config you get from
  // the firebase console. It needs to be added separately.
  messagingVapidKey: "BOgQVPOMzIMXUpsYGpbVkZoEBc0ifKY_f2kSU5DNDGYI6i6CoKqqxDd7w7PJ3FaGRBgVGJffldETumOx831jl58",
  // Google analytics tag. Uncomment and use one you got from https://analytics.google.com/.
  // measurementId: "G-ABCDEF1234"
};


================================================
FILE: img/bkg/index.json
================================================
{
  "patt": [
    {"name": "a00.png", "size": 200}, {"name": "a01.jpg", "size": 384}, {"name": "a02.jpg", "size": 384},
    {"name": "a03.jpg", "size": 384}, {"name": "a04.png", "size": 400}, {"name": "a05.jpg", "size": 400},
    {"name": "a06.jpg", "size": 256}, {"name": "a07.jpg", "size": 384}, {"name": "a08.jpg", "size": 384},
    {"name": "a09.jpg", "size": 400}, {"name": "a10.jpg", "size": 256}, {"name": "a11.png", "size": 200}
  ],
  "img": [
    {"name": "w01.jpg", "pr": "p01.jpg"}, {"name": "w02.jpg", "pr": "p02.jpg"}, {"name": "w03.jpg", "pr": "p03.jpg"},
    {"name": "w04.jpg", "pr": "p04.jpg"}, {"name": "w05.jpg", "pr": "p05.jpg"}, {"name": "w06.jpg", "pr": "p06.jpg"},
    {"name": "w07.jpg", "pr": "p07.jpg"}, {"name": "w08.jpg", "pr": "p08.jpg"}, {"name": "w09.jpg", "pr": "p09.jpg"},
    {"name": "w10.jpg", "pr": "p10.jpg"}, {"name": "w11.jpg", "pr": "p11.jpg"}, {"name": "w12.jpg", "pr": "p12.jpg"},
    {"name": "w13.jpg", "pr": "p13.jpg"}, {"name": "w14.jpg", "pr": "p14.jpg"}, {"name": "w15.jpg", "pr": "p15.jpg"},
    {"name": "w16.jpg", "pr": "p16.jpg"}, {"name": "w17.jpg", "pr": "p17.jpg"}, {"name": "w18.jpg", "pr": "p18.jpg"},
    {"name": "w19.jpg", "pr": "p19.jpg"}, {"name": "w20.jpg", "pr": "p20.jpg"}, {"name": "w21.jpg", "pr": "p21.jpg"},
    {"name": "w22.jpg", "pr": "p22.jpg"}, {"name": "w23.jpg", "pr": "p23.jpg"}, {"name": "w24.jpg", "pr": "p24.jpg"}
  ]
}


================================================
FILE: index-dev.html
================================================
<!-- DEVELOPMENT version of the web app. -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Tinode</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="application-name" content="Tinode Web, version for developers" />
    <meta name="description" content="Tinode instant messenger, development version" />
    <meta name="application-url" content="https://web.tinode.co/">
    <!-- Browser styling for Chrome, FF, Opera -->
    <meta name="theme-color" content="#3949AB" />
    <!-- Ask Google not to offer page translation -->
    <meta name="google" value="notranslate" />
    <!-- Open Graph description -->
    <meta name="og:url" content="https://web.tinode.co/">
    <meta name="og:title" content="Tinode Web Development">
    <meta name="og:image" content="img/og-logo.jpeg">
    <meta name="og:description" content="Tinode instant messenger, development version" />
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="mobile-web-app-capable" content="yes">
    <link rel="manifest" href="manifest.json" />
    <link rel="shortcut icon" id="shortcut-icon" href="img/logo32x32.png" type="image/png" />
    <link rel="apple-touch-icon" sizes="192x192" href="img/logo192.png" type="image/png" />
    <link rel="canonical" href="https://web.tinode.co/" />
    <!-- Google's Roboto font -->
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,500,700,700i" />
    <!-- Google's material design icons -->
    <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
    <!-- Styles for local elements -->
    <link rel="stylesheet" href="css/base.css" />
    <!-- Polyfill Intl.Segmenter for Firefox 124 and earlier. This can be safely removed in the end of 2024. -->
    <script crossorigin="anonymous" src="https://polyfill-fastly.io/v3/polyfill.min.js?features=Intl.Segmenter"></script>
    <!-- ReactJS -->
    <script crossorigin="anonymous" src="https://cdn.jsdelivr.net/npm/react@18/umd/react.development.js"></script>
    <script crossorigin="anonymous" src="https://cdn.jsdelivr.net/npm/react-dom@18/umd/react-dom.development.js"></script>
    <!-- React-Intl for translations -->
    <script crossorigin="anonymous" src="https://cdn.jsdelivr.net/npm/react-intl@7/react-intl.iife.js"></script>
    <!-- Displaying QR code with ID of the topic -->
    <script crossorigin="anonymous" src="https://cdn.jsdelivr.net/npm/qrcodejs@1.0.0/qrcode.js"></script>
  </head>

  <body>
    <noscript><div id="noscript-message"><div id="noscript-title">Javascript support is required.</div>
      <div id="noscript-content">It appears JavaScript is turned off or is not supported by your browser.
        TinodeWeb does not work without JavaScript. Please enable JavaScript by changing your browser options,
        then <a href="">try again</a>.
      </div>
    </div></noscript>
    <div id="mountPoint"></div>
    <script src="firebase-init.js"></script>
    <script src="umd/tinode.dev.js"></script>
    <script src="umd/index.dev.js"></script>
  </body>
</html>


================================================
FILE: index.html
================================================
<!DOCTYPE html>
<html>
<head>
<title>Tinode</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="application-name" content="Tinode Web" />
<meta name="description" content="Tinode instant messenger in a browser" />
<meta name="application-url" content="https://web.tinode.co/">
<meta name="theme-color" content="#3949AB" />
<meta name="google" value="notranslate" />
<meta name="format-detection" content="telephone=no" />
<meta name="og:url" content="https://web.tinode.co/">
<meta name="og:title" content="Tinode Web">
<meta name="og:image" content="img/og-logo.jpeg">
<meta name="og:description" content="Tinode instant messenger in a browser" />
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="mobile-web-app-capable" content="yes">
<link rel="manifest" href="manifest.json" />
<link rel="shortcut icon" id="shortcut-icon" href="img/logo32x32.png" type="image/png" />
<link rel="apple-touch-icon" sizes="192x192" href="img/logo192.png" type="image/png" />
<link rel="canonical" href="https://web.tinode.co/" />
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,500,700,700i" />
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
<link rel="stylesheet" href="css/base.min.css" />
<script crossorigin="anonymous" src="https://polyfill-fastly.io/v3/polyfill.min.js?features=Intl.Segmenter"></script>
<script crossorigin="anonymous" src="https://cdn.jsdelivr.net/npm/react@18.3.1/umd/react.production.min.js"></script>
<script crossorigin="anonymous" src="https://cdn.jsdelivr.net/npm/react-dom@18.3.1/umd/react-dom.production.min.js"></script>
<script crossorigin="anonymous" src="https://cdn.jsdelivr.net/npm/react-intl@7.1.6/react-intl.iife.min.js"></script>
<script crossorigin="anonymous" src="https://cdn.jsdelivr.net/npm/qrcodejs@1.0.0/qrcode.min.js"></script>
</head>
<body>
<noscript><div id="noscript-message"><div id="noscript-title">Javascript support is required.</div>
<div id="noscript-content">It appears JavaScript is turned off or is not supported by your browser.
TinodeWeb does not work without JavaScript. Please enable JavaScript by changing your browser options,
then <a href="">try again</a>.</div></div></noscript>
<div id="mountPoint"></div>
<script src="firebase-init.js"></script>
<script src="umd/tinode.prod.js"></script>
<script src="umd/index.prod.js"></script>
</body>
</html>


================================================
FILE: manifest.json
================================================
{
  "name": "Tinode",
  "short_name": "Tinode",
  "description": "Tinode Web App.\nSee more at https://tinode.co/",
  "categories": ["chat", "communication", "productivity"],
  "icons": [
    {
      "src":"img/logo96.png",
      "sizes": "96x96",
      "type": "image/png"
    },
    {
      "src":"img/logo192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "img/logo.svg",
      "type": "image/svg+xml",
      "sizes": "512x512"
    }
  ],
  "start_url": "/",
  "background_color": "silver",
  "theme_color": "#3949AB",
  "display": "standalone",
  "gcm_sender_id": "103953800507",
  "prefer_related_applications": true,
  "related_applications": [
    {
      "platform": "play",
      "url": "https://play.google.com/store/apps/details?id=co.tinode.tindroidx",
      "id": "co.tinode.tindroidx"
    },
    {
      "platform": "itunes",
      "url": "https://apps.apple.com/us/app/tinode/id1483763538"
    }
  ],
  "permissions": {
    "audio-capture": {
      "description": "Required for recording voice messages"
    }
  }
}


================================================
FILE: package.json
================================================
{
  "name": "tinode-webapp",
  "description": "Tinode messenger for the web",
  "version": "0.25.2",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/tinode/webapp.git"
  },
  "scripts": {
    "start": "echo 'Read installation instructions'",
    "build": "npm run vers && npm run build:css && npm run extract && npm run build:i18n && npm run build:prod && npm run build:dev",
    "clean": "rm umd/* && rm css/base.min.css && rm src/i18n.min/*",
    "build:css": "postcss css/base.css > css/base.min.css",
    "build:dev": "webpack --mode development",
    "build:prod": "webpack --mode production",
    "build:i18n": "node scripts/i18n.js",
    "i18n:missing": "node scripts/i18n.js missing",
    "i18n:obsolete": "node scripts/i18n.js obsolete",
    "vers": "node scripts/gen-version.js",
    "extract": "formatjs extract \"src/**/*.{js,jsx}\" --out-file src/i18n/ex/base-en.json --id-interpolation-pattern '[sha512:contenthash:base64:6]'",
    "compile": "formatjs compile",
    "test": "jest"
  },
  "browserslist": [
    "defaults"
  ],
  "files": [
    "umd/*.js",
    "umd/*.map",
    "audio/*.m4a",
    "css/base.css",
    "css/base.min.css",
    "img/*.png",
    "img/*.svg",
    "img/*.jpeg",
    "img/bkg/*.jpg",
    "img/bkg/*.png",
    "img/bkg/*.json",
    "index-dev.html",
    "index.html",
    "manifest.json",
    "service-worker.js",
    "version.js"
  ],
  "keywords": [
    "chat",
    "instant-messenger",
    "message",
    "messenger",
    "react",
    "web"
  ],
  "locales": [
    "ar",
    "de",
    "en",
    "es",
    "fr",
    "it",
    "ko",
    "ro",
    "ru",
    "th",
    "uk",
    "vi",
    "zh",
    "zh-TW"
  ],
  "main": "umd/index.prod.js",
  "bugs": {
    "url": "https://github.com/tinode/webapp/issues"
  },
  "homepage": "https://github.com/tinode/chat",
  "email": "info@tinode.co",
  "author": "Tinode Authors <info@tinode.co>",
  "license": "Apache-2.0",
  "dependencies": {
    "firebase": "^11.0.0",
    "libphonenumber-js": "^1.10.40",
    "qrcodejs": "^1.0.0",
    "react": "^18.3.0",
    "react-dom": "^18.3.0",
    "react-intl": "^7.0.0",
    "tinode-sdk": "^0.25.2",
    "webm-duration-fix": "^1.0.4"
  },
  "devDependencies": {
    "@babel/core": "^7.22.10",
    "@babel/preset-env": "^7.22.10",
    "@babel/preset-react": "^7.22.5",
    "@formatjs/cli": "^6.1.3",
    "babel-loader": "^10.0.0",
    "babel-plugin-formatjs": "^10.5.3",
    "browserslist": "^4.21.10",
    "copy-webpack-plugin": "^13.0.0",
    "cssnano": "^7.0.6",
    "glob": "^13.0.0",
    "jest": "^30.0.0",
    "postcss": "^8.4.27",
    "postcss-cli": "^11.0.0",
    "webpack": "^5.88.2",
    "webpack-cli": "^6.0.0"
  }
}


================================================
FILE: postcss.config.js
================================================
module.exports = {
    plugins: [
        require('cssnano')({
            preset: 'default',
        }),
    ],
};


================================================
FILE: push.md
================================================
# Push notifications

If you want to use the app with your own server and want web push notification to work you have to set them up:

* Register at https://firebase.google.com/, set up the project if you have not done so already.
* Follow instructions to create a web application https://support.google.com/firebase/answer/9326094 in your project.
* Follow instructions at https://support.google.com/firebase/answer/7015592 to get a Firebase configuration object ("Firebase SDK snippet").
* Locate `firebase-init.js` in the root folder of your copy of TinodeWeb app. Copy-paste the following keys from the configuration object to `firebase-init.js`: `apiKey`, `messagingSenderId`, `projectId`, `appId` (you may copy all keys).
* Copy `Web Push certificate` (Project Settings -> Cloud Messaging -> Web configuration -> Web Push certificates) to `messagingVapidKey` field in `firebase-init.js`.
* Double check that `firebase-init.js` contains the following keys: `apiKey`, `messagingSenderId`, `projectId`, `appId`, `messagingVapidKey`. The file may contain other optional keys.
* Copy Google-provided server key to `tinode.conf`, see details [here](https://github.com/tinode/chat/blob/master/docs/faq.md#q-how-to-setup-fcm-push-notifications).


================================================
FILE: scripts/gen-version.js
================================================
const fs = require('fs');
const version = require('../package.json').version;

function writeVersion(fileName, useExport) {
  fs.writeFile(fileName,
    '// This is a generated file. Don\'t edit.\n\n'+
    `${useExport ? 'export ' : ''}const PACKAGE_VERSION = "${version}";\n`,
    { flag: 'w' },
    (err) => {
      if (err) {
          return console.error(err);
      }
    }
  );
}

writeVersion('./src/version.js', true);
writeVersion('./version.js', false);


================================================
FILE: scripts/i18n.js
================================================
// 1. Updates translations files with new messages, mark no longer needed translations as obsolete.
// 2. Takes all translations and groups them into a single file.
// 3. When called with parameters 'missing' or 'obsolete' writes missing and obsolete translations to console.

const fs = require('fs');
const path = require('path');
const globSync = require('glob').sync;

const EXTRACTED_STRINGS = './src/i18n/ex/base-en.json';
const BASE_LANG        = 'en';
const LANG_PATTERN     = './src/i18n/*.json';
const LANG_PATTERN_ONE = './src/i18n/%s.json';
const OUTPUT_PATTERN   = './src/i18n.min/%s.json';

const args = process.argv.slice(2);

function getLocaleFromFileName(filename) {
  const parts = filename.split(path.sep);
  return parts[parts.length - 1].split('.json')[0];
}

function printf(str) {
  const args = [].slice.call(arguments, 1);
  let i = 0;
  return str.replace(/%s/g, () => args[i++]);
}

// Called with one or two parameters?
if (args[0] == 'missing' || args[0] == 'obsolete') {
  // Extract missing or obsolete translations as requested.
  // Read either all or just one translation.
  const pattern = args[1] ? printf(LANG_PATTERN_ONE, args[1]) : LANG_PATTERN;
  const extracted = globSync(pattern)
    .map((filename) => {
      const locale = getLocaleFromFileName(filename);
      const translated = JSON.parse(fs.readFileSync(filename, 'utf8'));

      const dest = {};
      // Copy messages while skipping missing and obsolete ones.
      for (let key in translated) {
        if ((args[0] == 'missing' && translated[key].missing) ||
          (args[0] == 'obsolete' && translated[key].obsolete)) {
          dest[key] = translated[key];
        }
      }

      return { [locale]: dest };
    })
    .reduce((collection, descriptors) => {
      return { ...collection, ...descriptors };
    }, {});

  console.log(JSON.stringify(extracted, null, 2)+"\n");
  return;
}

// The formatjs/cli saves extracted messages into a file {'message_id': {defaultMessage: 'default message text', description: '...'}, ...}.
// Rewrite them into a single file en.json {'message_id': 'default message text', }.

// Read master-set of messages in default language.
const baseMessages = JSON.parse(fs.readFileSync(EXTRACTED_STRINGS, 'utf8'));

// Find messages present in baseMessages but missing in translations and vice versa.
// Mark missing or obsolete messages as such.
globSync(LANG_PATTERN)
  .map((filename) => {
    const translated = JSON.parse(fs.readFileSync(filename, 'utf8'));
    const locale = getLocaleFromFileName(filename);

    // Refresh existing entries with possible new descriptions and default messages, add missing.
    Object.entries(baseMessages).forEach((ent) => {
      const [key, value] = ent;
      let translation = translated[key] ? translated[key].translation : "";
      if (!translation && locale == BASE_LANG) {
        translation = value.defaultMessage;
      }

      translated[key] = {
        translation: translation,
        defaultMessage: value.defaultMessage,
        description: value.description,
        missing: !translation,
        obsolete: false
      };
    });

    // Find no longer needed messages.
    Object.entries(translated).forEach((ent) => {
      const [key, value] = ent;
      if (!baseMessages[key] && translated[key]) {
        // Obsolete, no longer missing.
        translated[key].missing = !translated[key].translation;
        translated[key].obsolete = true;
      }
    });

    fs.writeFileSync(filename, JSON.stringify(translated, null, 2)+"\n");
  });

// Legacy: Combine all translations into a single json {"lang_1": {...}, "lang_2: {...}"}
// while removing messages marked as missing or obsolete.
// New way: Emit one file per language with all unnecessary data stripped.

// Read all translations.
const messages = globSync(LANG_PATTERN)
  .map((filename) => {
    const locale = getLocaleFromFileName(filename);
    const translated = JSON.parse(fs.readFileSync(filename, 'utf8'));

    const dest = {};
    // Copy messages while skipping missing and obsolete ones.
    for (let key in translated) {
      if (!translated[key].missing && !translated[key].obsolete) {
        dest[key] = translated[key].translation;
      }
    }

    return { [locale]: dest };
  })
  .reduce((collection, descriptors) => {
    return { ...collection, ...descriptors };
  }, {});

// Write minified translation files, one per language.
for (let lang in messages) {
  fs.writeFileSync(printf(OUTPUT_PATTERN, lang), JSON.stringify(messages[lang]));
}


================================================
FILE: service-worker.js
================================================
// Must be located at the root.
importScripts('https://cdn.jsdelivr.net/npm/firebase@9.14.0/firebase-app-compat.js');
importScripts('https://cdn.jsdelivr.net/npm/firebase@9.14.0/firebase-messaging-compat.js');
importScripts('firebase-init.js');
importScripts('version.js');

// Channel to notify the webapp. There is no BroadcastChannel in Safari.
const webAppChannel = (typeof BroadcastChannel == 'function') ?
  new BroadcastChannel('tinode-sw') : null;

// Basic internationalization.
const i18n = {
  'ar': {
    'new_message': "رسالة جديدة",
    'new_chat': "محادثة جديدة",
  },
  'de': {
    'new_message': "Neue Nachricht",
    'new_chat': "Neuer Chat",
  },
  'en': {
    'new_message': "New message",
    'new_chat': "New chat",
  },
  'fr': {
    'new_message': "Nouveau message",
    'new_chat': "Nouvelle conversation",
  },
  'es': {
    'new_message': "Nuevo mensaje",
    'new_chat': "Nueva conversación",
  },
  'it': {
    'new_message': "Nuovo Messaggio",
    'new_chat': "Nuova Chat",
  },
  'ko': {
    'new_message': "새로운 메시지",
    'new_chat': "새로운 채팅",
  },
  'ro': {
    'new_message': "Mesaj nou",
    'new_chat': "Chat nou",
  },
  'ru': {
    'new_message': "Новое сообщение",
    'new_chat': "Новый чат",
  },
  'th': {
    'new_message': "ข้อความใหม่",
    'new_chat': "แชทใหม่",
  },
  'uk': {
    'new_message': "Нове повідомлення",
    'new_chat': "Новий чат",
  },
  'vi': {
    'new_message': "Tin nhắn mới",
    'new_chat': "Cuộc trò chuyện mới",
  },
  'zh': {
    'new_message': "新讯息",
    'new_chat': "新聊天",
  },
  'zh-TW': {
    'new_message': "新訊息",
    'new_chat': "新聊天",
  }
};

self.i18nMessage = function (id) {
  if (!id) {
    return null;
  }
  // Choose translations: given something like 'de-CH', try 'de-CH' then 'de' then 'en'.
  const lang = i18n[self.locale] || i18n[self.baseLocale] || i18n['en'];
  // Try finding string by id in the specified language, if missing try English, otherwise use the id itself
  // as the last resort.
  return lang[id] || i18n['en'][id] || id;
}

firebase.initializeApp(FIREBASE_INIT);
const fbMessaging = firebase.messaging();

// This method shows the push notifications while the window is in background.
fbMessaging.onBackgroundMessage(payload => {
  // Notify webapp that a message was received.
  if (webAppChannel) {
    webAppChannel.postMessage(payload.data);
  }

  if (payload.data.silent == 'true') {
    // No need to show anything.
    return;
  }

  const titles = { 'msg': 'new_message', 'sub': 'new_chat' };
  const pushType = payload.data.what || 'msg';
  const title = payload.data.title || self.i18nMessage(titles[pushType]);
  if (title) {
    const options = {
      body: payload.data.content || '', // TODO: content for 'sub' should be topic's or user's title.
      icon: '/img/logo96.png', // TODO: use topic's or user's avatar (would have to fetch for 'sub', read from db for 'msg').
      badge: '/img/badge96.png',
      tag: payload.data.topic || undefined,
      data: {
        topic: payload.data.topic
      }
    };
    return self.registration.showNotification(title, options);
  }
});

// Update service worker immediately for both the current client
// and all other active clients.
self.addEventListener('install', _ => {
  self.skipWaiting();
});

// This code handles a click on notification: takes
// the user to the browser tab with the chat or opens a new tab.
self.addEventListener('notificationclick', event => {
  const data = event.notification.data;
  event.notification.close();
  if (!data) {
    console.info("Missing 'data' in notification", event.notification);
    return;
  }

  const urlHash = '#/' + data.topic;

  event.waitUntil(self.clients.matchAll({
    type: 'window',
    includeUncontrolled: true
  })
    .then(windowClients => {
      let anyClient = null;
      for (let i = 0; i < windowClients.length; i++) {
        const url = new URL(windowClients[i].url);
        if (url.hash.includes(data.topic)) {
          // Found the Tinode tab with the right topic open.
          return windowClients[i].focus();
        } else {
          // This will be the least recently used tab.
          anyClient = windowClients[i];
        }
      }

      // Found tab with Tinode on a different topic,
      // navigate to the right topic.
      if (anyClient) {
        const url = new URL(anyClient.url);
        url.hash = urlHash;
        return anyClient.focus().then(thisClient => {
          return thisClient.navigate(url);
        });
      }

      // Did not find a Tinode browser tab. Open one.
      const url = new URL(self.location.origin);
      url.hash = urlHash;
      return clients.openWindow(url);
    }));
});

// This is needed for 'Add to Home Screen'.
self.addEventListener('fetch', event => {
  if (event.request.method != 'GET') {
    return;
  }

  event.respondWith((async _ => {
    //  Try to find the response in the cache.
    const cache = await caches.open(PACKAGE_VERSION);

    const reqUrl = new URL(event.request.url);
    // Using ignoreSearch=true to read cached images and docs despite different auth signatures.
    const cachedResponse = await cache.match(event.request, { ignoreSearch: (self.location.origin == reqUrl.origin) });
    if (cachedResponse) {
      return cachedResponse;
    }
    // Not found in cache.
    const response = await fetch(event.request);
    if (!response || response.status != 200 || response.type != 'basic') {
      return response;
    }
    if (reqUrl.protocol == 'http:' || reqUrl.protocol == 'https:') {
      await cache.put(event.request, response.clone());
    }
    return response;
  })());
});

// This code gets the human language from the webapp.
self.addEventListener('message', event => {
  const data = JSON.parse(event.data);

  // The locale is used for selecting strings in an appropriate language.
  self.locale = data.locale || '';
  self.baseLocale = self.locale.toLowerCase().split(/[-_]/)[0];
});


================================================
FILE: src/config.js
================================================
import { PACKAGE_VERSION } from './version.js';

// Name of this application, used in the User-Agent.
export const APP_NAME = 'TinodeWeb/' + (PACKAGE_VERSION || '0.24');

// API key. Use https://github.com/tinode/chat/tree/master/keygen to generate your own
export const API_KEY = 'AQEAAAABAAD_rAp4DJh05a1HAwFT3A6K';

// The array of possible hosts to connect to.
export const KNOWN_HOSTS = {hosted: 'web.tinode.co', local: 'localhost:6060'};

// Default host name and port to connect to.
export const DEFAULT_HOST = KNOWN_HOSTS.hosted;

// Enable console logging.
export const LOGGING_ENABLED = true;

// Minimum time between two keypress notifications, milliseconds.
export const KEYPRESS_DELAY = 3_000;
// Delay before sending a read notification, milliseconds.
export const READ_DELAY = 1_500;

// The default shortest allowed tag length. Matches the value on the server.
export const MIN_TAG_LENGTH = 2;
// The default greatest allowed tag length. Matches the value on the server.
export const MAX_TAG_LENGTH = 96;
// The default maximum number of tags allowed. Matches the value on the server.
export const MAX_TAG_COUNT = 16;

// Access mode for P2P subscriptions initiated by the current user.
export const DEFAULT_P2P_ACCESS_MODE = 'JRWPS';
// Access mode for new group topics created by the current user.
export const NEW_GRP_ACCESS_MODE = 'JRWPSAO';
// Access mode for a channel.
export const CHANNEL_ACCESS_MODE = 'JR';

// Access mode for no access.
export const NO_ACCESS_MODE = 'N';

// Mediaquery breakpoint between desktop and mobile, in px. Should match the value
// in @media (max-size: 640px) in base.css
export const MEDIA_BREAKPOINT = 640;
// Size of css 'rem' unit in pixels. Default 1rem = 10pt = 13px.
export const REM_SIZE = 13;

// Size of the avatar image: when image dimensions are greater or the image is not square, it's resized to
// a square of this size or less.
export const AVATAR_SIZE = 384;

// Maximum size of an avatar in bytes for sending in-band. Bigger avatars will be sent out of band (as uploads).
export const MAX_AVATAR_BYTES = 4096;

// Size of the broken_image shown in MessagesView
export const BROKEN_IMAGE_SIZE = 32;

// Size of video preview when dimensions are missing.
export const NO_DIMENSIONS_VIDEO = 128;

// Number of chat messages to fetch in one call.
export const MESSAGES_PAGE = 24;

// Default maximum in-band (included directly into the message) attachment size which fits into
// a message of 256K in size. Used when the server-provided value is unavailable. The actual
// binary size of the attachment should be smaller due to base64 encoding expansion and some overhead,
// for instance 1024 bytes.
// Increase this limit to a greater value in production, if desired. Also increase
// max_message_size in the server config.
export const MAX_INBAND_ATTACHMENT_SIZE = 262_144;

// Default absolute maximum attachment size to be used with the server = 8MB.
// Used when the server-provided value is unavailable. Increase to something like 100MB in production.
export const MAX_EXTERN_ATTACHMENT_SIZE = 1 << 23;

// Maximum allowed linear dimension (pixels) of an image sent inline. Larger images will be shrunk
// to make the larger dimension fit under this size. You may want to adjust it to 1600 or
// 2400 for production.
export const MAX_IMAGE_DIM = 1024;

// Linear dimensions of image preview: shrink image under this size for previews.
export const IMAGE_PREVIEW_DIM = 64;

// Linear dimensions of video screencapture: shrink image under this size for previews.
export const VIDEO_PREVIEW_DIM = 96;

// Linear dimensions of image thumbnail: shrink image under this size for thumbnails in reply quote previews.
export const IMAGE_THUMBNAIL_DIM = 36;
// Width of video thumbnail: allow it to be wider, but not taller. Use IMAGE_THUMBNAIL_DIM for height.
export const VIDEO_THUMBNAIL_WIDTH = 48;

// Maximum number of online users to be shown in a topic title bar. Others will be
// hidden under "+X more"
export const MAX_ONLINE_IN_TOPIC = 4;

// Maximum length of user name, topic title, and private comment.
export const MAX_TITLE_LENGTH = 60;
// Maximum length of topic description.
export const MAX_TOPIC_DESCRIPTION_LENGTH = 360;
// Maximum length of user name when displaying a video call.
export const MAX_PEER_TITLE_LENGTH = 24;

// Length of message previews in chat list, in characters.
export const MESSAGE_PREVIEW_LENGTH = 80;

// Length of a quote in quoted reply (for outgoing messages).
export const QUOTED_REPLY_LENGTH = 30;
// Length of a preview of a forwarded message.
export const FORWARDED_PREVIEW_LENGTH = 84;
// Length of preview for a message being edited.
export const EDIT_PREVIEW_LENGTH = 48;

// Minimum duration of an audio recording in milliseconds (2 sec).
export const MIN_DURATION = 2_000;
// Maximum duration of an audio recording in milliseconds (10 min).
export const MAX_DURATION = 600_000;

// Link for "Contact Us".
export const LINK_CONTACT_US = 'mailto:support@tinode.co';

// Link to Privacy Policy.
export const LINK_PRIVACY_POLICY = 'https://tinode.co/privacy.html';

// Link to Terms of Service.
export const LINK_TERMS_OF_SERVICE = 'https://tinode.co/terms.html';

// When user starts a P2P topic, automatic subscription does not
// happen until the first message. Setting this option to true enables
// immediate subscription.
export const IMMEDIATE_P2P_SUBSCRIPTION = false;

// URL schemes permitted to appear in links (i.e. no javascript: scheme).
export const CLICKABLE_URL_SCHEMES = ['http', 'https', 'ftp', 'ftps'];

// Size of the QR code in the app.
export const QRCODE_SIZE = 128;

// How much time has to pass to consider computer awoken from sleep (80 sec).
// Chrome throttles ticker events in inactive tabs to once per minute. This
// value ensures that these once-a-minute events do not trigger a reconnect.
export const WAKE_UP_TIMEOUT = 80000;
// Timer interval between checks if computer woke up from sleep (1 sec).
export const WAKE_UP_TICK = 1000;

// Swipe distance to register as a gesture, in pixels.
export const MIN_SWIPE_DISTANCE = REM_SIZE * 3;

// Self-topic avatar as an SVG icon encoded as data URI
export const SELF_AVATAR_URI = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48c3ZnIHZpZXdCb3g9IjAgMCAxNyAxNyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMy41NjIgMXYxNS40NTlsNC42ODYtMy4yNyA0Ljc1MiAzLjI2di0xNS40NDloLTkuNDM4ek0xMiAxNC41NTFsLTMuNzU2LTIuNTc4LTMuNjgxIDIuNTY4di0xMi41NDFoNy40Mzd2MTIuNTUxeiIgZmlsbD0iIzU1NTU1NSIgLz48L3N2Zz4=' // eslint-disable-line max-len

// Toast display duration, milliseconds.
export const TOAST_DURATION = 3_000;

// Initial/default color scheme.
export const DEFAULT_COLOR_SCHEME = 'auto';

// Default text size in points.
export const DEFAULT_TEXT_SIZE = 10;

// MIME type for the legacy Drafty form-response data.
export const DRAFTY_FR_MIME_TYPE_LEGACY = 'application/json'; // Remove in 2026.

// Path to wallpaper images.
export const WALLPAPER_DEFAULTS = {type: 'patt', index: 0, path:'img/bkg/'};


================================================
FILE: src/constants.js
================================================
// Video call states.
export const CALL_STATE_NONE = 0;
export const CALL_STATE_OUTGOING_INITATED = 1;
export const CALL_STATE_INCOMING_RECEIVED = 2;
export const CALL_STATE_IN_PROGRESS = 3;

// Video call message headers representing call state.
export const CALL_HEAD_STARTED = 'started';



================================================
FILE: src/dcodes.json
================================================
[{"dial":"93","code":"AF"},{"dial":"355","code":"AL"},{"dial":"213","code":"DZ"},{"dial":"1-684","code":"AS"},{"dial":"376","code":"AD"},{"dial":"244","code":"AO"},{"dial":"1-264","code":"AI"},{"dial":"672","code":"AQ"},{"dial":"1-268","code":"AG"},{"dial":"54","code":"AR"},{"dial":"374","code":"AM"},{"dial":"297","code":"AW"},{"dial":"61","code":"AU"},{"dial":"43","code":"AT"},{"dial":"994","code":"AZ"},{"dial":"1-242","code":"BS"},{"dial":"973","code":"BH"},{"dial":"880","code":"BD"},{"dial":"1-246","code":"BB"},{"dial":"375","code":"BY"},{"dial":"32","code":"BE"},{"dial":"501","code":"BZ"},{"dial":"229","code":"BJ"},{"dial":"1-441","code":"BM"},{"dial":"975","code":"BT"},{"dial":"591","code":"BO"},{"dial":"387","code":"BA"},{"dial":"267","code":"BW"},{"dial":"55","code":"BR"},{"dial":"246","code":"IO"},{"dial":"1-284","code":"VG"},{"dial":"673","code":"BN"},{"dial":"359","code":"BG"},{"dial":"226","code":"BF"},{"dial":"257","code":"BI"},{"dial":"855","code":"KH"},{"dial":"237","code":"CM"},{"dial":"1","code":"CA"},{"dial":"238","code":"CV"},{"dial":"1-345","code":"KY"},{"dial":"236","code":"CF"},{"dial":"235","code":"TD"},{"dial":"56","code":"CL"},{"dial":"86","code":"CN"},{"dial":"61","code":"CX"},{"dial":"61","code":"CC"},{"dial":"57","code":"CO"},{"dial":"269","code":"KM"},{"dial":"682","code":"CK"},{"dial":"506","code":"CR"},{"dial":"385","code":"HR"},{"dial":"53","code":"CU"},{"dial":"599","code":"CW"},{"dial":"357","code":"CY"},{"dial":"420","code":"CZ"},{"dial":"243","code":"CD"},{"dial":"45","code":"DK"},{"dial":"253","code":"DJ"},{"dial":"1-767","code":"DM"},{"dial":"1-809, 1-829, 1-849","code":"DO"},{"dial":"670","code":"TL"},{"dial":"593","code":"EC"},{"dial":"20","code":"EG"},{"dial":"503","code":"SV"},{"dial":"240","code":"GQ"},{"dial":"291","code":"ER"},{"dial":"372","code":"EE"},{"dial":"251","code":"ET"},{"dial":"500","code":"FK"},{"dial":"298","code":"FO"},{"dial":"679","code":"FJ"},{"dial":"358","code":"FI"},{"dial":"33","code":"FR"},{"dial":"689","code":"PF"},{"dial":"241","code":"GA"},{"dial":"220","code":"GM"},{"dial":"995","code":"GE"},{"dial":"49","code":"DE"},{"dial":"233","code":"GH"},{"dial":"350","code":"GI"},{"dial":"30","code":"GR"},{"dial":"299","code":"GL"},{"dial":"1-473","code":"GD"},{"dial":"1-671","code":"GU"},{"dial":"502","code":"GT"},{"dial":"44-1481","code":"GG"},{"dial":"224","code":"GN"},{"dial":"245","code":"GW"},{"dial":"592","code":"GY"},{"dial":"509","code":"HT"},{"dial":"504","code":"HN"},{"dial":"852","code":"HK"},{"dial":"36","code":"HU"},{"dial":"354","code":"IS"},{"dial":"91","code":"IN"},{"dial":"62","code":"ID"},{"dial":"98","code":"IR"},{"dial":"964","code":"IQ"},{"dial":"353","code":"IE"},{"dial":"44-1624","code":"IM"},{"dial":"972","code":"IL"},{"dial":"39","code":"IT"},{"dial":"225","code":"CI"},{"dial":"1-876","code":"JM"},{"dial":"81","code":"JP"},{"dial":"44-1534","code":"JE"},{"dial":"962","code":"JO"},{"dial":"7, 997","code":"KZ"},{"dial":"254","code":"KE"},{"dial":"686","code":"KI"},{"dial":"383","code":"XK"},{"dial":"965","code":"KW"},{"dial":"996","code":"KG"},{"dial":"856","code":"LA"},{"dial":"371","code":"LV"},{"dial":"961","code":"LB"},{"dial":"266","code":"LS"},{"dial":"231","code":"LR"},{"dial":"218","code":"LY"},{"dial":"423","code":"LI"},{"dial":"370","code":"LT"},{"dial":"352","code":"LU"},{"dial":"853","code":"MO"},{"dial":"389","code":"MK"},{"dial":"261","code":"MG"},{"dial":"265","code":"MW"},{"dial":"60","code":"MY"},{"dial":"960","code":"MV"},{"dial":"223","code":"ML"},{"dial":"356","code":"MT"},{"dial":"692","code":"MH"},{"dial":"222","code":"MR"},{"dial":"230","code":"MU"},{"dial":"262","code":"YT"},{"dial":"52","code":"MX"},{"dial":"691","code":"FM"},{"dial":"373","code":"MD"},{"dial":"377","code":"MC"},{"dial":"976","code":"MN"},{"dial":"382","code":"ME"},{"dial":"1-664","code":"MS"},{"dial":"212","code":"MA"},{"dial":"258","code":"MZ"},{"dial":"95","code":"MM"},{"dial":"264","code":"NA"},{"dial":"674","code":"NR"},{"dial":"977","code":"NP"},{"dial":"31","code":"NL"},{"dial":"599","code":"CW"},{"dial":"687","code":"NC"},{"dial":"64","code":"NZ"},{"dial":"505","code":"NI"},{"dial":"227","code":"NE"},{"dial":"234","code":"NG"},{"dial":"683","code":"NU"},{"dial":"850","code":"KP"},{"dial":"1-670","code":"MP"},{"dial":"47","code":"NO"},{"dial":"968","code":"OM"},{"dial":"92","code":"PK"},{"dial":"680","code":"PW"},{"dial":"970","code":"PS"},{"dial":"507","code":"PA"},{"dial":"675","code":"PG"},{"dial":"595","code":"PY"},{"dial":"51","code":"PE"},{"dial":"63","code":"PH"},{"dial":"64","code":"PN"},{"dial":"48","code":"PL"},{"dial":"351","code":"PT"},{"dial":"1-787, 1-939","code":"PR"},{"dial":"974","code":"QA"},{"dial":"242","code":"CG"},{"dial":"262","code":"RE"},{"dial":"40","code":"RO"},{"dial":"7","code":"RU"},{"dial":"250","code":"RW"},{"dial":"590","code":"BL"},{"dial":"290","code":"SH"},{"dial":"1-869","code":"KN"},{"dial":"1-758","code":"LC"},{"dial":"590","code":"MF"},{"dial":"508","code":"PM"},{"dial":"1-784","code":"VC"},{"dial":"685","code":"WS"},{"dial":"378","code":"SM"},{"dial":"239","code":"ST"},{"dial":"966","code":"SA"},{"dial":"221","code":"SN"},{"dial":"381","code":"RS"},{"dial":"248","code":"SC"},{"dial":"232","code":"SL"},{"dial":"65","code":"SG"},{"dial":"1-721","code":"SX"},{"dial":"421","code":"SK"},{"dial":"386","code":"SI"},{"dial":"677","code":"SB"},{"dial":"252","code":"SO"},{"dial":"27","code":"ZA"},{"dial":"82","code":"KR"},{"dial":"211","code":"SS"},{"dial":"34","code":"ES"},{"dial":"94","code":"LK"},{"dial":"249","code":"SD"},{"dial":"597","code":"SR"},{"dial":"47","code":"SJ"},{"dial":"268","code":"SZ"},{"dial":"46","code":"SE"},{"dial":"41","code":"CH"},{"dial":"963","code":"SY"},{"dial":"886","code":"TW"},{"dial":"992","code":"TJ"},{"dial":"255","code":"TZ"},{"dial":"66","code":"TH"},{"dial":"228","code":"TG"},{"dial":"690","code":"TK"},{"dial":"676","code":"TO"},{"dial":"1-868","code":"TT"},{"dial":"216","code":"TN"},{"dial":"90","code":"TR"},{"dial":"993","code":"TM"},{"dial":"1-649","code":"TC"},{"dial":"688","code":"TV"},{"dial":"1-340","code":"VI"},{"dial":"256","code":"UG"},{"dial":"380","code":"UA"},{"dial":"971","code":"AE"},{"dial":"44","code":"GB"},{"dial":"1","code":"US"},{"dial":"598","code":"UY"},{"dial":"998","code":"UZ"},{"dial":"678","code":"VU"},{"dial":"379","code":"VA"},{"dial":"58","code":"VE"},{"dial":"84","code":"VN"},{"dial":"681","code":"WF"},{"dial":"212","code":"EH"},{"dial":"967","code":"YE"},{"dial":"260","code":"ZM"},{"dial":"263","code":"ZW"}]


================================================
FILE: src/i18n/ar.json
================================================
{
  "action_block_contact": {
    "translation": "حظر جهة الاتصال",
    "defaultMessage": "Block Contact",
    "description": "Flat button [Block Contact]",
    "missing": false,
    "obsolete": false
  },
  "action_cancel": {
    "translation": "إلغاء",
    "defaultMessage": "cancel",
    "description": "Call to action [cancel]",
    "missing": false,
    "obsolete": false
  },
  "action_clear_messages": {
    "translation": "مسح الرسائل",
    "defaultMessage": "Clear Messages",
    "description": "Flat button [Clear Messages] (soft-delete messages)",
    "missing": false,
    "obsolete": false
  },
  "action_delete_messages": {
    "translation": "مسح الرسائل للجميع",
    "defaultMessage": "Clear Messages for All",
    "description": "Flat button [Clear for All] (hard-delete all messages)",
    "missing": false,
    "obsolete": false
  },
  "action_leave_chat": {
    "translation": "مغادرة المحادثة",
    "defaultMessage": "Leave Conversation",
    "description": "Flat button [Leave Conversation]",
    "missing": false,
    "obsolete": false
  },
  "action_report_chat": {
    "translation": "الإبلاغ عن المحادثة",
    "defaultMessage": "Report Conversation",
    "description": "Flat button [Report Group]",
    "missing": false,
    "obsolete": false
  },
  "archived_contacts": {
    "translation": "جهات الاتصال المؤرشفة ({count})",
    "defaultMessage": "Archived contacts ({count})",
    "description": "Label for archived chats",
    "missing": false,
    "obsolete": false
  },
  "badge_danger": {
    "translation": "غير موثوق به",
    "defaultMessage": "Untrustworthy",
    "description": "Suspicious or untrustworthy account or topic badge",
    "missing": false,
    "obsolete": false
  },
  "badge_owner": {
    "translation": "مالك",
    "defaultMessage": "owner",
    "description": "Badge for indicating the owner",
    "missing": false,
    "obsolete": false
  },
  "badge_staff": {
    "translation": "إدارة الموقع",
    "defaultMessage": "Staff-managed",
    "description": "Explanation of a staff-managed account or topic badge",
    "missing": false,
    "obsolete": false
  },
  "badge_verified": {
    "translation": "موثق/رسمي",
    "defaultMessage": "Verified/official",
    "description": "Explanation of a verified account or topic badge",
    "missing": false,
    "obsolete": false
  },
  "badge_you": {
    "translation": "أنت",
    "defaultMessage": "you",
    "description": "Badge for indicating the current user",
    "missing": false,
    "obsolete": false
  },
  "block_contact_warning": {
    "translation": "هل أنت متأكد من أنك تريد حظر جهة الاتصال هذه؟",
    "defaultMessage": "Are you sure you want to block this contact?",
    "description": "Alert dialog warning when blocking a contact.",
    "missing": false,
    "obsolete": false
  },
  "blocked_contacts_link": {
    "translation": "جهات الاتصال المحظورة ({count})",
    "defaultMessage": "Blocked contacts ({count})",
    "description": "Blocked contacts link",
    "missing": false,
    "obsolete": false
  },
  "button_add_members": {
    "translation": "إضافة أعضاء",
    "defaultMessage": "Add members",
    "description": "Flat button [Add members] (to topic)",
    "missing": false,
    "obsolete": false
  },
  "button_cancel": {
    "translation": "إلغاء",
    "defaultMessage": "Cancel",
    "description": "Button [Cancel]",
    "missing": false,
    "obsolete": false
  },
  "button_confirm": {
    "translation": "تأكيد",
    "defaultMessage": "Confirm",
    "description": "Button [Confirm]",
    "missing": false,
    "obsolete": false
  },
  "button_create": {
    "translation": "إنشاء",
    "defaultMessage": "Create",
    "description": "Button [Create]",
    "missing": false,
    "obsolete": false
  },
  "button_delete_account": {
    "translation": "حذف الحساب",
    "defaultMessage": "Delete account",
    "description": "Button [Delete account]",
    "missing": false,
    "obsolete": false
  },
  "button_edit": {
    "translation": "تعديل",
    "defaultMessage": "Edit",
    "description": "Call to action [Edit]",
    "missing": false,
    "obsolete": false
  },
  "button_logout": {
    "translation": "تسجيل الخروج",
    "defaultMessage": "Logout",
    "description": "Button [Logout]",
    "missing": false,
    "obsolete": false
  },
  "button_ok": {
    "translation": "موافق",
    "defaultMessage": "OK",
    "description": "Button [OK]",
    "missing": false,
    "obsolete": false
  },
  "button_reset": {
    "translation": "إعادة تعيين",
    "defaultMessage": "Reset",
    "description": "Button [Reset]",
    "missing": false,
    "obsolete": false
  },
  "button_send_request": {
    "translation": "إرسال طلب",
    "defaultMessage": "Send request",
    "description": "Button [Send request]",
    "missing": false,
    "obsolete": false
  },
  "button_sign_in": {
    "translation": "تسجيل الدخول",
    "defaultMessage": "Sign in",
    "description": "Button [Sign In]",
    "missing": false,
    "obsolete": false
  },
  "button_sign_up": {
    "translation": "إنشاء حساب",
    "defaultMessage": "Sign up",
    "description": "Create account button [Sign Up]",
    "missing": false,
    "obsolete": false
  },
  "button_subscribe": {
    "translation": "اشتراك",
    "defaultMessage": "Subscribe",
    "description": "Button [Subscribe]",
    "missing": false,
    "obsolete": false
  },
  "button_update": {
    "translation": "تحديث",
    "defaultMessage": "Update",
    "description": "Button [Update]",
    "missing": false,
    "obsolete": false
  },
  "cannot_initiate_file_upload": {
    "translation": "لا يمكن بدء تحميل الملف",
    "defaultMessage": "Cannot initiate file upload.",
    "description": "Generic error messagewhen attachment fails",
    "missing": false,
    "obsolete": false
  },
  "channel": {
    "translation": "قناة",
    "defaultMessage": "channel",
    "description": "Subtitle shown for channels in MessagesView instead of last seen",
    "missing": false,
    "obsolete": false
  },
  "channel_prompt": {
    "translation": "هذه قناة",
    "defaultMessage": "This is a channel",
    "description": "Checkbox label when creating a channel",
    "missing": false,
    "obsolete": false
  },
  "chat_invitation": {
    "translation": "أنت مدعو لبدء محادثة جديدة. ماذا تريد أن تفعل؟",
    "defaultMessage": "You are invited to start a new chat. What would you like to do?",
    "description": "New chat invitation message: [Accept] [Ignore] [Block].",
    "missing": false,
    "obsolete": false
  },
  "chat_invitation_accept": {
    "translation": "قبول",
    "defaultMessage": "Accept",
    "description": "Action [Accept] for chat invitation.",
    "missing": false,
    "obsolete": false
  },
  "chat_invitation_block": {
    "translation": "حظر",
    "defaultMessage": "Block",
    "description": "Action [Block] for chat invitation.",
    "missing": false,
    "obsolete": false
  },
  "chat_invitation_ignore": {
    "translation": "تجاهل",
    "defaultMessage": "Ignore",
    "description": "Action [Ignore] for chat invitation.",
    "missing": false,
    "obsolete": false
  },
  "clear_messages_warning": {
    "translation": "هل أنت متأكد من أنك تريد مسح جميع الرسائل؟ لا يمكن التراجع عن هذا الإجراء.",
    "defaultMessage": "Are you sure you want to clear all messages? It cannot be undone.",
    "description": "Alert dialog warning when deleting all messages.",
    "missing": false,
    "obsolete": false
  },
  "code_doesnot_match": {
    "translation": "الرمز غير متطابق",
    "defaultMessage": "Code does not match",
    "description": "Error message when the credential validation code is incorrect.",
    "missing": false,
    "obsolete": false
  },
  "contacts_not_found": {
    "translation": "ليس لديك محادثات\n¯∖_(ツ)_/¯",
    "defaultMessage": "You have no chats\\n¯∖_(ツ)_/¯",
    "description": "HTML message shown in ContactList when no contacts are found",
    "missing": false,
    "obsolete": false
  },
  "contacts_not_found_short": {
    "translation": "لا توجد جهات اتصال تطابق ''{query}''",
    "defaultMessage": "No contacts match ''{query}''",
    "description": "Shown in ContactsView when search returned no results",
    "missing": false,
    "obsolete": false
  },
  "credential_email_prompt": {
    "translation": "البريد الإلكتروني للتسجيل",
    "defaultMessage": "Your registration email",
    "description": "Placeholder for entering email",
    "missing": false,
    "obsolete": false
  },
  "delete_account": {
    "translation": "حذف الحساب",
    "defaultMessage": "Delete account",
    "description": "Title for delete account warning",
    "missing": false,
    "obsolete": false
  },
  "delete_account_warning": {
    "translation": "هل أنت متأكد من أنك تريد حذف حسابك؟ لا يمكن التراجع عن هذا الإجراء.",
    "defaultMessage": "Are you sure you want to delete your account? It cannot be undone.",
    "description": "Warning message when deleting an account",
    "missing": false,
    "obsolete": false
  },
  "delete_messages_warning": {
    "translation": "هل أنت متأكد من أنك تريد حذف جميع الرسائل للجميع؟ لا يمكن التراجع عن هذا الإجراء.",
    "defaultMessage": "Are you sure you want to delete all messages for everyone? It cannot be undone.",
    "description": "Alert dialog warning when hard-deleting all messages.",
    "missing": false,
    "obsolete": false
  },
  "download_action": {
    "translation": "تحميل",
    "defaultMessage": "download",
    "description": "Call to action [download]",
    "missing": false,
    "obsolete": false
  },
  "drafty_attachment": {
    "translation": "مرفق",
    "defaultMessage": "Attachment",
    "description": "Comment for attachment in Drafty",
    "missing": false,
    "obsolete": false
  },
  "drafty_form": {
    "translation": "نموذج:",
    "defaultMessage": "Form:",
    "description": "Comment for form in Drafty",
    "missing": false,
    "obsolete": false
  },
  "drafty_image": {
    "translation": "صورة",
    "defaultMessage": "Picture",
    "description": "Comment for embedded images in Drafty",
    "missing": false,
    "obsolete": false
  },
  "email_dative": {
    "translation": "البريد الإلكتروني",
    "defaultMessage": "email",
    "description": "Dative case of 'email', i.e. 'email' in 'by email'",
    "missing": false,
    "obsolete": false
  },
  "email_prompt": {
    "translation": "البريد الإلكتروني، مثال: jdoe@example.com",
    "defaultMessage": "Email, e.g. jdoe@example.com",
    "description": "Input placeholder for email entry",
    "missing": false,
    "obsolete": false
  },
  "enable_peers_messaging": {
    "translation": "تفعيل",
    "defaultMessage": "Enable",
    "description": "Call to action to enable peer's messaging",
    "missing": false,
    "obsolete": false
  },
  "enter_confirmation_code_prompt": {
    "translation": "رمز التأكيد",
    "defaultMessage": "Confirmation code",
    "description": "Request to enter confirmation code",
    "missing": false,
    "obsolete": false
  },
  "error_invalid_id": {
    "translation": "معرف غير صالح",
    "defaultMessage": "Invalid ID",
    "description": "Error message",
    "missing": false,
    "obsolete": false
  },
  "file_attachment_too_large": {
    "translation": "حجم الملف {size} يتجاوز الحد {limit}.",
    "defaultMessage": "The file size {size} exceeds the {limit} limit.",
    "description": "Error message when attachment is too large",
    "missing": false,
    "obsolete": false
  },
  "forgot_password_link": {
    "translation": "نسيت كلمة المرور؟",
    "defaultMessage": "Forgot password?",
    "description": "Link to Reset password form",
    "missing": false,
    "obsolete": false
  },
  "full_name_prompt": {
    "translation": "الاسم الكامل، مثال: جون دو",
    "defaultMessage": "Full name, e.g. John Doe",
    "description": "Input placeholder for person's full name",
    "missing": false,
    "obsolete": false
  },
  "granted_permissions": {
    "translation": "ممنوح",
    "defaultMessage": "Granted",
    "description": "Title for permissions",
    "missing": false,
    "obsolete": false
  },
  "group_has_no_members": {
    "translation": "لا يوجد أعضاء",
    "defaultMessage": "No members",
    "description": "Shown in place of group members",
    "missing": false,
    "obsolete": false
  },
  "group_user_id_prompt": {
    "translation": "معرف المجموعة أو المستخدم",
    "defaultMessage": "Group or User ID",
    "description": "Prompt for entering user or group ID",
    "missing": false,
    "obsolete": false
  },
  "image_caption_prompt": {
    "translation": "وصف الصورة",
    "defaultMessage": "Image caption",
    "description": "Prompt in SendMessage for attached image",
    "missing": false,
    "obsolete": false
  },
  "invalid_content": {
    "translation": "محتوى غير صالح",
    "defaultMessage": "invalid content",
    "description": "Shown when the message is unreadable",
    "missing": false,
    "obsolete": false
  },
  "invalid_security_token": {
    "translation": "رمز الأمان غير صالح",
    "defaultMessage": "Invalid security token",
    "description": "Error message when resetting password.",
    "missing": false,
    "obsolete": false
  },
  "label_client": {
    "translation": "العميل:",
    "defaultMessage": "Client:",
    "description": "Label for a client version",
    "missing": false,
    "obsolete": false
  },
  "label_content_type": {
    "translation": "نوع المحتوى:",
    "defaultMessage": "Content type:",
    "description": "Label for file content type (mime)",
    "missing": false,
    "obsolete": false
  },
  "label_default_access_mode": {
    "translation": "وضع الوصول الافتراضي:",
    "defaultMessage": "Default access mode:",
    "description": "Label for default access mode",
    "missing": false,
    "obsolete": false
  },
  "label_file_name": {
    "translation": "اسم الملف:",
    "defaultMessage": "File name:",
    "description": "Label for a file name",
    "missing": false,
    "obsolete": false
  },
  "label_group_members": {
    "translation": "أعضاء المجموعة:",
    "defaultMessage": "Group members:",
    "description": "Section title or label",
    "missing": false,
    "obsolete": false
  },
  "label_incognito_mode": {
    "translation": "وضع التخفي:",
    "defaultMessage": "Incognito mode:",
    "description": "Label for incognito mode toggle",
    "missing": false,
    "obsolete": false
  },
  "label_message_sound": {
    "translation": "صوت الرسالة:",
    "defaultMessage": "Message sound:",
    "description": "Label for message sounds toggle",
    "missing": false,
    "obsolete": false
  },
  "label_muting_topic": {
    "translation": "صامت:",
    "defaultMessage": "Muted:",
    "description": "Label for Muting/unmuting the topic",
    "missing": false,
    "obsolete": false
  },
  "label_other_user": {
    "translation": "آخر",
    "defaultMessage": "Other",
    "description": "Label for the other user when the user is unnamed",
    "missing": false,
    "obsolete": false
  },
  "label_password": {
    "translation": "كلمة المرور",
    "defaultMessage": "Password",
    "description": "Label for password editing",
    "missing": false,
    "obsolete": false
  },
  "label_permissions": {
    "translation": "الصلاحيات:",
    "defaultMessage": "Permissions:",
    "description": "Section title",
    "missing": false,
    "obsolete": false
  },
  "label_private": {
    "translation": "تعليق خاص",
    "defaultMessage": "Private comment",
    "description": "Label for editing 'private'",
    "missing": false,
    "obsolete": false
  },
  "label_push_notifications": {
    "translation": "تنبيهات الإشعارات:",
    "defaultMessage": "Notification alerts:",
    "description": "Label for push notifications switch",
    "missing": false,
    "obsolete": false
  },
  "label_push_notifications_disabled": {
    "translation": "تنبيهات الإشعارات (يتطلب HTTPS):",
    "defaultMessage": "Notification alerts (requires HTTPS):",
    "description": "Label for push notifications switch",
    "missing": false,
    "obsolete": false
  },
  "label_reset_password": {
    "translation": "إرسال بريد إلكتروني لإعادة تعيين كلمة المرور:",
    "defaultMessage": "Send a password reset email",
    "description": "Label for password reset field",
    "missing": false,
    "obsolete": false
  },
  "label_sdk": {
    "translation": "SDK:",
    "defaultMessage": "SDK:",
    "missing": false,
    "obsolete": false
  },
  "label_server": {
    "translation": "الخادم:",
    "defaultMessage": "Server:",
    "description": "Label for a server version",
    "missing": false,
    "obsolete": false
  },
  "label_server_address": {
    "translation": "عنوان الخادم:",
    "defaultMessage": "Server address:",
    "missing": false,
    "obsolete": false
  },
  "label_server_to_use": {
    "translation": "الخادم المراد استخدامه:",
    "defaultMessage": "Server to use:",
    "description": "Label for server selector in SettingsView",
    "missing": false,
    "obsolete": false
  },
  "label_size": {
    "translation": "الحجم:",
    "defaultMessage": "Size:",
    "description": "Label for file size",
    "missing": false,
    "obsolete": false
  },
  "label_topic_name": {
    "translation": "الاسم",
    "defaultMessage": "Name",
    "description": "Label for editing topic name",
    "missing": false,
    "obsolete": false
  },
  "label_user_contacts": {
    "translation": "جهات الاتصال",
    "defaultMessage": "Contacts",
    "description": "Label for user contacts",
    "missing": false,
    "obsolete": false
  },
  "label_user_id": {
    "translation": "المعرف:",
    "defaultMessage": "ID:",
    "description": "Label for user address (ID)",
    "missing": false,
    "obsolete": false
  },
  "label_wire_transport": {
    "translation": "نقل البيانات:",
    "defaultMessage": "Wire transport:",
    "description": "Label for wire transport selection in SettingsView",
    "missing": false,
    "obsolete": false
  },
  "label_you": {
    "translation": "أنت:",
    "defaultMessage": "You:",
    "description": "Label for the current user",
    "missing": false,
    "obsolete": false
  },
  "label_your_name": {
    "translation": "اسمك",
    "defaultMessage": "Your name",
    "description": "Label for full name editing",
    "missing": false,
    "obsolete": false
  },
  "label_your_permissions": {
    "translation": "صلاحياتك:",
    "defaultMessage": "Your permissions:",
    "description": "Label for current user permissions",
    "missing": false,
    "obsolete": false
  },
  "last_seen_timestamp": {
    "translation": "آخر ظهور",
    "defaultMessage": "Last seen: {timestamp}",
    "description": "Label for the timestamp of when the user or topic was last online",
    "missing": false,
    "obsolete": false
  },
  "leave_chat_warning": {
    "translation": "هل أنت متأكد من أنك تريد مغادرة هذه المحادثة؟",
    "defaultMessage": "Are you sure you want to leave this conversation?",
    "description": "Alert dialog warning when unsubscribing from a chat.",
    "missing": false,
    "obsolete": false
  },
  "link_contact_us": {
    "translation": "اتصل بنا",
    "defaultMessage": "Contact Us",
    "description": "Ancor text for contacting us by email",
    "missing": false,
    "obsolete": false
  },
  "link_privacy_policy": {
    "translation": "سياسة الخصوصية",
    "defaultMessage": "Privacy Policy",
    "description": "Ancor text for privacy policy link",
    "missing": false,
    "obsolete": false
  },
  "link_terms_of_service": {
    "translation": "شروط الخدمة",
    "defaultMessage": "Terms of Service",
    "description": "Ancor text for terms of service link",
    "missing": false,
    "obsolete": false
  },
  "login_prompt": {
    "translation": "تسجيل الدخول",
    "defaultMessage": "Login",
    "description": "Placeholer for username/login",
    "missing": false,
    "obsolete": false
  },
  "menu_item_archive_topic": {
    "translation": "أرشفة",
    "defaultMessage": "Archive",
    "description": "Move topic from the list of active chats to archive",
    "missing": false,
    "obsolete": false
  },
  "menu_item_block": {
    "translation": "حظر",
    "defaultMessage": "Block",
    "description": "Block topic or user",
    "missing": false,
    "obsolete": false
  },
  "menu_item_clear_messages": {
    "translation": "مسح الرسائل",
    "defaultMessage": "Clear messages",
    "description": "Delete all messages",
    "missing": false,
    "obsolete": false
  },
  "menu_item_clear_messages_for_all": {
    "translation": "مسح للجميع",
    "defaultMessage": "Clear for All",
    "description": "Delete all message(s) for all members",
    "missing": false,
    "obsolete": false
  },
  "menu_item_delete": {
    "translation": "حذف",
    "defaultMessage": "Delete",
    "description": "Delete selected messages",
    "missing": false,
    "obsolete": false
  },
  "menu_item_delete_for_all": {
    "translation": "حذف للجميع",
    "defaultMessage": "Delete for All",
    "description": "Delete selected message(s) for all members",
    "missing": false,
    "obsolete": false
  },
  "menu_item_delete_topic": {
    "translation": "حذف",
    "defaultMessage": "Delete",
    "description": "Delete entire topic",
    "missing": false,
    "obsolete": false
  },
  "menu_item_edit_permissions": {
    "translation": "تعديل الصلاحيات",
    "defaultMessage": "Edit permissions",
    "description": "Menu item [Edit permissions]",
    "missing": false,
    "obsolete": false
  },
  "menu_item_info": {
    "translation": "معلومات",
    "defaultMessage": "Info",
    "description": "Show extended topic information",
    "missing": false,
    "obsolete": false
  },
  "menu_item_member_delete": {
    "translation": "إزالة",
    "defaultMessage": "Remove",
    "description": "Remove user from topic",
    "missing": false,
    "obsolete": false
  },
  "menu_item_mute": {
    "translation": "كتم",
    "defaultMessage": "Mute",
    "description": "Turn off notifications",
    "missing": false,
    "obsolete": false
  },
  "menu_item_reply": {
    "translation": "رد",
    "defaultMessage": "Reply",
    "description": "Reply to message",
    "missing": false,
    "obsolete": false
  },
  "menu_item_restore_topic": {
    "translation": "استعادة",
    "defaultMessage": "Restore",
    "description": "Restore topic from archive",
    "missing": false,
    "obsolete": false
  },
  "menu_item_send_retry": {
    "translation": "إعادة المحاولة",
    "defaultMessage": "Retry",
    "description": "Retry sending message",
    "missing": false,
    "obsolete": false
  },
  "menu_item_unblock": {
    "translation": "إلغاء الحظر",
    "defaultMessage": "Unblock",
    "description": "Unblock topic or user",
    "missing": false,
    "obsolete": false
  },
  "menu_item_unmute": {
    "translation": "إلغاء الكتم",
    "defaultMessage": "Unmute",
    "description": "Turn notifications on",
    "missing": false,
    "obsolete": false
  },
  "message_sending": {
    "translation": "جاري الإرسال...",
    "defaultMessage": "sending...",
    "description": "Message being sent, in place of time stamp",
    "missing": false,
    "obsolete": false
  },
  "message_sending_failed": {
    "translation": "فشل",
    "defaultMessage": "failed",
    "description": "Failed to send message, in place of time stamp",
    "missing": false,
    "obsolete": false
  },
  "messages_not_readable": {
    "translation": "لا يمكن الوصول إلى الرسائل",
    "defaultMessage": "no access to messages",
    "description": "Message shown in topic without the read access",
    "missing": false,
    "obsolete": false
  },
  "messaging_disabled_prompt": {
    "translation": "المراسلة معطلة",
    "defaultMessage": "Messaging disabled",
    "description": "Prompt in SendMessage in read-only topic",
    "missing": false,
    "obsolete": false
  },
  "more_online_members": {
    "translation": "+{overflow} آخرون",
    "defaultMessage": "+{overflow} more",
    "description": "Shown in MessagesView title bar when the number of online subscribers exceeds MAX_ONLINE_IN_TOPIC",
    "missing": false,
    "obsolete": false
  },
  "new_message_prompt": {
    "translation": "رسالة جديدة",
    "defaultMessage": "New message",
    "description": "Prompt in send message field",
    "missing": false,
    "obsolete": false
  },
  "new_password_placeholder": {
    "translation": "أدخل كلمة المرور الجديدة",
    "defaultMessage": "Enter new password",
    "description": "Placeholder for entering new password",
    "missing": false,
    "obsolete": false
  },
  "no_connection": {
    "translation": "لا يوجد اتصال",
    "defaultMessage": "No connection",
    "description": "Warning that the user is offline.",
    "missing": false,
    "obsolete": false
  },
  "no_contacts": {
    "translation": "ليس لديك جهات اتصال :-(",
    "defaultMessage": "You have no contacts :-(",
    "description": "Shown in ContactsView when the user has no contacts",
    "missing": false,
    "obsolete": false
  },
  "numeric_confirmation_code_prompt": {
    "translation": "أرقام فقط",
    "defaultMessage": "Numbers only",
    "description": "Prompt for numeric conformation code",
    "missing": false,
    "obsolete": false
  },
  "online_now": {
    "translation": "متصل الآن",
    "defaultMessage": "online now",
    "description": "Indicator that the user or topic is currently online",
    "missing": false,
    "obsolete": false
  },
  "password_prompt": {
    "translation": "كلمة المرور",
    "defaultMessage": "Password",
    "description": "Placeholder/prompt for entering password",
    "missing": false,
    "obsolete": false
  },
  "password_unchanged_prompt": {
    "translation": "لم يتغير",
    "defaultMessage": "Unchanged",
    "description": "Message in editor while password is unchanged",
    "missing": false,
    "obsolete": false
  },
  "peers_messaging_disabled": {
    "translation": "المراسلة معطلة للطرف الآخر",
    "defaultMessage": "Peer's messaging is disabled.",
    "description": "Shown when the p2p peer's messaging is disabled",
    "missing": false,
    "obsolete": false
  },
  "permission_admin": {
    "translation": "الموافقة ({val})",
    "defaultMessage": "Approve ({val})",
    "description": "Name of A permission",
    "missing": false,
    "obsolete": false
  },
  "permission_delete": {
    "translation": "حذف ({val})",
    "defaultMessage": "Delete ({val})",
    "description": "Name of D permission",
    "missing": false,
    "obsolete": false
  },
  "permission_join": {
    "translation": "انضمام ({val})",
    "defaultMessage": "Join ({val})",
    "description": "Name of J permission",
    "missing": false,
    "obsolete": false
  },
  "permission_owner": {
    "translation": "مالك ({val})",
    "defaultMessage": "Owner ({val})",
    "description": "Name of O permission",
    "missing": false,
    "obsolete": false
  },
  "permission_pres": {
    "translation": "تلقي الإشعارات ({val})",
    "defaultMessage": "Get notified ({val})",
    "description": "Name of P permission",
    "missing": false,
    "obsolete": false
  },
  "permission_read": {
    "translation": "قراءة ({val})",
    "defaultMessage": "Read ({val})",
    "description": "Name of R permission",
    "missing": false,
    "obsolete": false
  },
  "permission_share": {
    "translation": "مشاركة ({val})",
    "defaultMessage": "Share ({val})",
    "description": "Name of S permission",
    "missing": false,
    "obsolete": false
  },
  "permission_write": {
    "translation": "كتابة ({val})",
    "defaultMessage": "Write ({val})",
    "description": "Name of W permission",
    "missing": false,
    "obsolete": false
  },
  "phone_dative": {
    "translation": "هاتف",
    "defaultMessage": "phone",
    "description": "Dative case of 'phone', i.e. 'phone' in 'by phone'",
    "missing": false,
    "obsolete": false
  },
  "private_editing_placeholder": {
    "translation": "مرئي لك فقط",
    "defaultMessage": "Visible to you only",
    "description": "Placeholder for editing 'private'",
    "missing": false,
    "obsolete": false
  },
  "push_init_failed": {
    "translation": "فشل في تهيئة الإشعارات",
    "defaultMessage": "Failed to initialize push notifications",
    "description": "Error message when push notifications have failed to initialize.",
    "missing": false,
    "obsolete": false
  },
  "reconnect_countdown": {
    "translation": "تم قطع الاتصال. إعادة الاتصال خلال {seconds}...",
    "defaultMessage": "Disconnected. Reconnecting in {seconds}…",
    "description": "Message shown when an app update is available.",
    "missing": false,
    "obsolete": false
  },
  "reconnect_now": {
    "translation": "حاول الآن",
    "defaultMessage": "Try now",
    "description": "Prompt for reconnecting now",
    "missing": false,
    "obsolete": false
  },
  "reload_update": {
    "translation": "إعادة تحميل",
    "defaultMessage": "Reload",
    "description": "Call to action to reload application when update is available.",
    "missing": false,
    "obsolete": false
  },
  "report_chat_warning": {
    "translation": "هل أنت متأكد من أنك تريد حظر والإبلاغ عن هذه المحادثة؟",
    "defaultMessage": "Are you sure you want to block and report this conversation?",
    "description": "Alert dialog warning when reporting a conversation for abuse",
    "missing": false,
    "obsolete": false
  },
  "requested_permissions": {
    "translation": "مطلوب",
    "defaultMessage": "Requested",
    "description": "Title for permissions",
    "missing": false,
    "obsolete": false
  },
  "save_attachment": {
    "translation": "حفظ",
    "defaultMessage": "save",
    "description": "Call to save an attachment",
    "missing": false,
    "obsolete": false
  },
  "search_for_contacts": {
    "translation": "استخدم البحث للعثور على جهات الاتصال",
    "defaultMessage": "Use search to find contacts",
    "description": "Text shown in contacts view when user entered no search query.",
    "missing": false,
    "obsolete": false
  },
  "search_no_results": {
    "translation": "لم يسفر البحث عن أي نتائج",
    "defaultMessage": "Search returned no results",
    "description": "Text shown in contacts view when query returned no results.",
    "missing": false,
    "obsolete": false
  },
  "search_placeholder": {
    "translation": "قائمة مثل alice@example.com، +17025550003...",
    "defaultMessage": "List like alice@example.com, +17025550003...",
    "description": "Placeholder in contacts search field",
    "missing": false,
    "obsolete": false
  },
  "sidepanel_title_acc_notifications": {
    "translation": "الإشعارات",
    "defaultMessage": "Notifications",
    "description": "Sidepanel title for AccNotificationsView.",
    "missing": false,
    "obsolete": false
  },
  "sidepanel_title_acc_support": {
    "translation": "الدعم",
    "defaultMessage": "Support",
    "description": "Sidepanel title for AccSupportView.",
    "missing": false,
    "obsolete": false
  },
  "sidepanel_title_account_settings": {
    "translation": "إعدادات الحساب",
    "defaultMessage": "Account Settings",
    "description": "Sidepanel title for AccountSettingsView.",
    "missing": false,
    "obsolete": false
  },
  "sidepanel_title_archive": {
    "translation": "المحادثات المؤرشفة",
    "defaultMessage": "Archived Chats",
    "description": "Sidepanel title for ContactsView-Archive.",
    "missing": false,
    "obsolete": false
  },
  "sidepanel_title_blocked": {
    "translation": "المحادثات المحظورة",
    "defaultMessage": "Blocked Chats",
    "description": "Sidepanel title for ContactsView-Blocked.",
    "missing": false,
    "obsolete": false
  },
  "sidepanel_title_cred": {
    "translation": "تأكيد بيانات الاعتماد",
    "defaultMessage": "Confirm Credentials",
    "description": "Sidepanel title for ValidationView.",
    "missing": false,
    "obsolete": false
  },
  "sidepanel_title_login": {
    "translation": "تسجيل الدخول",
    "defaultMessage": "Sign In",
    "description": "Sidepanel title for LoginView.",
    "missing": false,
    "obsolete": false
  },
  "sidepanel_title_newtpk": {
    "translation": "بدء محادثة جديدة",
    "defaultMessage": "Start New Chat",
    "description": "Sidepanel title for NewTopicView.",
    "missing": false,
    "obsolete": false
  },
  "sidepanel_title_register": {
    "translation": "إنشاء حساب",
    "defaultMessage": "Create Account",
    "description": "Sidepanel title for CreateAccountView.",
    "missing": false,
    "obsolete": false
  },
  "sidepanel_title_reset": {
    "translation": "إعادة تعيين كلمة المرور",
    "defaultMessage": "Reset Password",
    "description": "Sidepanel title for PasswordResetView.",
    "missing": false,
    "obsolete": false
  },
  "sidepanel_title_settings": {
    "translation": "الإعدادات",
    "defaultMessage": "Settings",
    "description": "Sidepanel title for SettingsView.",
    "missing": false,
    "obsolete": false
  },
  "stay_logged_in": {
    "translation": "البقاء متصلاً",
    "defaultMessage": "Stay logged in",
    "description": "Label for a checkbox",
    "missing": false,
    "obsolete": false
  },
  "tabtitle_find_user": {
    "translation": "بحث",
    "defaultMessage": "find",
    "description": "Tab title Find",
    "missing": false,
    "obsolete": false
  },
  "tabtitle_group_by_id": {
    "translation": "بواسطة المعرف",
    "defaultMessage": "by id",
    "description": "Tab title Find topic by ID",
    "missing": false,
    "obsolete": false
  },
  "tabtitle_new_group": {
    "translation": "مجموعة جديدة",
    "defaultMessage": "new group",
    "description": "Tab title New Group",
    "missing": false,
    "obsolete": false
  },
  "tags_editor_no_tags": {
    "translation": "أضف بعض الوسوم",
    "defaultMessage": "Add some tags",
    "description": "Tag editor prompt when no tags are found.",
    "missing": false,
    "obsolete": false
  },
  "tags_not_found": {
    "translation": "لا توجد وسوم محددة. أضف بعضها.",
    "defaultMessage": "No tags defined. Add some.",
    "description": "",
    "missing": false,
    "obsolete": false
  },
  "title_all_contacts": {
    "translation": "جميع جهات الاتصال",
    "defaultMessage": "All Contacts",
    "description": "Section title [All Contacts]",
    "missing": false,
    "obsolete": false
  },
  "title_group_members": {
    "translation": "أعضاء المجموعة",
    "defaultMessage": "Group Members",
    "description": "Section title",
    "missing": false,
    "obsolete": false
  },
  "title_manage_tags": {
    "translation": "إدارة",
    "defaultMessage": "Manage",
    "description": "Section title for the list of tags",
    "missing": false,
    "obsolete": false
  },
  "title_not_found": {
    "translation": "غير موجود",
    "defaultMessage": "Not found",
    "description": "Title shown when topic is not found",
    "missing": false,
    "obsolete": false
  },
  "title_permissions": {
    "translation": "الصلاحيات",
    "defaultMessage": "Permissions",
    "description": "Section title",
    "missing": false,
    "obsolete": false
  },
  "title_tag_manager": {
    "translation": "الوسوم (البحث والاكتشاف)",
    "defaultMessage": "Tags (search & discovery)",
    "description": "Section title for TagManager",
    "missing": false,
    "obsolete": false
  },
  "topic_block_warning": {
    "translation": "هل أنت متأكد من أنك تريد حظر هذه المحادثة؟",
    "defaultMessage": "Are you sure you want to block this conversation?",
    "description": "Alert warning when blocking a topic.",
    "missing": false,
    "obsolete": false
  },
  "topic_delete_warning": {
    "translation": "هل أنت متأكد من أنك تريد حذف هذه المحادثة؟ لا يمكن التراجع عن هذا الإجراء.",
    "defaultMessage": "Are you sure you want to delete this conversation? It cannot be undone.",
    "description": "Alert warning when deleting entire topic",
    "missing": false,
    "obsolete": false
  },
  "topic_name_editing_placeholder": {
    "translation": "اسم حر للمجموعة",
    "defaultMessage": "Freeform name of the group",
    "description": "Prompt for entering topic name",
    "missing": false,
    "obsolete": false
  },
  "unnamed_topic": {
    "translation": "بدون اسم",
    "defaultMessage": "Unnamed",
    "description": "Title shown when the topic has no name",
    "missing": false,
    "obsolete": false
  },
  "update_available": {
    "translation": "يتوفر تحديث.",
    "defaultMessage": "Update available.",
    "description": "Message shown when an app update is available.",
    "missing": false,
    "obsolete": false
  },
  "upload_finishing": {
    "translation": "جاري الإنهاء...",
    "defaultMessage": "finishing...",
    "description": "Notification that upload is finishing",
    "missing": false,
    "obsolete": false
  },
  "user_not_found": {
    "translation": "غير موجود",
    "defaultMessage": "Not found",
    "description": "In place of a user's full name when the user is not found.",
    "missing": false,
    "obsolete": false
  },
  "description_editing_placeholder": {
    "translation": "وصف اختياري",
    "defaultMessage": "Description (optional)",
    "description": "Placeholder for editing topic description",
    "missing": false,
    "obsolete": false
  },
  "label_description": {
    "translation": "الوصف",
    "defaultMessage": "Description",
    "description": "Label for description of user or topic",
    "missing": false,
    "obsolete": false
  },
  "button_security": {
    "translation": "الأمان",
    "defaultMessage": "Security",
    "description": "Navigaton button for security panel.",
    "missing": false,
    "obsolete": false
  },
  "panel_title_crop": {
    "translation": "اسحب للتعديل",
    "defaultMessage": "Drag to Adjust",
    "description": "Title for AvatarCropView.",
    "missing": false,
    "obsolete": false
  },
  "panel_title_general": {
    "translation": "عام",
    "defaultMessage": "General",
    "description": "Title for TopicCommon.",
    "missing": false,
    "obsolete": false
  },
  "panel_title_members": {
    "translation": "الأعضاء",
    "defaultMessage": "Members",
    "description": "Title for managing group members view.",
    "missing": false,
    "obsolete": false
  },
  "panel_title_security": {
    "translation": "الأمان",
    "defaultMessage": "Security",
    "description": "Title for TopicSecirity and AccSecurity.",
    "missing": false,
    "obsolete": false
  },
  "panel_title_info": {
    "translation": "معلومات",
    "defaultMessage": "Info",
    "description": "Title for InfoView",
    "missing": false,
    "obsolete": false
  },
  "permissions_anonymous": {
    "translation": "مجهول",
    "defaultMessage": "Anonymous",
    "description": "Title for editing default anonymous permissions",
    "missing": false,
    "obsolete": false
  },
  "permissions_authenticated": {
    "translation": "مصادق عليه",
    "defaultMessage": "Authenticated",
    "description": "Title for editing default authenticated permissions",
    "missing": false,
    "obsolete": false
  },
  "topic_delete": {
    "translation": "حذف المحادثة",
    "defaultMessage": "Delete Conversation",
    "description": "Alert title when deleting the topic.",
    "missing": false,
    "obsolete": false
  },
  "permissions_user": {
    "translation": "صلاحيات المستخدم",
    "defaultMessage": "User's Permissions",
    "description": "Title for editing user's permissions",
    "missing": false,
    "obsolete": false
  },
  "password_reset_email_sent": {
    "translation": "تم إرسال بريد إلكتروني يحتوي على رمز الأمان.",
    "defaultMessage": "An email with security code has been sent.",
    "description": "Notification that the email with password reset instructions has been sent",
    "missing": false,
    "obsolete": false
  },
  "label_unarchive_topic": {
    "translation": "مؤرشف:",
    "defaultMessage": "Archived:",
    "description": "Label for unarchiving the topic",
    "missing": false,
    "obsolete": false
  },
  "menu_item_forward": {
    "translation": "إعادة توجيه",
    "defaultMessage": "Forward",
    "description": "Forward message",
    "missing": false,
    "obsolete": false
  },
  "forward_to": {
    "translation": "إعادة توجيه إلى",
    "defaultMessage": "Forward to",
    "missing": false,
    "obsolete": false
  },
  "forward_to_search_placeholder": {
    "translation": "البحث عن جهات الاتصال",
    "defaultMessage": "Search contacts",
    "description": "Contact search prompt when forwarding a message.",
    "missing": false,
    "obsolete": false
  },
  "label_new_password": {
    "translation": "كلمة المرور الجديدة",
    "defaultMessage": "New password",
    "description": "Label for entering a new password",
    "missing": false,
    "obsolete": false
  },
  "drafty_unknown": {
    "translation": "غير مدعوم",
    "defaultMessage": "Unsupported",
    "description": "Unsupported entity in drafty",
    "missing": false,
    "obsolete": false
  },
  "calls_incoming": {
    "translation": "مكالمة واردة",
    "defaultMessage": "Incoming call",
    "description": "Incoming call label",
    "missing": false,
    "obsolete": false
  },
  "calls_outgoing": {
    "translation": "مكالمة صادرة",
    "defaultMessage": "Outgoing call",
    "description": "Outgoing call label",
    "missing": false,
    "obsolete": false
  },
  "calls_you_label": {
    "translation": "أنت",
    "defaultMessage": "You",
    "description": "Shown over the local video screen",
    "missing": false,
    "obsolete": false
  },
  "menu_item_video_call": {
    "translation": "مكالمة فيديو",
    "defaultMessage": "Video call",
    "description": "Start video call",
    "missing": false,
    "obsolete": false
  },
  "already_in_call": {
    "translation": "أنت بالفعل في مكالمة جارية!",
    "defaultMessage": "You already in an ongoing call!",
    "description": "Error message when the user tried to accept a new call without finishing pervious one",
    "missing": false,
    "obsolete": false
  },
  "call_cancelled": {
    "translation": "تم الإلغاء",
    "defaultMessage": "cancelled",
    "description": "Label for cancelled outgoing call",
    "missing": false,
    "obsolete": false
  },
  "call_missed": {
    "translation": "فائتة",
    "defaultMessage": "missed",
    "description": "Label for missed incoming call",
    "missing": false,
    "obsolete": false
  },
  "call_declined": {
    "translation": "تم الرفض",
    "defaultMessage": "declined",
    "description": "Label for declined call",
    "missing": false,
    "obsolete": false
  },
  "call_disconnected": {
    "translation": "تم قطع الاتصال",
    "defaultMessage": "disconnected",
    "description": "Label for disconnected call",
    "missing": false,
    "obsolete": false
  },
  "label_use_secure_connection": {
    "translation": "استخدام اتصال آمن",
    "defaultMessage": "Use secure connection",
    "description": "Label for WS/WSS connection type in SettingsView",
    "missing": false,
    "obsolete": false
  },
  "cred_confirmed_successfully": {
    "translation": "تم التأكيد بنجاح",
    "defaultMessage": "Confirmed successfully",
    "description": "Notification message that the credential was successfully validated.",
    "missing": false,
    "obsolete": false
  },
  "menu_item_edit": {
    "translation": "تعديل",
    "defaultMessage": "Edit",
    "description": "Edit message",
    "missing": false,
    "obsolete": false
  },
  "editing_message": {
    "translation": "جاري التعديل",
    "defaultMessage": "Editing",
    "description": "Title over message editing preview",
    "missing": false,
    "obsolete": false
  },
  "message_edited_marker": {
    "translation": "، تم التعديل",
    "defaultMessage": ", edited",
    "description": "Marker indicating that the message was edited",
    "missing": false,
    "obsolete": false
  },
  "icon_title_add_image": {
    "translation": "إضافة صورة",
    "defaultMessage": "Add image",
    "description": "Icon tool tip for attaching an image",
    "missing": false,
    "obsolete": false
  },
  "icon_title_attach_file": {
    "translation": "إرفاق ملف",
    "defaultMessage": "Attach file",
    "description": "Icon tool tip for attaching a file",
    "missing": false,
    "obsolete": false
  },
  "icon_title_delete": {
    "translation": "حذف التسجيل",
    "defaultMessage": "Delete recording",
    "description": "Icon tool tip for deleting recorded audio",
    "missing": false,
    "obsolete": false
  },
  "icon_title_pause": {
    "translation": "إيقاف مؤقت",
    "defaultMessage": "Pause playback",
    "description": "Icon tool tip for pausing audio playback",
    "missing": false,
    "obsolete": false
  },
  "icon_title_play": {
    "translation": "تشغيل",
    "defaultMessage": "Play recording",
    "description": "Icon tool tip for starting audio playback",
    "missing": false,
    "obsolete": false
  },
  "icon_title_record_voice": {
    "translation": "تسجيل رسالة صوتية",
    "defaultMessage": "Record voice message",
    "description": "Icon tool tip for recording a voice message",
    "missing": false,
    "obsolete": false
  },
  "icon_title_resume": {
    "translation": "استئناف",
    "defaultMessage": "Resume playback",
    "description": "Icon tool tip for resuming audio playback",
    "missing": false,
    "obsolete": false
  },
  "icon_title_send": {
    "translation": "إرسال رسالة",
    "defaultMessage": "Send message",
    "description": "Icon tool tip for sending a message",
    "missing": false,
    "obsolete": false
  },
  "drag_file": {
    "translation": "اسحب الملف هنا",
    "defaultMessage": "Drag file here",
    "description": "Prompt on the file drag-n-drop overlay banner",
    "missing": false,
    "obsolete": false
  },
  "drafty_video": {
    "translation": "تسجيل فيديو",
    "defaultMessage": "Video recording",
    "description": "Comment for videos embedded in Drafty",
    "missing": false,
    "obsolete": false
  },
  "call_in_progress": {
    "translation": "جارية",
    "defaultMessage": "in progress",
    "description": "Label for call in progress",
    "missing": false,
    "obsolete": false
  },
  "menu_item_audio_call": {
    "translation": "مكالمة",
    "defaultMessage": "Call",
    "description": "Start audio call",
    "missing": false,
    "obsolete": false
  },
  "unrecognized_video_format": {
    "translation": "تنسيق هذا الفيديو غير معروف",
    "defaultMessage": "Format of this video is not recognized",
    "description": "Error message when uploaded video is invalid",
    "missing": false,
    "obsolete": false
  },
  "loading_note": {
    "translation": "جاري التحميل...",
    "defaultMessage": "Loading...",
    "description": "Message shown when component is loading",
    "missing": false,
    "obsolete": false
  },
  "password_i_have_code": {
    "translation": "لدي رمز",
    "defaultMessage": "I have code",
    "description": "Call to open field to enter password reset code",
    "missing": false,
    "obsolete": false
  },
  "label_reset_password_tel": {
    "translation": "إرسال رسالة نصية لإعادة تعيين كلمة المرور:",
    "defaultMessage": "Send SMS to reset password",
    "description": "Label for password reset field by phone",
    "missing": false,
    "obsolete": false
  },
  "mobile_phone_number": {
    "translation": "رقم الهاتف المحمول",
    "defaultMessage": "Mobile phone number",
    "description": "Prompt for entering a mobile phone number",
    "missing": false,
    "obsolete": false
  },
  "password_reset_sms_sent": {
    "translation": "تم إرسال رسالة نصية تحتوي على رمز الأمان.",
    "defaultMessage": "A text message with security code has been sent.",
    "description": "Notification that the SMS with password reset instructions has been sent",
    "missing": false,
    "obsolete": false
  },
  "mobile_number_required": {
    "translation": "رقم الهاتف المحمول مطلوب",
    "defaultMessage": "Mobile phone number required",
    "description": "Error message",
    "missing": false,
    "obsolete": false
  },
  "current_email": {
    "translation": "البريد الإلكتروني الحالي",
    "defaultMessage": "Current email",
    "description": "Label for old email",
    "missing": false,
    "obsolete": false
  },
  "current_phone": {
    "translation": "رقم الهاتف الحالي",
    "defaultMessage": "Current phone number",
    "description": "Label for old phone",
    "missing": false,
    "obsolete": false
  },
  "new_email": {
    "translation": "بريد إلكتروني جديد",
    "defaultMessage": "New email",
    "description": "Prompt for entering a new email",
    "missing": false,
    "obsolete": false
  },
  "new_phone_number": {
    "translation": "رقم هاتف جديد",
    "defaultMessage": "New phone number",
    "description": "Prompt for entering a new telephone number",
    "missing": false,
    "obsolete": false
  },
  "change_email": {
    "translation": "تغيير البريد الإلكتروني",
    "defaultMessage": "Change email",
    "description": "Prompt to change current email",
    "missing": false,
    "obsolete": false
  },
  "change_phone": {
    "translation": "تغيير رقم الهاتف",
    "defaultMessage": "Change phone number",
    "description": "Prompt to change current phone number",
    "missing": false,
    "obsolete": false
  },
  "call_busy": {
    "translation": "مشغول",
    "defaultMessage": "busy",
    "description": "Label for busy call line",
    "missing": false,
    "obsolete": false
  },
  "failed_to_init_audio": {
    "translation": "فشل في تهيئة تسجيل الصوت",
    "defaultMessage": "Failed to initialize audio recording",
    "description": "Error message when audio is not available",
    "missing": false,
    "obsolete": false
  },
  "password_reset_success": {
    "translation": "تم إعادة تعيين كلمة المرور بنجاح",
    "defaultMessage": "Password reset successfully",
    "description": "Notification message that the password was successfully reset.",
    "missing": false,
    "obsolete": false
  },
  "scan_qr_code": {
    "translation": "مسح رمز QR",
    "defaultMessage": "Scan QR Code",
    "description": "Title for scanning QR code",
    "missing": false,
    "obsolete": false
  },
  "alias_already_taken": {
    "translation": "(مُستخدم بالفعل)",
    "defaultMessage": "(already taken)",
    "description": "Error message for alias already taken",
    "missing": false,
    "obsolete": false
  },
  "alias_editing_placeholder": {
    "translation": "الاسم المستعار (اختياري)",
    "defaultMessage": "Alias (optional)",
    "description": "Placeholder for editing user or topic alias",
    "missing": false,
    "obsolete": false
  },
  "alias_invalid": {
    "translation": "(غير صالح)",
    "defaultMessage": "(invalid)",
    "description": "Error message for invalid alias",
    "missing": false,
    "obsolete": false
  },
  "label_alias": {
    "translation": "الاسم المستعار:",
    "defaultMessage": "Alias:",
    "description": "Label for user or topic alias",
    "missing": false,
    "obsolete": false
  },
  "label_alias_edit": {
    "translation": "الاسم المستعار",
    "defaultMessage": "Alias",
    "description": "Label for editing user or topic alias",
    "missing": false,
    "obsolete": false
  },
  "message_deleted": {
    "translation": "تم حذف الرسالة",
    "defaultMessage": "message deleted",
    "description": "Pinned message is deleted",
    "missing": false,
    "obsolete": false
  },
  "message_not_found": {
    "translation": "لم يتم العثور على الرسالة",
    "defaultMessage": "message not found",
    "description": "Pinned message is not found",
    "missing": false,
    "obsolete": false
  },
  "pin_message": {
    "translation": "تثبيت",
    "defaultMessage": "Pin",
    "description": "Menu item [Pin] for pinning message to the top.",
    "missing": false,
    "obsolete": false
  },
  "select_country": {
    "translation": "اختر الدولة",
    "defaultMessage": "Select country",
    "description": "Placeholder for the country selector",
    "missing": false,
    "obsolete": false
  },
  "self_topic_comment": {
    "translation": "ملاحظات ورسائل وروابط وملفات محفوظة للمستقبل",
    "defaultMessage": "Notes, messages, links, files saved for posterity",
    "description": "Comment for self topic for UI",
    "missing": false,
    "obsolete": false
  },
  "self_topic_name": {
    "translation": "الرسائل المحفوظة",
    "defaultMessage": "Saved messages",
    "description": "Name of self topic for UI",
    "missing": false,
    "obsolete": false
  },
  "text_copied": {
    "translation": "تم النسخ إلى الحافظة",
    "defaultMessage": "Copied to clipboard",
    "description": "Notification that text has been copied to clipboard",
    "missing": false,
    "obsolete": false
  },
  "unpin_message": {
    "translation": "إلغاء التثبيت",
    "defaultMessage": "Unpin",
    "description": "Menu item [Unpin] for un-pinning the message.",
    "missing": false,
    "obsolete": false
  },
  "color_schema_dark": {
    "translation": "داكن",
    "defaultMessage": "Dark",
    "description": "Name of the color schema",
    "missing": false,
    "obsolete": false
  },
  "color_schema_light": {
    "translation": "فاتح",
    "defaultMessage": "Light",
    "description": "Name of the color schema",
    "missing": false,
    "obsolete": false
  },
  "color_schema_system"
Download .txt
gitextract_okuamhsj/

├── .babelrc
├── .gitattributes
├── .github/
│   └── ISSUE_TEMPLATE/
│       ├── bug_report.md
│       └── feature_request.md
├── .gitignore
├── .well-known/
│   └── assetlinks.json
├── LICENSE
├── README.md
├── audio/
│   ├── call-end.m4a
│   ├── call-in.m4a
│   ├── call-out.m4a
│   ├── dialing.m4a
│   └── msg.m4a
├── css/
│   └── base.css
├── firebase-init.js
├── img/
│   └── bkg/
│       └── index.json
├── index-dev.html
├── index.html
├── manifest.json
├── package.json
├── postcss.config.js
├── push.md
├── scripts/
│   ├── gen-version.js
│   └── i18n.js
├── service-worker.js
├── src/
│   ├── config.js
│   ├── constants.js
│   ├── dcodes.json
│   ├── i18n/
│   │   ├── ar.json
│   │   ├── de.json
│   │   ├── en.json
│   │   ├── es.json
│   │   ├── ex/
│   │   │   └── base-en.json
│   │   ├── fr.json
│   │   ├── it.json
│   │   ├── ko.json
│   │   ├── ro.json
│   │   ├── ru.json
│   │   ├── th.json
│   │   ├── uk.json
│   │   ├── vi.json
│   │   ├── zh-TW.json
│   │   └── zh.json
│   ├── i18n.min/
│   │   ├── ar.json
│   │   ├── de.json
│   │   ├── en.json
│   │   ├── es.json
│   │   ├── fr.json
│   │   ├── it.json
│   │   ├── ko.json
│   │   ├── ro.json
│   │   ├── ru.json
│   │   ├── th.json
│   │   ├── uk.json
│   │   ├── vi.json
│   │   ├── zh-TW.json
│   │   └── zh.json
│   ├── index.js
│   ├── lib/
│   │   ├── blob-helpers.js
│   │   ├── formatters.js
│   │   ├── host-name.js
│   │   ├── local-storage.js
│   │   ├── navigation.js
│   │   ├── strformat.js
│   │   ├── strformat.test.js
│   │   ├── utils.js
│   │   └── utils.test.js
│   ├── version.js
│   ├── views/
│   │   ├── acc-general-view.jsx
│   │   ├── acc-notifications-view.jsx
│   │   ├── acc-security-view.jsx
│   │   ├── acc-support-view.jsx
│   │   ├── account-settings-view.jsx
│   │   ├── contacts-view.jsx
│   │   ├── create-account-view.jsx
│   │   ├── info-view.jsx
│   │   ├── login-view.jsx
│   │   ├── logo-view.jsx
│   │   ├── messages-view.jsx
│   │   ├── new-topic-view.jsx
│   │   ├── password-reset-view.jsx
│   │   ├── settings-view.jsx
│   │   ├── sidepanel-view.jsx
│   │   ├── tinode-web.jsx
│   │   ├── topic-common-view.jsx
│   │   ├── validation-view.jsx
│   │   └── wallpapers.jsx
│   └── widgets/
│       ├── alert.jsx
│       ├── attachment.jsx
│       ├── audio-player.jsx
│       ├── audio-recorder.jsx
│       ├── avatar-crop.jsx
│       ├── avatar-upload.jsx
│       ├── badge-list.jsx
│       ├── button-back.jsx
│       ├── call-incoming.jsx
│       ├── call-message.jsx
│       ├── call-panel.jsx
│       ├── call-status.jsx
│       ├── chat-message.jsx
│       ├── checkbox.jsx
│       ├── chip-input.jsx
│       ├── chip.jsx
│       ├── contact-action.jsx
│       ├── contact-badges.jsx
│       ├── contact-list.jsx
│       ├── contact.jsx
│       ├── context-menu.jsx
│       ├── credential-edit.jsx
│       ├── cropper.jsx
│       ├── doc-preview.jsx
│       ├── error-panel.jsx
│       ├── file-progress.jsx
│       ├── forward-dialog.jsx
│       ├── group-manager.jsx
│       ├── group-subs.jsx
│       ├── host-selector.jsx
│       ├── image-preview.jsx
│       ├── in-place-edit.jsx
│       ├── inline-video.jsx
│       ├── invitation.jsx
│       ├── lazy-image.jsx
│       ├── letter-tile.jsx
│       ├── load-spinner.jsx
│       ├── menu-cancel.jsx
│       ├── menu-contacts.jsx
│       ├── menu-start.jsx
│       ├── meta-message.jsx
│       ├── new-topic-by-id.jsx
│       ├── new-topic-group.jsx
│       ├── permissions-editor.jsx
│       ├── phone-country-selector.jsx
│       ├── phone-edit.jsx
│       ├── pinned-messages.jsx
│       ├── received-marker.jsx
│       ├── search-contacts.jsx
│       ├── send-message.jsx
│       ├── show-qrcode.jsx
│       ├── side-navbar.jsx
│       ├── tag-manager.jsx
│       ├── the-card-mini.jsx
│       ├── the-card-preview.jsx
│       ├── topic-desc-edit.jsx
│       ├── topic-security.jsx
│       ├── unread-badge.jsx
│       ├── uploading-image.jsx
│       ├── video-preview.jsx
│       └── visible-password.jsx
├── umd/
│   ├── 0.prod.js
│   ├── 107.prod.js
│   ├── 128.prod.js
│   ├── 140.prod.js
│   ├── 143.prod.js
│   ├── 175.prod.js
│   ├── 178.prod.js
│   ├── 186.prod.js
│   ├── 187.prod.js
│   ├── 197.prod.js
│   ├── 203.prod.js
│   ├── 226.prod.js
│   ├── 246.prod.js
│   ├── 252.prod.js
│   ├── 264.prod.js
│   ├── 271.prod.js
│   ├── 290.prod.js
│   ├── 297.prod.js
│   ├── 311.prod.js
│   ├── 316.prod.js
│   ├── 327.prod.js
│   ├── 330.prod.js
│   ├── 336.prod.js
│   ├── 352.prod.js
│   ├── 365.prod.js
│   ├── 371.prod.js
│   ├── 372.prod.js
│   ├── 399.prod.js
│   ├── 429.prod.js
│   ├── 440.prod.js
│   ├── 472.prod.js
│   ├── 500.prod.js
│   ├── 501.prod.js
│   ├── 514.prod.js
│   ├── 536.prod.js
│   ├── 537.prod.js
│   ├── 552.prod.js
│   ├── 553.prod.js
│   ├── 564.prod.js
│   ├── 570.prod.js
│   ├── 632.prod.js
│   ├── 634.prod.js
│   ├── 64.prod.js
│   ├── 648.prod.js
│   ├── 688.prod.js
│   ├── 700.prod.js
│   ├── 734.prod.js
│   ├── 744.prod.js
│   ├── 747.prod.js
│   ├── 752.prod.js
│   ├── 780.prod.js
│   ├── 817.prod.js
│   ├── 827.prod.js
│   ├── 836.prod.js
│   ├── 844.prod.js
│   ├── 864.prod.js
│   ├── 868.prod.js
│   ├── 884.prod.js
│   ├── 889.prod.js
│   ├── 892.prod.js
│   ├── 898.prod.js
│   ├── 92.prod.js
│   ├── 932.prod.js
│   ├── 936.prod.js
│   ├── 942.prod.js
│   ├── 952.prod.js
│   ├── 961.prod.js
│   ├── 978.prod.js
│   ├── 993.prod.js
│   ├── 996.prod.js
│   ├── index.dev.js
│   ├── index.prod.js
│   ├── src_i18n_min_ar_json.dev.js
│   ├── src_i18n_min_de_json.dev.js
│   ├── src_i18n_min_en_json.dev.js
│   ├── src_i18n_min_es_json.dev.js
│   ├── src_i18n_min_fr_json.dev.js
│   ├── src_i18n_min_it_json.dev.js
│   ├── src_i18n_min_ko_json.dev.js
│   ├── src_i18n_min_ro_json.dev.js
│   ├── src_i18n_min_ru_json.dev.js
│   ├── src_i18n_min_th_json.dev.js
│   ├── src_i18n_min_uk_json.dev.js
│   ├── src_i18n_min_vi_json.dev.js
│   ├── src_i18n_min_zh-TW_json.dev.js
│   ├── src_i18n_min_zh_json.dev.js
│   ├── src_views_acc-security-view_jsx.dev.js
│   ├── src_views_account-settings-view_jsx.dev.js
│   ├── src_views_create-account-view_jsx.dev.js
│   ├── src_views_info-view_jsx.dev.js
│   ├── src_views_messages-view_jsx.dev.js
│   ├── src_views_password-reset-view_jsx.dev.js
│   ├── src_views_wallpapers_jsx.dev.js
│   ├── src_widgets_audio-recorder_jsx.dev.js
│   ├── src_widgets_call-panel_jsx.dev.js
│   ├── src_widgets_doc-preview_jsx.dev.js
│   ├── src_widgets_image-preview_jsx.dev.js
│   ├── src_widgets_phone-country-selector_jsx.dev.js
│   ├── src_widgets_the-card-preview_jsx.dev.js
│   ├── src_widgets_video-preview_jsx.dev.js
│   ├── tinode.dev.js
│   ├── tinode.prod.js
│   ├── vendors-node_modules_libphonenumber-js_examples_mobile_json_js-node_modules_libphonenumber-js-7e28c7.dev.js
│   ├── vendors-node_modules_libphonenumber-js_examples_mobile_json_js-node_modules_libphonenumber-js-883e54.dev.js
│   ├── vendors-node_modules_libphonenumber-js_mobile_exports_parsePhoneNumberWithError_js.dev.js
│   └── vendors-node_modules_webm-duration-fix_lib_index_js.dev.js
├── version.js
└── webpack.config.js
Download .txt
Showing preview only (554K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (5326 symbols across 151 files)

FILE: firebase-init.js
  constant FIREBASE_INIT (line 2) | const FIREBASE_INIT = {

FILE: scripts/gen-version.js
  function writeVersion (line 4) | function writeVersion(fileName, useExport) {

FILE: scripts/i18n.js
  constant EXTRACTED_STRINGS (line 9) | const EXTRACTED_STRINGS = './src/i18n/ex/base-en.json';
  constant BASE_LANG (line 10) | const BASE_LANG        = 'en';
  constant LANG_PATTERN (line 11) | const LANG_PATTERN     = './src/i18n/*.json';
  constant LANG_PATTERN_ONE (line 12) | const LANG_PATTERN_ONE = './src/i18n/%s.json';
  constant OUTPUT_PATTERN (line 13) | const OUTPUT_PATTERN   = './src/i18n.min/%s.json';
  function getLocaleFromFileName (line 17) | function getLocaleFromFileName(filename) {
  function printf (line 22) | function printf(str) {

FILE: src/config.js
  constant APP_NAME (line 4) | const APP_NAME = 'TinodeWeb/' + (PACKAGE_VERSION || '0.24');
  constant API_KEY (line 7) | const API_KEY = 'AQEAAAABAAD_rAp4DJh05a1HAwFT3A6K';
  constant KNOWN_HOSTS (line 10) | const KNOWN_HOSTS = {hosted: 'web.tinode.co', local: 'localhost:6060'};
  constant DEFAULT_HOST (line 13) | const DEFAULT_HOST = KNOWN_HOSTS.hosted;
  constant LOGGING_ENABLED (line 16) | const LOGGING_ENABLED = true;
  constant KEYPRESS_DELAY (line 19) | const KEYPRESS_DELAY = 3_000;
  constant READ_DELAY (line 21) | const READ_DELAY = 1_500;
  constant MIN_TAG_LENGTH (line 24) | const MIN_TAG_LENGTH = 2;
  constant MAX_TAG_LENGTH (line 26) | const MAX_TAG_LENGTH = 96;
  constant MAX_TAG_COUNT (line 28) | const MAX_TAG_COUNT = 16;
  constant DEFAULT_P2P_ACCESS_MODE (line 31) | const DEFAULT_P2P_ACCESS_MODE = 'JRWPS';
  constant NEW_GRP_ACCESS_MODE (line 33) | const NEW_GRP_ACCESS_MODE = 'JRWPSAO';
  constant CHANNEL_ACCESS_MODE (line 35) | const CHANNEL_ACCESS_MODE = 'JR';
  constant NO_ACCESS_MODE (line 38) | const NO_ACCESS_MODE = 'N';
  constant MEDIA_BREAKPOINT (line 42) | const MEDIA_BREAKPOINT = 640;
  constant REM_SIZE (line 44) | const REM_SIZE = 13;
  constant AVATAR_SIZE (line 48) | const AVATAR_SIZE = 384;
  constant MAX_AVATAR_BYTES (line 51) | const MAX_AVATAR_BYTES = 4096;
  constant BROKEN_IMAGE_SIZE (line 54) | const BROKEN_IMAGE_SIZE = 32;
  constant NO_DIMENSIONS_VIDEO (line 57) | const NO_DIMENSIONS_VIDEO = 128;
  constant MESSAGES_PAGE (line 60) | const MESSAGES_PAGE = 24;
  constant MAX_INBAND_ATTACHMENT_SIZE (line 68) | const MAX_INBAND_ATTACHMENT_SIZE = 262_144;
  constant MAX_EXTERN_ATTACHMENT_SIZE (line 72) | const MAX_EXTERN_ATTACHMENT_SIZE = 1 << 23;
  constant MAX_IMAGE_DIM (line 77) | const MAX_IMAGE_DIM = 1024;
  constant IMAGE_PREVIEW_DIM (line 80) | const IMAGE_PREVIEW_DIM = 64;
  constant VIDEO_PREVIEW_DIM (line 83) | const VIDEO_PREVIEW_DIM = 96;
  constant IMAGE_THUMBNAIL_DIM (line 86) | const IMAGE_THUMBNAIL_DIM = 36;
  constant VIDEO_THUMBNAIL_WIDTH (line 88) | const VIDEO_THUMBNAIL_WIDTH = 48;
  constant MAX_ONLINE_IN_TOPIC (line 92) | const MAX_ONLINE_IN_TOPIC = 4;
  constant MAX_TITLE_LENGTH (line 95) | const MAX_TITLE_LENGTH = 60;
  constant MAX_TOPIC_DESCRIPTION_LENGTH (line 97) | const MAX_TOPIC_DESCRIPTION_LENGTH = 360;
  constant MAX_PEER_TITLE_LENGTH (line 99) | const MAX_PEER_TITLE_LENGTH = 24;
  constant MESSAGE_PREVIEW_LENGTH (line 102) | const MESSAGE_PREVIEW_LENGTH = 80;
  constant QUOTED_REPLY_LENGTH (line 105) | const QUOTED_REPLY_LENGTH = 30;
  constant FORWARDED_PREVIEW_LENGTH (line 107) | const FORWARDED_PREVIEW_LENGTH = 84;
  constant EDIT_PREVIEW_LENGTH (line 109) | const EDIT_PREVIEW_LENGTH = 48;
  constant MIN_DURATION (line 112) | const MIN_DURATION = 2_000;
  constant MAX_DURATION (line 114) | const MAX_DURATION = 600_000;
  constant LINK_CONTACT_US (line 117) | const LINK_CONTACT_US = 'mailto:support@tinode.co';
  constant LINK_PRIVACY_POLICY (line 120) | const LINK_PRIVACY_POLICY = 'https://tinode.co/privacy.html';
  constant LINK_TERMS_OF_SERVICE (line 123) | const LINK_TERMS_OF_SERVICE = 'https://tinode.co/terms.html';
  constant IMMEDIATE_P2P_SUBSCRIPTION (line 128) | const IMMEDIATE_P2P_SUBSCRIPTION = false;
  constant CLICKABLE_URL_SCHEMES (line 131) | const CLICKABLE_URL_SCHEMES = ['http', 'https', 'ftp', 'ftps'];
  constant QRCODE_SIZE (line 134) | const QRCODE_SIZE = 128;
  constant WAKE_UP_TIMEOUT (line 139) | const WAKE_UP_TIMEOUT = 80000;
  constant WAKE_UP_TICK (line 141) | const WAKE_UP_TICK = 1000;
  constant MIN_SWIPE_DISTANCE (line 144) | const MIN_SWIPE_DISTANCE = REM_SIZE * 3;
  constant SELF_AVATAR_URI (line 147) | const SELF_AVATAR_URI = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iM...
  constant TOAST_DURATION (line 150) | const TOAST_DURATION = 3_000;
  constant DEFAULT_COLOR_SCHEME (line 153) | const DEFAULT_COLOR_SCHEME = 'auto';
  constant DEFAULT_TEXT_SIZE (line 156) | const DEFAULT_TEXT_SIZE = 10;
  constant DRAFTY_FR_MIME_TYPE_LEGACY (line 159) | const DRAFTY_FR_MIME_TYPE_LEGACY = 'application/json';
  constant WALLPAPER_DEFAULTS (line 162) | const WALLPAPER_DEFAULTS = {type: 'patt', index: 0, path:'img/bkg/'};

FILE: src/constants.js
  constant CALL_STATE_NONE (line 2) | const CALL_STATE_NONE = 0;
  constant CALL_STATE_OUTGOING_INITATED (line 3) | const CALL_STATE_OUTGOING_INITATED = 1;
  constant CALL_STATE_INCOMING_RECEIVED (line 4) | const CALL_STATE_INCOMING_RECEIVED = 2;
  constant CALL_STATE_IN_PROGRESS (line 5) | const CALL_STATE_IN_PROGRESS = 3;
  constant CALL_HEAD_STARTED (line 8) | const CALL_HEAD_STARTED = 'started';

FILE: src/index.js
  function gtag (line 20) | function gtag(){dataLayer.push(arguments);}

FILE: src/lib/blob-helpers.js
  constant SUPPORTED_IMAGE_FORMATS (line 5) | const SUPPORTED_IMAGE_FORMATS = ['image/jpeg', 'image/gif', 'image/png',...
  constant MIME_EXTENSIONS (line 6) | const MIME_EXTENSIONS         = ['jpg',        'gif',       'png',      ...
  function makeImageUrl (line 9) | function makeImageUrl(photo) {
  function fitImageSize (line 25) | function fitImageSize(width, height, maxWidth, maxHeight, forceSquare) {
  function fileNameForMime (line 65) | function fileNameForMime(fname, mime) {
  function imageScaled (line 82) | function imageScaled(fileOrBlob, maxWidth, maxHeight, maxSize, forceSqua...
  function imageCrop (line 138) | function imageCrop(mime, objURL, left, top, width, height, scale) {
  function fileToBase64 (line 173) | function fileToBase64(file) {
  function blobToBase64 (line 187) | function blobToBase64(blob) {
  function filePasted (line 201) | function filePasted(event, onImageSuccess, onAttachmentSuccess, onError) {
  function getMimeType (line 230) | function getMimeType(header) {
  function base64EncodedLen (line 237) | function base64EncodedLen(n) {
  function base64DecodedLen (line 243) | function base64DecodedLen(n) {
  function base64ReEncode (line 249) | function base64ReEncode(str) {
  function base64ToBlob (line 263) | function base64ToBlob(str, mime) {
  function intArrayToBase64 (line 286) | function intArrayToBase64(arr) {
  function base64ToIntArray (line 298) | function base64ToIntArray(b64) {
  function importVCard (line 310) | function importVCard(fileOrBlob) {

FILE: src/lib/formatters.js
  function fullFormatter (line 53) | function fullFormatter(style, data, values, key, stack) {
  function handleImageData (line 182) | function handleImageData(el, data, attr) {
  function handleVideoData (line 226) | function handleVideoData(el, data, attr) {
  function previewFormatter (line 267) | function previewFormatter(style, data, values, key) {
  function inlineImageAttr (line 365) | function inlineImageAttr(attr, data) {
  function inlineVideoAttr (line 384) | function inlineVideoAttr(attr, data) {
  function quoteFormatter (line 409) | function quoteFormatter(style, data, values, key) {
  function quoteImageOrVideo (line 462) | function quoteImageOrVideo(data, isVideo) {
  function replyFormatter (line 534) | function replyFormatter(style, data, values, key, stack) {

FILE: src/lib/host-name.js
  function detectServerAddress (line 4) | function detectServerAddress() {
  function isSecureConnection (line 17) | function isSecureConnection() {
  function isLocalHost (line 24) | function isLocalHost() {

FILE: src/lib/local-storage.js
  class LocalStorageUtil (line 4) | class LocalStorageUtil {
    method setObject (line 6) | static setObject(key, value) {
    method getObject (line 11) | static getObject(key) {
    method updateObject (line 17) | static updateObject(key, value) {
    method removeItem (line 23) | static removeItem(key) {

FILE: src/lib/navigation.js
  class HashNavigation (line 3) | class HashNavigation {
    method parseUrlHash (line 6) | static parseUrlHash(hash) {
    method navigateTo (line 26) | static navigateTo(url) {
    method composeUrlHash (line 30) | static composeUrlHash(path, params) {
    method addUrlParam (line 46) | static addUrlParam(hash, key, value) {
    method removeUrlParam (line 52) | static removeUrlParam(hash, key) {
    method removeUrlParams (line 58) | static removeUrlParams(hash, keys) {
    method setUrlSidePanel (line 69) | static setUrlSidePanel(hash, sidepanel) {
    method setUrlInfoPanel (line 75) | static setUrlInfoPanel(hash, infopanel) {
    method setUrlTopic (line 85) | static setUrlTopic(hash, topic) {

FILE: src/lib/strformat.js
  function shortDateFormat (line 2) | function shortDateFormat(then, locale) {
  function relativeDateFormat (line 20) | function relativeDateFormat(then, locale) {
  function secondsToTime (line 36) | function secondsToTime(seconds, fixedMin) {
  function bytesToHumanSize (line 56) | function bytesToHumanSize(bytes) {
  function shortenFileName (line 69) | function shortenFileName(filename, maxLength) {
  function stringToColorHash (line 79) | function stringToColorHash(value) {
  function letterTileColorId (line 90) | function letterTileColorId(userId) {
  function idToColorClass (line 99) | function idToColorClass(id, light, fg) {
  function flagEmoji (line 104) | function flagEmoji(countryCode) {
  function truncateString (line 114) | function truncateString(str, maxLength) {

FILE: src/lib/utils.js
  function updateFavicon (line 7) | function updateFavicon(count) {
  function theCard (line 24) | function theCard(fn, imageUrl, imageMimeType, note) {
  function arrayEqual (line 64) | function arrayEqual(a, b) {
  function asPhone (line 90) | function asPhone(val) {
  function asEmail (line 99) | function asEmail(val) {
  function isUrlRelative (line 114) | function isUrlRelative(url) {
  function sanitizeUrl (line 122) | function sanitizeUrl(url, allowedSchemes) {
  function sanitizeUrlForMime (line 157) | function sanitizeUrlForMime(url, mimeMajor) {
  function urlAsAttachment (line 179) | function urlAsAttachment(url) {
  function deliveryMarker (line 212) | function deliveryMarker(received) {
  function cancelablePromise (line 232) | function cancelablePromise(promise) {
  function defaultWallpaper (line 252) | function defaultWallpaper() {
  function wallpaperNameFromUrl (line 258) | function wallpaperNameFromUrl(wallpaperUrl) {
  function wallpaperTypeFromUrl (line 264) | function wallpaperTypeFromUrl(wallpaperUrl) {

FILE: src/version.js
  constant PACKAGE_VERSION (line 3) | const PACKAGE_VERSION = "0.25.2";

FILE: src/views/acc-general-view.jsx
  class AccGeneralView (line 5) | class AccGeneralView extends React.PureComponent {
    method constructor (line 6) | constructor(props) {
    method handleColorSchemaSelected (line 22) | handleColorSchemaSelected(e) {
    method handleTextSizeChanged (line 27) | handleTextSizeChanged(e) {
    method handleSendOnEnterSelected (line 34) | handleSendOnEnterSelected(e) {
    method render (line 39) | render() {

FILE: src/views/acc-notifications-view.jsx
  class AccNotificationsView (line 7) | class AccNotificationsView extends React.PureComponent {
    method constructor (line 8) | constructor(props) {
    method handleCheckboxClick (line 14) | handleCheckboxClick(what, checked) {
    method render (line 22) | render() {

FILE: src/views/acc-security-view.jsx
  class AccSecurityView (line 22) | class AccSecurityView extends React.Component {
    method constructor (line 23) | constructor(props) {
    method handlePasswordUpdate (line 49) | handlePasswordUpdate(pwd) {
    method handleLaunchPermissionsEditor (line 54) | handleLaunchPermissionsEditor(which) {
    method handleHidePermissionsEditor (line 61) | handleHidePermissionsEditor() {
    method handlePermissionsChanged (line 65) | handlePermissionsChanged(perm) {
    method handleCheckboxClick (line 75) | handleCheckboxClick(what, checked) {
    method handleDeleteAccount (line 79) | handleDeleteAccount(e) {
    method render (line 92) | render() {

FILE: src/views/acc-support-view.jsx
  class AccSupportView (line 9) | class AccSupportView extends React.PureComponent {
    method render (line 10) | render() {

FILE: src/views/account-settings-view.jsx
  function _clip (line 14) | function _clip(str, length) {
  class AccountSettingsView (line 18) | class AccountSettingsView extends React.Component {
    method constructor (line 19) | constructor(props) {
    method componentDidMount (line 33) | componentDidMount() {
    method componentWillUnmount (line 38) | componentWillUnmount() {
    method render (line 43) | render() {

FILE: src/views/contacts-view.jsx
  class ContactsView (line 17) | class ContactsView extends React.Component {
    method constructor (line 18) | constructor(props) {
    method deriveStateFromProps (line 26) | static deriveStateFromProps(props) {
    method componentDidUpdate (line 75) | componentDidUpdate(prevProps, prevState) {
    method handleAction (line 87) | handleAction(action_ignored) {
    method render (line 91) | render() {

FILE: src/views/create-account-view.jsx
  class CreateAccountView (line 19) | class CreateAccountView extends React.PureComponent {
    method constructor (line 20) | constructor(props) {
    method handleLoginChange (line 57) | handleLoginChange(e) {
    method handlePasswordChange (line 61) | handlePasswordChange(password) {
    method handleEmailChange (line 65) | handleEmailChange(e) {
    method handlePhoneChange (line 69) | handlePhoneChange(number) {
    method handleFnChange (line 73) | handleFnChange(e) {
    method handleImageChanged (line 77) | handleImageChanged(mime, img) {
    method handleToggleSaveToken (line 85) | handleToggleSaveToken() {
    method handleSubmit (line 90) | handleSubmit(e) {
    method handleAvatarCropped (line 106) | handleAvatarCropped(mime, blob, width, height) {
    method handleAvatarCropCancel (line 114) | handleAvatarCropCancel() {
    method uploadAvatar (line 120) | uploadAvatar(mime, blob, width, height) {
    method render (line 149) | render() {

FILE: src/views/info-view.jsx
  class InfoView (line 103) | class InfoView extends React.Component {
    method constructor (line 104) | constructor(props) {
    method propsUpdated (line 157) | propsUpdated(props) {
    method componentDidMount (line 180) | componentDidMount() {
    method componentDidUpdate (line 184) | componentDidUpdate(props) {
    method componentWillUnmount (line 188) | componentWillUnmount() {
    method resetSubs (line 198) | resetSubs(topic, props) {
    method resetDesc (line 220) | resetDesc(topic, props) {
    method resetTags (line 264) | resetTags(topic) {
    method onMetaDesc (line 276) | onMetaDesc(desc) {
    method onSubsUpdated (line 288) | onSubsUpdated(subs) {
    method handleImageChanged (line 300) | handleImageChanged(mime, img) {
    method handleMuted (line 305) | handleMuted(ignored, checked) {
    method handleUnarchive (line 310) | handleUnarchive(ignored, ignored2) {
    method handlePermissionsChanged (line 314) | handlePermissionsChanged(which, perm) {
    method handleLaunchPermissionsEditor (line 337) | handleLaunchPermissionsEditor(which, uid) {
    method handleShowQRCode (line 413) | handleShowQRCode(e) {
    method handleCopyToClipboard (line 418) | handleCopyToClipboard(e, text) {
    method handleShare (line 426) | handleShare(e) {
    method handleShowAddMembers (line 433) | handleShowAddMembers(e) {
    method handleMemberUpdateRequest (line 439) | handleMemberUpdateRequest(members, added, removed) {
    method handleMemberSelected (line 444) | handleMemberSelected(uid) {
    method handleBackNavigate (line 448) | handleBackNavigate() {
    method handleContextMenu (line 463) | handleContextMenu(params) {
    method render (line 493) | render() {

FILE: src/views/login-view.jsx
  class LoginView (line 8) | class LoginView extends React.Component {
    method constructor (line 9) | constructor(props) {
    method handleLoginChange (line 24) | handleLoginChange(e) {
    method handlePasswordChange (line 28) | handlePasswordChange(e) {
    method handleToggleSaveToken (line 32) | handleToggleSaveToken() {
    method handleSubmit (line 37) | handleSubmit(e) {
    method render (line 42) | render() {

FILE: src/views/logo-view.jsx
  class LogoView (line 9) | class LogoView extends React.PureComponent {
    method render (line 10) | render() {

FILE: src/views/messages-view.jsx
  constant NOTIFICATION_EXEC_INTERVAL (line 34) | const NOTIFICATION_EXEC_INTERVAL = 300;
  constant SHOW_GO_TO_LAST_DIST (line 36) | const SHOW_GO_TO_LAST_DIST = 100;
  constant FETCH_PAGE_TRIGGER (line 38) | const FETCH_PAGE_TRIGGER = 40;
  function isUnconfirmed (line 116) | function isUnconfirmed(acs) {
  function isPeerRestricted (line 124) | function isPeerRestricted(acs) {
  function shouldPresentCallPanel (line 132) | function shouldPresentCallPanel(callState) {
  class MessagesView (line 139) | class MessagesView extends React.Component {
    method constructor (line 140) | constructor(props) {
    method getOrCreateMessageRef (line 212) | getOrCreateMessageRef(seqId) {
    method getVisibleMessageRange (line 221) | getVisibleMessageRange(holderRect) {
    method componentDidMount (line 243) | componentDidMount() {
    method componentWillUnmount (line 254) | componentWillUnmount() {
    method componentDidUpdate (line 272) | componentDidUpdate(prevProps, prevState) {
    method componentSetup (line 296) | componentSetup(prevProps, prevState) {
    method getDerivedStateFromProps (line 336) | static getDerivedStateFromProps(nextProps, prevState) {
    method subscribe (line 539) | subscribe(topic) {
    method leave (line 603) | leave(oldTopicName) {
    method handleScrollReference (line 628) | handleScrollReference(node) {
    method handleScrollEvent (line 638) | handleScrollEvent(event) {
    method mountDnDEvents (line 669) | mountDnDEvents(dnd) {
    method goToLatestMessage (line 680) | goToLatestMessage() {
    method handleDescChange (line 687) | handleDescChange(desc) {
    method postReadNotification (line 716) | postReadNotification(seq) {
    method clearNotificationQueue (line 776) | clearNotificationQueue() {
    method handleSubsUpdated (line 784) | handleSubsUpdated() {
    method handleMessageUpdate (line 809) | handleMessageUpdate(msg) {
    method handleAllMessagesReceived (line 848) | handleAllMessagesReceived(count) {
    method handleAuxUpdate (line 873) | handleAuxUpdate(aux) {
    method handleInfoReceipt (line 885) | handleInfoReceipt(info) {
    method handleExpandMedia (line 905) | handleExpandMedia(content) {
    method handleClosePreview (line 917) | handleClosePreview() {
    method handleFormResponse (line 934) | handleFormResponse(action, text, data) {
    method handleContextClick (line 959) | handleContextClick(e) {
    method handleShowMessageContextMenu (line 965) | handleShowMessageContextMenu(params, messageSpecificMenuItems) {
    method handleNewChatAcceptance (line 1008) | handleNewChatAcceptance(action) {
    method handleEnablePeer (line 1012) | handleEnablePeer(e) {
    method sendKeyPress (line 1017) | sendKeyPress(audio) {
    method sendMessage (line 1029) | sendMessage(msg, uploadCompletionPromise, uploader) {
    method retrySend (line 1060) | retrySend(pub) {
    method sendFileAttachment (line 1072) | sendFileAttachment(file) {
    method sendTheCardAttachment (line 1121) | sendTheCardAttachment(file, maxInbandAttachmentSize) {
    method handleAttachFile (line 1144) | handleAttachFile(file) {
    method handleCallHangup (line 1163) | handleCallHangup(topic, seq) {
    method handleCallPanelToggle (line 1171) | handleCallPanelToggle() {
    method sendImageAttachment (line 1176) | sendImageAttachment(caption, blob) {
    method sendVideoAttachment (line 1242) | sendVideoAttachment(caption, videoBlob, previewBlob, params) {
    method handleAttachImageOrVideo (line 1329) | handleAttachImageOrVideo(file) {
    method handleFileDrop (line 1361) | handleFileDrop(files) {
    method sendAudioAttachment (line 1374) | sendAudioAttachment(url, preview, duration) {
    method handleCancelUpload (line 1414) | handleCancelUpload(seq, uploader) {
    method handlePickReply (line 1427) | handlePickReply(seq, content, senderId, senderName) {
    method handleEditMessage (line 1453) | handleEditMessage(seq, content) {
    method handleCancelReply (line 1481) | handleCancelReply() {
    method handleQuoteClick (line 1486) | handleQuoteClick(replyToSeq) {
    method handleUnpinMessage (line 1497) | handleUnpinMessage(seq) {
    method isDragEnabled (line 1502) | isDragEnabled() {
    method handleDragStart (line 1506) | handleDragStart(e) {
    method handleDragIn (line 1512) | handleDragIn(e) {
    method handleDragOut (line 1521) | handleDragOut(e) {
    method handleDrag (line 1530) | handleDrag(e) {
    method handleDrop (line 1535) | handleDrop(e) {
    method render (line 1545) | render() {

FILE: src/views/new-topic-view.jsx
  class NewTopicView (line 33) | class NewTopicView extends React.Component {
    method constructor (line 34) | constructor(props) {
    method componentDidMount (line 53) | componentDidMount() {
    method handleTabClick (line 57) | handleTabClick(e) {
    method handleSearchContacts (line 63) | handleSearchContacts(query) {
    method handleSearchResultSelected (line 88) | handleSearchResultSelected(topicName) {
    method handleNewGroupSubmit (line 95) | handleNewGroupSubmit(name, description, dataUrl, priv, tags, isChannel) {
    method handleGroupByID (line 101) | handleGroupByID(topicName) {
    method render (line 106) | render() {

FILE: src/views/password-reset-view.jsx
  class PasswordResetView (line 23) | class PasswordResetView extends React.PureComponent {
    method constructor (line 24) | constructor(props) {
    method componentDidMount (line 49) | componentDidMount() {
    method componentDidUpdate (line 64) | componentDidUpdate(prevProps, prevState) {
    method handleSubmit (line 70) | handleSubmit(e) {
    method handleEmailChange (line 103) | handleEmailChange(e) {
    method handlePasswordChange (line 107) | handlePasswordChange(e) {
    method handleCodeChange (line 111) | handleCodeChange(e) {
    method handleShowCodeField (line 115) | handleShowCodeField(e) {
    method render (line 120) | render() {

FILE: src/views/settings-view.jsx
  class SettingsView (line 9) | class SettingsView extends React.PureComponent {
    method constructor (line 10) | constructor(props) {
    method handleSubmit (line 25) | handleSubmit(e) {
    method handleTransportSelected (line 34) | handleTransportSelected(e) {
    method handleServerAddressChange (line 38) | handleServerAddressChange(name) {
    method handleToggleSecure (line 42) | handleToggleSecure(e) {
    method render (line 46) | render() {

FILE: src/views/sidepanel-view.jsx
  class SidepanelView (line 107) | class SidepanelView extends React.PureComponent {
    method constructor (line 108) | constructor(props) {
    method handleNewTopic (line 114) | handleNewTopic() {
    method render (line 118) | render() {

FILE: src/views/tinode-web.jsx
  constant POP_SOUND (line 35) | const POP_SOUND = new Audio('audio/msg.m4a');
  class TinodeWeb (line 100) | class TinodeWeb extends React.Component {
    method constructor (line 101) | constructor(props) {
    method getBlankState (line 206) | getBlankState() {
    method componentDidMount (line 312) | componentDidMount() {
    method componentWillUnmount (line 408) | componentWillUnmount() {
    method tnSetup (line 421) | static tnSetup(serverAddress, secureConnection, transport, locale, per...
    method handlePushMessage (line 430) | handlePushMessage(payload) {
    method initFCMessaging (line 434) | initFCMessaging() {
    method requestFCMToken (line 484) | static requestFCMToken(fcm, sw) {
    method handleResize (line 514) | handleResize() {
    method handleEscapeKey (line 525) | handleEscapeKey(e) {
    method checkForAppUpdate (line 547) | checkForAppUpdate(reg) {
    method handleHashRoute (line 567) | handleHashRoute() {
    method handleOnline (line 626) | handleOnline(online) {
    method handleVisibilityEvent (line 637) | handleVisibilityEvent() {
    method stateForError (line 641) | static stateForError(err, level, action, actionText) {
    method handleError (line 651) | handleError(err, level, action, actionText) {
    method handleLoginRequest (line 656) | handleLoginRequest(login, password) {
    method handlePersistenceChange (line 684) | handlePersistenceChange(persist) {
    method handleConnected (line 699) | handleConnected() {
    method handleAutoreconnectIteration (line 718) | handleAutoreconnectIteration(sec, prom) {
    method handleDisconnect (line 764) | handleDisconnect(err) {
    method doLogin (line 778) | doLogin(login, password, tmpToken, cred) {
    method navigateToCredentialsView (line 839) | static navigateToCredentialsView(params) {
    method handleLoginSuccessful (line 848) | handleLoginSuccessful() {
    method tnMeMetaDesc (line 896) | tnMeMetaDesc(desc) {
    method tnMeContactUpdate (line 932) | tnMeContactUpdate(what, cont) {
    method tnMeSubsUpdated (line 983) | tnMeSubsUpdated(unused) {
    method prepareSearchableContacts (line 989) | static prepareSearchableContacts(chatList, foundContacts) {
    method resetContactList (line 1016) | resetContactList() {
    method checkIfPinsUpdated (line 1052) | static checkIfPinsUpdated(me, chatList) {
    method tnInitFind (line 1063) | tnInitFind() {
    method tnFndSubsUpdated (line 1075) | tnFndSubsUpdated() {
    method handleSearchContacts (line 1090) | handleSearchContacts(query) {
    method handleTopicSelected (line 1098) | handleTopicSelected(topicName) {
    method handleHideMessagesView (line 1140) | handleHideMessagesView() {
    method handleSendMessage (line 1153) | handleSendMessage(msg, uploadCompletionPromise, uploader, head) {
    method sendMessageToTopic (line 1158) | sendMessageToTopic(topic, msg, uploadCompletionPromise, uploader, head) {
    method handleNewChatInvitation (line 1211) | handleNewChatInvitation(topicName, action) {
    method handleNewAccount (line 1245) | handleNewAccount() {
    method handleNewAccountRequest (line 1252) | handleNewAccountRequest(login_, password_, public_, cred_, tags_) {
    method handleToggleIncognitoMode (line 1275) | handleToggleIncognitoMode(on) {
    method handleChangeColorSchema (line 1289) | handleChangeColorSchema(schema) {
    method handleColorSchemeChange (line 1297) | handleColorSchemeChange(event) {
    method applyColorSchema (line 1303) | applyColorSchema(schema, systemSchema, size) {
    method handleSelectWallpapers (line 1309) | handleSelectWallpapers() {
    method applyWallpaperSettings (line 1314) | applyWallpaperSettings(wallpaper, size, blur, effectiveSchema) {
    method handleWallpaperSelected (line 1324) | handleWallpaperSelected(wallpaper, size, blur) {
    method handleChangeTextSize (line 1332) | handleChangeTextSize(size) {
    method handleSendOnEnter (line 1338) | handleSendOnEnter(option) {
    method handleUpdateAccountTagsRequest (line 1343) | handleUpdateAccountTagsRequest(_, tags) {
    method handleSettings (line 1349) | handleSettings() {
    method handleGlobalSettings (line 1357) | handleGlobalSettings(settings) {
    method handleShowArchive (line 1390) | handleShowArchive() {
    method handleShowBlocked (line 1396) | handleShowBlocked() {
    method toggleFCMToken (line 1401) | toggleFCMToken(enabled) {
    method handleToggleMessageSounds (line 1428) | handleToggleMessageSounds(enabled) {
    method handleCredAdd (line 1435) | handleCredAdd(method, value) {
    method handleCredDelete (line 1441) | handleCredDelete(method, value) {
    method handleCredConfirm (line 1447) | handleCredConfirm(method, response) {
    method handleSidepanelCancel (line 1452) | handleSidepanelCancel() {
    method basicNavigator (line 1479) | basicNavigator(hash) {
    method infoNavigator (line 1484) | infoNavigator(hash) {
    method handleStartTopicRequest (line 1489) | handleStartTopicRequest(topicName, newTopicParams, isChannel) {
    method handleNewTopicCreated (line 1514) | handleNewTopicCreated(oldName, newName) {
    method handleTopicUpdateRequest (line 1530) | handleTopicUpdateRequest(topicName, pub, priv, defacs) {
    method handleUnarchive (line 1560) | handleUnarchive(topicName) {
    method handleUpdatePasswordRequest (line 1567) | handleUpdatePasswordRequest(password)  {
    method handleChangePermissions (line 1576) | handleChangePermissions(topicName, mode, uid) {
    method handleTagsUpdateRequest (line 1592) | handleTagsUpdateRequest(topicName, tags) {
    method handleLogout (line 1600) | handleLogout() {
    method handleDeleteAccount (line 1640) | handleDeleteAccount() {
    method handleDeleteTopicRequest (line 1646) | handleDeleteTopicRequest(topicName) {
    method handleDeleteMessagesRequest (line 1661) | handleDeleteMessagesRequest(topicName) {
    method handleLeaveUnsubRequest (line 1672) | handleLeaveUnsubRequest(topicName) {
    method handleBlockTopicRequest (line 1686) | handleBlockTopicRequest(topicName) {
    method handleReportTopic (line 1700) | handleReportTopic(topicName) {
    method handleShowContextMenu (line 1718) | handleShowContextMenu(params, menuItems) {
    method handleShowForwardDialog (line 1729) | handleShowForwardDialog(params) {
    method handleShareTheCard (line 1749) | handleShareTheCard(card) {
    method defaultTopicContextMenu (line 1759) | defaultTopicContextMenu(topicName) {
    method handleHideContextMenu (line 1813) | handleHideContextMenu() {
    method handleHideForwardDialog (line 1822) | handleHideForwardDialog(keepForwardedMessage) {
    method handleContextMenuAction (line 1829) | handleContextMenuAction(action, promise, params) {
    method handleShowAlert (line 1841) | handleShowAlert(title, content, onConfirm, confirmText, onReject, reje...
    method handleShowInfoView (line 1855) | handleShowInfoView() {
    method handleMemberUpdateRequest (line 1860) | handleMemberUpdateRequest(topicName, added, removed) {
    method handleValidateCredentialsRequest (line 1885) | handleValidateCredentialsRequest(cred, code, token) {
    method handlePasswordResetRequest (line 1898) | handlePasswordResetRequest(method, value) {
    method handleResetPassword (line 1908) | handleResetPassword(newPassword, tempAuth) {
    method handleShowCountrySelector (line 1925) | handleShowCountrySelector(code, dial, selectedCallback) {
    method handleStartVideoCall (line 1939) | handleStartVideoCall() {
    method handleStartAudioCall (line 1947) | handleStartAudioCall() {
    method handleCallInvite (line 1955) | handleCallInvite(callTopic, callSeq, callState, audioOnly) {
    method handleCallRinging (line 1979) | handleCallRinging(callTopic, callSeq) {
    method handleCallHangup (line 1988) | handleCallHangup(callTopic, callSeq) {
    method handleCallSendOffer (line 1997) | handleCallSendOffer(callTopic, callSeq, sdp) {
    method handleCallIceCandidate (line 2006) | handleCallIceCandidate(callTopic, callSeq, candidate) {
    method handleCallSendAnswer (line 2014) | handleCallSendAnswer(callTopic, callSeq, sdp) {
    method handleCallClose (line 2023) | handleCallClose() {
    method handleCallAccept (line 2034) | handleCallAccept(topicName, setCallTopic, callSeq) {
    method handleInfoMessage (line 2057) | handleInfoMessage(info) {
    method handleDataMessage (line 2085) | handleDataMessage(data) {
    method render (line 2118) | render() {

FILE: src/views/topic-common-view.jsx
  class TopicCommonView (line 9) | class TopicCommonView extends React.Component {
    method constructor (line 10) | constructor(props) {
    method componentDidUpdate (line 26) | componentDidUpdate(props) {
    method componentWillUnmount (line 46) | componentWillUnmount() {
    method onTagsUpdated (line 52) | onTagsUpdated(tags) {
    method handleTagsUpdated (line 61) | handleTagsUpdated(tags) {
    method render (line 67) | render() {

FILE: src/views/validation-view.jsx
  class ValidationView (line 18) | class ValidationView extends React.PureComponent {
    method constructor (line 19) | constructor(props) {
    method getDerivedStateFromProps (line 33) | static getDerivedStateFromProps(nextProps, prevState) {
    method componentDidMount (line 44) | componentDidMount() {
    method componentDidUpdate (line 51) | componentDidUpdate(prevProps, prevState) {
    method handleCodeChange (line 59) | handleCodeChange(e) {
    method handleKeyPress (line 63) | handleKeyPress(e) {
    method handleSubmit (line 71) | handleSubmit(e) {
    method handleCancel (line 78) | handleCancel(e) {
    method render (line 83) | render() {

FILE: src/views/wallpapers.jsx
  class WallpapersView (line 9) | class WallpapersView extends React.PureComponent {
    method constructor (line 10) | constructor(props) {
    method handleTabClick (line 30) | handleTabClick(e) {
    method handleWallpaperSelected (line 36) | handleWallpaperSelected(e) {
    method handleBlurChanged (line 59) | handleBlurChanged(e) {
    method hasChanged (line 69) | hasChanged() {
    method render (line 75) | render() {

FILE: src/widgets/alert.jsx
  class Alert (line 4) | class Alert extends React.PureComponent {
    method render (line 5) | render() {

FILE: src/widgets/attachment.jsx
  class Attachment (line 8) | class Attachment extends React.Component {
    method constructor (line 9) | constructor(props) {
    method downloadFile (line 21) | downloadFile(url, filename, mimetype) {
    method handleCancel (line 42) | handleCancel() {
    method render (line 50) | render() {

FILE: src/widgets/audio-player.jsx
  constant CANVAS_UPSCALING (line 10) | const CANVAS_UPSCALING = 2.0;
  constant LINE_WIDTH (line 12) | const LINE_WIDTH = 3 * CANVAS_UPSCALING;
  constant SPACING (line 14) | const SPACING = 2 * CANVAS_UPSCALING;
  constant BAR_COLOR (line 16) | const BAR_COLOR = '#888A';
  constant BAR_COLOR_DARK (line 17) | const BAR_COLOR_DARK = '#666C';
  constant THUMB_COLOR (line 18) | const THUMB_COLOR = '#1781d7';
  constant MIN_PREVIEW_LENGTH (line 20) | const MIN_PREVIEW_LENGTH = 16;
  class AudioPlayer (line 30) | class AudioPlayer extends React.PureComponent {
    method constructor (line 31) | constructor(props) {
    method componentDidMount (line 63) | componentDidMount() {
    method componentWillUnmount (line 71) | componentWillUnmount() {
    method componentDidUpdate (line 81) | componentDidUpdate(prevProps) {
    method initAudio (line 95) | initAudio() {
    method initCanvas (line 107) | initCanvas() {
    method visualize (line 120) | visualize() {
    method resampleBars (line 181) | resampleBars(original) {
    method handlePlay (line 214) | handlePlay(e) {
    method handleError (line 229) | handleError(err) {
    method handleSeek (line 233) | handleSeek(e) {
    method render (line 246) | render() {

FILE: src/widgets/audio-recorder.jsx
  constant BUFFER_SIZE (line 16) | const BUFFER_SIZE = 256;
  constant CANVAS_UPSCALING (line 18) | const CANVAS_UPSCALING = 2.0;
  constant LINE_WIDTH (line 20) | const LINE_WIDTH = 3 * CANVAS_UPSCALING;
  constant SPACING (line 22) | const SPACING = 2 * CANVAS_UPSCALING;
  constant MILLIS_PER_BAR (line 24) | const MILLIS_PER_BAR = 100;
  constant BAR_COLOR (line 26) | const BAR_COLOR = '#BBBD';
  constant BAR_SCALE (line 28) | const BAR_SCALE = 64.0;
  constant VISUALIZATION_BARS (line 30) | const VISUALIZATION_BARS = 96;
  constant MAX_SAMPLES_PER_BAR (line 32) | const MAX_SAMPLES_PER_BAR = 10;
  constant DEFAULT_AUDIO_MIME_TYPE (line 35) | const DEFAULT_AUDIO_MIME_TYPE = 'audio/webm';
  constant SAFARI_AUDIO_MIME_TYPE (line 37) | const SAFARI_AUDIO_MIME_TYPE = 'audio/mp4';
  constant AUDIO_MIME_TYPES (line 38) | const AUDIO_MIME_TYPES = [DEFAULT_AUDIO_MIME_TYPE, SAFARI_AUDIO_MIME_TYP...
  class AudioRecorder (line 68) | class AudioRecorder extends React.PureComponent {
    method constructor (line 69) | constructor(props) {
    method componentDidMount (line 102) | componentDidMount() {
    method componentWillUnmount (line 119) | componentWillUnmount() {
    method visualize (line 127) | visualize() {
    method handlePause (line 218) | handlePause(e) {
    method handleResume (line 227) | handleResume(e) {
    method handleDelete (line 236) | handleDelete(e) {
    method handleDone (line 245) | handleDone(e) {
    method initCanvas (line 258) | initCanvas() {
    method initMediaRecording (line 270) | initMediaRecording(stream) {
    method getRecording (line 334) | getRecording(mimeType) {
    method createPreview (line 349) | createPreview(audio) {
    method cleanUp (line 378) | cleanUp() {
    method render (line 385) | render() {

FILE: src/widgets/avatar-crop.jsx
  class AvatarCrop (line 8) | class AvatarCrop extends React.PureComponent {
    method constructor (line 9) | constructor(props) {
    method handleChange (line 25) | handleChange(left, top, width, height, scale) {
    method handleSubmit (line 35) | handleSubmit() {
    method render (line 47) | render() {

FILE: src/widgets/avatar-upload.jsx
  class AvatarUpload (line 10) | class AvatarUpload extends React.Component {
    method constructor (line 11) | constructor(props) {
    method componentDidUpdate (line 21) | componentDidUpdate(prevProps) {
    method handleFileReceived (line 27) | handleFileReceived(e) {
    method render (line 34) | render() {

FILE: src/widgets/badge-list.jsx
  class BadgeList (line 26) | class BadgeList extends React.PureComponent {
    method render (line 27) | render() {

FILE: src/widgets/button-back.jsx
  class ButtonBack (line 4) | class ButtonBack extends React.PureComponent {
    method render (line 5) | render() {

FILE: src/widgets/call-incoming.jsx
  constant RING_SOUND (line 13) | const RING_SOUND = new Audio('audio/call-in.m4a');
  class CallIncoming (line 15) | class CallIncoming extends React.Component {
    method constructor (line 16) | constructor(props) {
    method componentDidMount (line 34) | componentDidMount() {
    method componentDidUpdate (line 50) | componentDidUpdate(props) {
    method componentWillUnmount (line 67) | componentWillUnmount() {
    method resetDesc (line 80) | resetDesc(topic) {
    method onMetaDesc (line 97) | onMetaDesc(desc) {
    method handleAcceptCall (line 109) | handleAcceptCall() {
    method handleRejectCall (line 113) | handleRejectCall() {
    method render (line 118) | render() {

FILE: src/widgets/call-message.jsx
  class CallMessage (line 8) | class CallMessage extends React.PureComponent {
    method render (line 9) | render() {

FILE: src/widgets/call-panel.jsx
  constant RING_SOUND (line 11) | const RING_SOUND = new Audio('audio/call-out.m4a');
  constant CALL_ENDED_SOUND (line 13) | const CALL_ENDED_SOUND = new Audio('audio/call-end.m4a');
  constant DIALING_SOUND (line 15) | const DIALING_SOUND = new Audio('audio/dialing.m4a');
  constant VIDEO_MUTED_EVENT (line 17) | const VIDEO_MUTED_EVENT = 'video:muted';
  constant VIDEO_UNMUTED_EVENT (line 18) | const VIDEO_UNMUTED_EVENT = 'video:unmuted';
  class CallPanel (line 28) | class CallPanel extends React.PureComponent {
    method constructor (line 29) | constructor(props) {
    method componentDidMount (line 154) | componentDidMount() {
    method componentWillUnmount (line 170) | componentWillUnmount() {
    method handleVideoCallAccepted (line 182) | handleVideoCallAccepted(info) {
    method onInfo (line 200) | onInfo(info) {
    method emptyVideoTrack (line 231) | emptyVideoTrack() {
    method start (line 240) | start() {
    method stop (line 272) | stop() {
    method disconnectMedia (line 302) | disconnectMedia(el) {
    method stopTracks (line 311) | stopTracks(stream) {
    method handleDataChannelError (line 325) | handleDataChannelError(error) {
    method handleDataChannelMessage (line 329) | handleDataChannelMessage(event) {
    method handleDataChannelOpen (line 342) | handleDataChannelOpen(event) {
    method handleDataChannelClose (line 348) | handleDataChannelClose(event) {
    method handleDataChannelEvent (line 352) | handleDataChannelEvent(event) {
    method createPeerConnection (line 362) | createPeerConnection(withDataChannel) {
    method handleVideoAnswerMsg (line 389) | handleVideoAnswerMsg(info) {
    method reportError (line 400) | reportError(err) {
    method canSendOffer (line 404) | canSendOffer() {
    method handleNegotiationNeededEvent (line 408) | handleNegotiationNeededEvent(event) {
    method handleIceCandidateErrorEvent (line 422) | handleIceCandidateErrorEvent(event) {
    method handleICECandidateEvent (line 426) | handleICECandidateEvent(event) {
    method handleNewICECandidateMsg (line 432) | handleNewICECandidateMsg(info) {
    method drainRemoteIceCandidatesCache (line 447) | drainRemoteIceCandidatesCache() {
    method handleICEConnectionStateChangeEvent (line 460) | handleICEConnectionStateChangeEvent(event) {
    method handleSignalingStateChangeEvent (line 469) | handleSignalingStateChangeEvent(event) {
    method handleICEGatheringStateChangeEvent (line 475) | handleICEGatheringStateChangeEvent(event) {
    method handleTrackEvent (line 479) | handleTrackEvent(event) {
    method handleGetUserMediaError (line 485) | handleGetUserMediaError(e) {
    method handleVideoOfferMsg (line 506) | handleVideoOfferMsg(info) {
    method handleRemoteHangup (line 552) | handleRemoteHangup() {
    method handleCloseClick (line 571) | handleCloseClick() {
    method muteVideo (line 577) | muteVideo() {
    method unmuteVideo (line 592) | unmuteVideo() {
    method handleToggleCameraClick (line 617) | handleToggleCameraClick() {
    method handleToggleMicClick (line 633) | handleToggleMicClick() {
    method render (line 641) | render() {

FILE: src/widgets/call-status.jsx
  class CallStatus (line 11) | class CallStatus extends React.PureComponent {
    method render (line 12) | render() {

FILE: src/widgets/chat-message.jsx
  class BaseChatMessage (line 15) | class BaseChatMessage extends React.PureComponent {
    method constructor (line 16) | constructor(props) {
    method handleExpandImage (line 83) | handleExpandImage(e) {
    method handlePlayVideo (line 95) | handlePlayVideo(e) {
    method handleFormButtonClick (line 110) | handleFormButtonClick(e) {
    method handleContextClick (line 127) | handleContextClick(e) {
    method handleProgress (line 174) | handleProgress(ratio) {
    method handleCancelUpload (line 178) | handleCancelUpload() {
    method handleQuoteClick (line 182) | handleQuoteClick(e) {
    method render (line 191) | render() {

FILE: src/widgets/checkbox.jsx
  class CheckBox (line 4) | class CheckBox extends React.PureComponent {
    method constructor (line 5) | constructor(props) {
    method handleChange (line 11) | handleChange() {
    method render (line 15) | render() {

FILE: src/widgets/chip-input.jsx
  class ChipInput (line 8) | class ChipInput extends React.Component {
    method constructor (line 9) | constructor(props) {
    method deriveStateFromProps (line 24) | static deriveStateFromProps(props) {
    method componentDidUpdate (line 31) | componentDidUpdate(prevProps, prevState) {
    method indexChips (line 43) | static indexChips(chips) {
    method sortChips (line 54) | static sortChips(chips, keep) {
    method handleTextInput (line 67) | handleTextInput(e) {
    method removeChipAt (line 74) | removeChipAt(idx) {
    method handleChipCancel (line 79) | handleChipCancel(item, idx) {
    method handleFocusGained (line 83) | handleFocusGained() {
    method handleFocusLost (line 87) | handleFocusLost() {
    method handleKeyDown (line 94) | handleKeyDown(e) {
    method render (line 113) | render() {

FILE: src/widgets/chip.jsx
  class Chip (line 5) | class Chip extends React.PureComponent {
    method constructor (line 6) | constructor(props) {
    method handleCancel (line 12) | handleCancel(e) {
    method render (line 17) | render() {

FILE: src/widgets/contact-action.jsx
  class ContactAction (line 5) | class ContactAction extends React.PureComponent {
    method constructor (line 6) | constructor(props) {
    method handleClick (line 12) | handleClick(e) {
    method render (line 18) | render() {

FILE: src/widgets/contact-badges.jsx
  class ContactBadges (line 6) | class ContactBadges extends React.PureComponent {
    method render (line 7) | render() {

FILE: src/widgets/contact-list.jsx
  class ContactList (line 28) | class ContactList extends React.PureComponent {
    method render (line 29) | render() {

FILE: src/widgets/contact.jsx
  class Contact (line 30) | class Contact extends React.Component {
    method constructor (line 31) | constructor(props) {
    method handleClick (line 38) | handleClick(e) {
    method handleContextClick (line 47) | handleContextClick(e) {
    method render (line 58) | render() {

FILE: src/widgets/context-menu.jsx
  class ContextMenu (line 141) | class ContextMenu extends React.Component {
    method constructor (line 142) | constructor(props) {
    method componentDidMount (line 416) | componentDidMount() {
    method componentWillUnmount (line 421) | componentWillUnmount() {
    method handlePageClick (line 426) | handlePageClick(e) {
    method handleEscapeKey (line 435) | handleEscapeKey(e) {
    method handleClick (line 441) | handleClick(e) {
    method deleteMessages (line 462) | deleteMessages(all, hard, params, errorHandler) {
    method retryMessage (line 491) | retryMessage(params, errorHandler) {
    method pinMessage (line 506) | pinMessage(pin, params, errorHandler) {
    method topicPermissionSetter (line 516) | topicPermissionSetter(mode, params, errorHandler) {
    method replyToMessage (line 530) | replyToMessage(params, errorHandler) {
    method editMessage (line 534) | editMessage(params, errorHandler) {
    method render (line 538) | render() {

FILE: src/widgets/credential-edit.jsx
  class CredentialEdit (line 21) | class CredentialEdit extends React.PureComponent {
    method constructor (line 22) | constructor(props) {
    method formatPhoneNumber (line 38) | static formatPhoneNumber(raw) {
    method handleEmailChange (line 46) | handleEmailChange(e) {
    method handlePhoneChange (line 50) | handlePhoneChange(number) {
    method handleCodeChange (line 54) | handleCodeChange(e) {
    method handleSubmit (line 58) | handleSubmit(e) {
    method render (line 72) | render() {

FILE: src/widgets/cropper.jsx
  constant DEFAULT_MAX_ZOOM (line 5) | const DEFAULT_MAX_ZOOM = 8;
  class Cropper (line 7) | class Cropper extends React.Component {
    method constructor (line 8) | constructor(props) {
    method componentDidMount (line 63) | componentDidMount() {
    method componentWillUnmount (line 77) | componentWillUnmount() {
    method positionAll (line 85) | positionAll(panX, panY, zoom) {
    method checkBound (line 107) | static checkBound(currPan, img, cutout, delta) {
    method initScaling (line 119) | initScaling() {
    method onZoom (line 144) | onZoom(e) {
    method handleZoom (line 148) | handleZoom(zoom) {
    method mouseDown (line 181) | mouseDown(e) {
    method translate (line 199) | translate(pageX, pageY) {
    method mouseMove (line 219) | mouseMove(e) {
    method mouseTouch (line 224) | mouseTouch(e) {
    method mouseUp (line 245) | mouseUp(e) {
    method render (line 256) | render() {

FILE: src/widgets/doc-preview.jsx
  function iconFromMime (line 8) | function iconFromMime(mime) {
  class DocPreview (line 15) | class DocPreview extends React.PureComponent {
    method constructor (line 16) | constructor(props) {
    method componentDidMount (line 23) | componentDidMount() {
    method componentWillUnmount (line 27) | componentWillUnmount() {
    method handleKeyDown (line 31) | handleKeyDown(e) {
    method handleSendDoc (line 38) | handleSendDoc(caption) {
    method render (line 43) | render() {

FILE: src/widgets/error-panel.jsx
  class ErrorPanel (line 5) | class ErrorPanel extends React.PureComponent {
    method constructor (line 6) | constructor(props) {
    method componentDidUpdate (line 16) | componentDidUpdate(prevProps) {
    method hide (line 24) | hide() {
    method render (line 31) | render() {

FILE: src/widgets/file-progress.jsx
  class FileProgress (line 5) | class FileProgress extends React.PureComponent {
    method render (line 6) | render() {

FILE: src/widgets/forward-dialog.jsx
  class ForwardDialog (line 10) | class ForwardDialog extends React.Component {
    method constructor (line 11) | constructor(props) {
    method componentDidMount (line 25) | componentDidMount() {
    method handleEscapeKey (line 29) | handleEscapeKey(e) {
    method handleClose (line 36) | handleClose(e) {
    method handleSearchContacts (line 41) | handleSearchContacts(query) {
    method handleContactSelected (line 46) | handleContactSelected(uid) {
    method render (line 51) | render() {

FILE: src/widgets/group-manager.jsx
  class GroupManager (line 26) | class GroupManager extends React.Component {
    method constructor (line 27) | constructor(props) {
    method indexMembers (line 47) | static indexMembers(members) {
    method staticMembers (line 55) | static staticMembers(members, keepInitial, requiredMember) {
    method selectedContacts (line 65) | static selectedContacts(members) {
    method handleContactSelected (line 73) | handleContactSelected(userId, index) {
    method handleMemberRemoved (line 97) | handleMemberRemoved(userId, index) {
    method handleContactFilter (line 116) | handleContactFilter(val) {
    method doContactFiltering (line 125) | static doContactFiltering(filter, values) {
    method handleSubmit (line 137) | handleSubmit() {
    method handleCancel (line 157) | handleCancel() {
    method render (line 161) | render() {

FILE: src/widgets/group-subs.jsx
  class GroupSubs (line 11) | class GroupSubs extends React.Component {
    method constructor (line 12) | constructor(props) {
    method render (line 16) | render() {

FILE: src/widgets/host-selector.jsx
  class HostSelector (line 7) | class HostSelector extends React.PureComponent {
    method constructor (line 8) | constructor(props) {
    method handleHostNameChange (line 21) | handleHostNameChange(e) {
    method handleEditingFinished (line 25) | handleEditingFinished() {
    method handleKeyDown (line 32) | handleKeyDown(e) {
    method render (line 38) | render() {

FILE: src/widgets/image-preview.jsx
  class ImagePreview (line 10) | class ImagePreview extends React.PureComponent {
    method constructor (line 11) | constructor(props) {
    method componentDidMount (line 23) | componentDidMount() {
    method componentWillUnmount (line 27) | componentWillUnmount() {
    method handleKeyDown (line 31) | handleKeyDown(e) {
    method assignWidth (line 42) | assignWidth(node) {
    method handleSendImage (line 52) | handleSendImage(caption) {
    method render (line 57) | render() {

FILE: src/widgets/in-place-edit.jsx
  class InPlaceEdit (line 6) | class InPlaceEdit extends React.Component {
    method constructor (line 7) | constructor(props) {
    method componentDidUpdate (line 26) | componentDidUpdate(prevProps, prevState) {
    method handeTextChange (line 38) | handeTextChange(e) {
    method handleKeyDown (line 54) | handleKeyDown(e) {
    method handleStartEditing (line 64) | handleStartEditing() {
    method handleEditingFinished (line 74) | handleEditingFinished(event) {
    method handlePasswordFinished (line 87) | handlePasswordFinished(value) {
    method render (line 94) | render() {

FILE: src/widgets/inline-video.jsx
  class InlineVideo (line 8) | class InlineVideo extends React.PureComponent {
    method constructor (line 9) | constructor(props) {
    method handleClick (line 17) | handleClick(e) {
    method render (line 24) | render() {

FILE: src/widgets/invitation.jsx
  class Invitation (line 5) | class Invitation extends React.PureComponent {
    method constructor (line 6) | constructor(props) {
    method handleButtonAction (line 12) | handleButtonAction(evt, data) {
    method render (line 17) | render() {

FILE: src/widgets/lazy-image.jsx
  class LazyImage (line 4) | class LazyImage extends React.PureComponent {
    method constructor (line 5) | constructor(props) {
    method componentDidMount (line 17) | componentDidMount() {
    method componentWillUnmount (line 25) | componentWillUnmount() {
    method componentDidUpdate (line 29) | componentDidUpdate(prevProps) {
    method render (line 39) | render() {

FILE: src/widgets/letter-tile.jsx
  class LetterTile (line 10) | class LetterTile extends React.PureComponent {
    method render (line 11) | render() {

FILE: src/widgets/load-spinner.jsx
  class LoadSpinner (line 3) | class LoadSpinner extends React.PureComponent {
    method render (line 4) | render() {

FILE: src/widgets/menu-cancel.jsx
  class MenuCancel (line 4) | class MenuCancel extends React.PureComponent {
    method render (line 5) | render() {

FILE: src/widgets/menu-contacts.jsx
  class MenuContacts (line 3) | class MenuContacts extends React.PureComponent {
    method render (line 4) | render() {

FILE: src/widgets/menu-start.jsx
  class MenuStart (line 3) | class MenuStart extends React.PureComponent {
    method render (line 4) | render() {

FILE: src/widgets/meta-message.jsx
  class MetaMessage (line 5) | class MetaMessage extends React.PureComponent {
    method constructor (line 6) | constructor(props) {
    method render (line 10) | render() {

FILE: src/widgets/new-topic-by-id.jsx
  class NewTopicById (line 15) | class NewTopicById extends React.PureComponent {
    method constructor (line 16) | constructor(props) {
    method componentDidMount (line 30) | componentDidMount() {
    method handleChange (line 38) | handleChange(e) {
    method handleKeyPress (line 42) | handleKeyPress(e) {
    method handleSubmit (line 48) | handleSubmit(e) {
    method render (line 61) | render() {

FILE: src/widgets/new-topic-group.jsx
  class NewTopicGroup (line 14) | class NewTopicGroup extends React.PureComponent {
    method constructor (line 15) | constructor(props) {
    method componentDidMount (line 41) | componentDidMount() {
    method handleFieldEdit (line 45) | handleFieldEdit(name, e) {
    method handleImageChanged (line 49) | handleImageChanged(mime, img) {
    method handleAvatarCropped (line 53) | handleAvatarCropped(mime, blob, width, height) {
    method handleAvatarCropCancel (line 61) | handleAvatarCropCancel() {
    method uploadAvatar (line 67) | uploadAvatar(mime, blob, width, height) {
    method handleTagsChanged (line 93) | handleTagsChanged(tags) {
    method handleChannelToggle (line 97) | handleChannelToggle() {
    method handleSubmit (line 101) | handleSubmit(e) {
    method render (line 112) | render() {

FILE: src/widgets/permissions-editor.jsx
  class PermissionsEditor (line 55) | class PermissionsEditor extends React.Component {
    method constructor (line 56) | constructor(props) {
    method handleChange (line 68) | handleChange(val) {
    method handleSubmit (line 79) | handleSubmit() {
    method handleCancel (line 90) | handleCancel() {
    method render (line 94) | render() {

FILE: src/widgets/phone-country-selector.jsx
  class PhoneCountrySelector (line 10) | class PhoneCountrySelector extends React.PureComponent {
    method constructor (line 11) | constructor(props) {
    method componentDidMount (line 31) | componentDidMount() {
    method render (line 37) | render() {

FILE: src/widgets/phone-edit.jsx
  class PhoneEdit (line 19) | class PhoneEdit extends React.PureComponent {
    method constructor (line 20) | constructor(props) {
    method handleChange (line 42) | handleChange(e) {
    method handleFinished (line 49) | handleFinished(e) {
    method handleKeyDown (line 67) | handleKeyDown(e) {
    method showCountrySelector (line 73) | showCountrySelector() {
    method filterNumber (line 85) | filterNumber(number) {
    method placeholderNumber (line 94) | placeholderNumber(code, dial) {
    method render (line 99) | render() {

FILE: src/widgets/pinned-messages.jsx
  class PinnedMessages (line 22) | class PinnedMessages extends React.PureComponent {
    method constructor (line 23) | constructor(props) {
    method componentDidMount (line 42) | componentDidMount() {
    method componentWillUnmount (line 48) | componentWillUnmount() {
    method getSelectedIndex (line 53) | getSelectedIndex() {
    method handleCancel (line 58) | handleCancel(e) {
    method handleSelected (line 63) | handleSelected(e) {
    method handleMoveNext (line 68) | handleMoveNext(e, isTouch) {
    method handleMovePrev (line 78) | handleMovePrev(e, isTouch) {
    method handleTouchEventStart (line 88) | handleTouchEventStart(e) {
    method handleTouchEventEnd (line 95) | handleTouchEventEnd(e) {
    method handleTouchCancel (line 117) | handleTouchCancel() {
    method render (line 121) | render() {

FILE: src/widgets/received-marker.jsx
  class ReceivedMarker (line 27) | class ReceivedMarker extends React.PureComponent {
    method render (line 28) | render() {

FILE: src/widgets/search-contacts.jsx
  class SearchContacts (line 5) | class SearchContacts extends React.PureComponent {
    method constructor (line 6) | constructor(props) {
    method componentWillUnmount (line 20) | componentWillUnmount() {
    method handleSearchChange (line 27) | handleSearchChange(e) {
    method handleSearch (line 31) | handleSearch(e) {
    method handleClear (line 38) | handleClear(e) {
    method handleKeyDown (line 46) | handleKeyDown(e) {
    method render (line 55) | render() {

FILE: src/widgets/send-message.jsx
  class SendMessage (line 62) | class SendMessage extends React.PureComponent {
    method constructor (line 63) | constructor(props) {
    method componentDidMount (line 90) | componentDidMount() {
    method componentWillUnmount (line 102) | componentWillUnmount() {
    method componentDidUpdate (line 108) | componentDidUpdate(prevProps) {
    method formatReply (line 135) | formatReply() {
    method handlePasteEvent (line 143) | handlePasteEvent(e) {
    method handleAttachImage (line 158) | handleAttachImage(e) {
    method handleAttachFile (line 166) | handleAttachFile(e) {
    method handleDropAttach (line 174) | handleDropAttach(files) {
    method handleAttachAudio (line 180) | handleAttachAudio(url, preview, duration) {
    method handleSend (line 185) | handleSend(e) {
    method handleKeyPress (line 195) | handleKeyPress(e) {
    method handleMessageTyping (line 224) | handleMessageTyping(e) {
    method handleQuoteClick (line 235) | handleQuoteClick(e) {
    method render (line 244) | render() {

FILE: src/widgets/show-qrcode.jsx
  class ShowQRCode (line 7) | class ShowQRCode extends React.PureComponent {
    method constructor (line 8) | constructor(props) {
    method componentDidMount (line 13) | componentDidMount() {
    method render (line 21) | render() {

FILE: src/widgets/side-navbar.jsx
  class SideNavbar (line 11) | class SideNavbar extends React.PureComponent {
    method render (line 12) | render() {

FILE: src/widgets/tag-manager.jsx
  class TagManager (line 12) | class TagManager extends React.Component {
    method constructor (line 13) | constructor(props) {
    method getDerivedStateFromProps (line 30) | static getDerivedStateFromProps(nextProps, prevState) {
    method handleTagInput (line 41) | handleTagInput(text) {
    method handleAddTag (line 57) | handleAddTag(tag) {
    method handleRemoveTag (line 73) | handleRemoveTag(tag, index) {
    method handleSubmit (line 82) | handleSubmit() {
    method handleCancel (line 92) | handleCancel() {
    method render (line 99) | render() {

FILE: src/widgets/the-card-mini.jsx
  class TheCardMini (line 15) | class TheCardMini extends React.PureComponent {
    method constructor (line 16) | constructor(props) {
    method handleDownload (line 23) | handleDownload(e) {
    method handleMessage (line 45) | handleMessage(e) {
    method render (line 49) | render() {

FILE: src/widgets/the-card-preview.jsx
  class TheCardPreview (line 19) | class TheCardPreview extends React.PureComponent {
    method constructor (line 20) | constructor(props) {
    method componentDidMount (line 38) | componentDidMount() {
    method componentWillUnmount (line 42) | componentWillUnmount() {
    method handleKeyDown (line 46) | handleKeyDown(e) {
    method handleSendCard (line 53) | handleSendCard() {
    method render (line 58) | render() {

FILE: src/widgets/topic-desc-edit.jsx
  constant ALIAS_AVAILABILITY_CHECK_DELAY (line 42) | const ALIAS_AVAILABILITY_CHECK_DELAY = 1000;
  class TopicDescEdit (line 44) | class TopicDescEdit extends React.Component {
    method constructor (line 45) | constructor(props) {
    method componentDidMount (line 85) | componentDidMount() {
    method componentWillUnmount (line 91) | componentWillUnmount() {
    method tnNewTags (line 97) | tnNewTags(tags) {
    method handleFullNameUpdate (line 101) | handleFullNameUpdate(fn) {
    method handlePrivateUpdate (line 109) | handlePrivateUpdate(comment) {
    method handleDescriptionUpdate (line 117) | handleDescriptionUpdate(desc) {
    method handleImageUpdated (line 126) | handleImageUpdated(mime, img) {
    method handleAvatarCropped (line 137) | handleAvatarCropped(mime, blob, width, height) {
    method uploadAvatar (line 147) | uploadAvatar(mime, blob, width, height) {
    method handleAvatarCropCancel (line 177) | handleAvatarCropCancel() {
    method handleAliasUpdate (line 181) | handleAliasUpdate(alias) {
    method validateAlias (line 189) | validateAlias(alias) {
    method cancelValidator (line 233) | cancelValidator() {
    method handleTagsUpdated (line 242) | handleTagsUpdated(tags) {
    method render (line 250) | render() {

FILE: src/widgets/topic-security.jsx
  class TopicSecurity (line 73) | class TopicSecurity extends React.PureComponent {
    method constructor (line 74) | constructor(props) {
    method handleDeleteTopic (line 84) | handleDeleteTopic(e) {
    method handleDeleteMessages (line 97) | handleDeleteMessages(e) {
    method handleLeave (line 110) | handleLeave(e) {
    method handleBlock (line 123) | handleBlock(e) {
    method handleReport (line 136) | handleReport(e) {
    method render (line 149) | render() {

FILE: src/widgets/unread-badge.jsx
  class UnreadBadge (line 4) | class UnreadBadge extends React.PureComponent {
    method render (line 5) | render() {

FILE: src/widgets/uploading-image.jsx
  class UploadingImage (line 6) | class UploadingImage extends React.PureComponent {
    method constructor (line 7) | constructor(props) {
    method render (line 11) | render() {

FILE: src/widgets/video-preview.jsx
  class VideoPreview (line 15) | class VideoPreview extends React.PureComponent {
    method constructor (line 16) | constructor(props) {
    method componentDidMount (line 25) | componentDidMount() {
    method componentWillUnmount (line 29) | componentWillUnmount() {
    method handleKeyDown (line 33) | handleKeyDown(e) {
    method handleSendVideo (line 44) | handleSendVideo(caption) {
    method render (line 71) | render() {

FILE: src/widgets/visible-password.jsx
  class VisiblePassword (line 4) | class VisiblePassword extends React.PureComponent {
    method constructor (line 5) | constructor(props) {
    method componentDidMount (line 21) | componentDidMount() {
    method handeTextChange (line 27) | handeTextChange(e) {
    method handleVisibility (line 34) | handleVisibility(e) {
    method handleKeyDown (line 39) | handleKeyDown(e) {
    method handleEditingFinished (line 52) | handleEditingFinished(e) {
    method render (line 67) | render() {

FILE: umd/0.prod.js
  class f (line 1) | class f extends a().PureComponent{constructor(e){super(e),this.state={en...
    method constructor (line 1) | constructor(e){super(e),this.state={enabled:!0,audioRecord:null,record...
    method componentDidMount (line 1) | componentDidMount(){this.stream=null,this.mediaRecorder=null,this.audi...
    method componentWillUnmount (line 1) | componentWillUnmount(){this.startedOn=null,this.stream&&this.cleanUp()}
    method visualize (line 1) | visualize(){this.initCanvas();const e=new Uint8Array(this.analyser.fre...
    method handlePause (line 1) | handlePause(e){e.preventDefault(),this.mediaRecorder.pause(),this.medi...
    method handleResume (line 1) | handleResume(e){e.preventDefault(),this.state.enabled&&(this.startedOn...
    method handleDelete (line 1) | handleDelete(e){e.preventDefault(),this.durationMillis=0,this.startedO...
    method handleDone (line 1) | handleDone(e){e.preventDefault(),this.setState({recording:!1}),this.st...
    method initCanvas (line 1) | initCanvas(){this.canvasRef.current.width=2*this.canvasRef.current.off...
    method initMediaRecording (line 1) | initMediaRecording(e){return this.stream=e,m.some(t=>!!MediaRecorder.i...
    method getRecording (line 1) | getRecording(e){e=e||p;let t=new Blob(this.audioChunks,{type:e});retur...
    method createPreview (line 1) | createPreview(e){const t=e.getChannelData(0),i=Math.min(t.length,96),s...
    method cleanUp (line 1) | cleanUp(){this.audioInput&&this.audioInput.disconnect(),this.stream.ge...
    method render (line 1) | render(){const{formatMessage:e}=this.props.intl,t="material-icons "+(t...

FILE: umd/140.prod.js
  function s (line 1) | function s(e){var t=e.length;if(t%4>0)throw new Error("Invalid string. L...
  function l (line 1) | function l(e,t,r){for(var i,o,a=[],s=t;s<r;s+=3)i=(e[s]<<16&16711680)+(e...
  function s (line 1) | function s(e){if(e>a)throw new RangeError('The value "'+e+'" is invalid ...
  function l (line 1) | function l(e,t,n){if("number"==typeof e){if("string"==typeof t)throw new...
  function u (line 1) | function u(e,t,n){if("string"==typeof e)return function(e,t){"string"==t...
  function c (line 1) | function c(e){if("number"!=typeof e)throw new TypeError('"size" argument...
  function f (line 1) | function f(e){return c(e),s(e<0?0:0|d(e))}
  function h (line 1) | function h(e){const t=e.length<0?0:0|d(e.length),n=s(t);for(let r=0;r<t;...
  function p (line 1) | function p(e,t,n){if(t<0||e.byteLength<t)throw new RangeError('"offset" ...
  function d (line 1) | function d(e){if(e>=a)throw new RangeError("Attempt to allocate Buffer l...
  function m (line 1) | function m(e,t){if(l.isBuffer(e))return e.length;if(ArrayBuffer.isView(e...
  function y (line 1) | function y(e,t,n){let r=!1;if((void 0===t||t<0)&&(t=0),t>this.length)ret...
  function g (line 1) | function g(e,t,n){const r=e[t];e[t]=e[n],e[n]=r}
  function v (line 1) | function v(e,t,n,r,i){if(0===e.length)return-1;if("string"==typeof n?(r=...
  function b (line 1) | function b(e,t,n,r,i){let o,a=1,s=e.length,l=t.length;if(void 0!==r&&("u...
  function w (line 1) | function w(e,t,n,r){n=Number(n)||0;const i=e.length-n;r?(r=Number(r))>i&...
  function k (line 1) | function k(e,t,n,r){return X(W(t,e.length-n),e,n,r)}
  function T (line 1) | function T(e,t,n,r){return X(function(e){const t=[];for(let n=0;n<e.leng...
  function E (line 1) | function E(e,t,n,r){return X(G(t),e,n,r)}
  function C (line 1) | function C(e,t,n,r){return X(function(e,t){let n,r,i;const o=[];for(let ...
  function S (line 1) | function S(e,t,n){return 0===t&&n===e.length?r.fromByteArray(e):r.fromBy...
  function B (line 1) | function B(e,t,n){n=Math.min(e.length,n);const r=[];let i=t;for(;i<n;){c...
  function A (line 1) | function A(e,t,n){let r="";n=Math.min(e.length,n);for(let i=t;i<n;++i)r+...
  function D (line 1) | function D(e,t,n){let r="";n=Math.min(e.length,n);for(let i=t;i<n;++i)r+...
  function _ (line 1) | function _(e,t,n){const r=e.length;(!t||t<0)&&(t=0),(!n||n<0||n>r)&&(n=r...
  function x (line 1) | function x(e,t,n){const r=e.slice(t,n);let i="";for(let e=0;e<r.length-1...
  function P (line 1) | function P(e,t,n){if(e%1!=0||e<0)throw new RangeError("offset is not uin...
  function L (line 1) | function L(e,t,n,r,i,o){if(!l.isBuffer(e))throw new TypeError('"buffer" ...
  function U (line 1) | function U(e,t,n,r,i){j(t,r,i,e,n,7);let o=Number(t&BigInt(4294967295));...
  function O (line 1) | function O(e,t,n,r,i){j(t,r,i,e,n,7);let o=Number(t&BigInt(4294967295));...
  function M (line 1) | function M(e,t,n,r,i,o){if(n+r>e.length)throw new RangeError("Index out ...
  function R (line 1) | function R(e,t,n,r,o){return t=+t,n>>>=0,o||M(e,0,n,4),i.write(e,t,n,r,2...
  function N (line 1) | function N(e,t,n,r,o){return t=+t,n>>>=0,o||M(e,0,n,8),i.write(e,t,n,r,5...
  function V (line 1) | function V(e,t,n){F[e]=class extends n{constructor(){super(),Object.defi...
  function z (line 1) | function z(e){let t="",n=e.length;const r="-"===e[0]?1:0;for(;n>=r+4;n-=...
  function j (line 1) | function j(e,t,n,r,i,o){if(e>n||e<t){const r="bigint"==typeof t?"n":"";l...
  function H (line 1) | function H(e,t){if("number"!=typeof e)throw new F.ERR_INVALID_ARG_TYPE(t...
  function q (line 1) | function q(e,t,n){if(Math.floor(e)!==e)throw H(e,n),new F.ERR_OUT_OF_RAN...
  function W (line 1) | function W(e,t){let n;t=t||1/0;const r=e.length;let i=null;const o=[];fo...
  function G (line 1) | function G(e){return r.toByteArray(function(e){if((e=(e=e.split("=")[0])...
  function X (line 1) | function X(e,t,n,r){let i;for(i=0;i<r&&!(i+n>=t.length||i>=e.length);++i...
  function Y (line 1) | function Y(e,t){return e instanceof t||null!=e&&null!=e.constructor&&nul...
  function J (line 1) | function J(e){return e!=e}
  function Z (line 1) | function Z(e){return"undefined"==typeof BigInt?Q:e}
  function Q (line 1) | function Q(){throw new Error("BigInt not supported")}
  function i (line 1) | function i(e){this.buffer=e,this.offset=0}
  function o (line 1) | function o(){o.init.call(this)}
  function i (line 1) | function i(n){e.removeListener(t,o),r(n)}
  function o (line 1) | function o(){"function"==typeof e.removeListener&&e.removeListener("erro...
  function s (line 1) | function s(e){if("function"!=typeof e)throw new TypeError('The "listener...
  function l (line 1) | function l(e){return void 0===e._maxListeners?o.defaultMaxListeners:e._m...
  function u (line 1) | function u(e,t,n,r){var i,o,a,u;if(s(n),void 0===(o=e._events)?(o=e._eve...
  function c (line 1) | function c(){if(!this.fired)return this.target.removeListener(this.type,...
  function f (line 1) | function f(e,t,n){var r={fired:!1,wrapFn:void 0,target:e,type:t,listener...
  function h (line 1) | function h(e,t,n){var r=e._events;if(void 0===r)return[];var i=r[t];retu...
  function p (line 1) | function p(e){var t=this._events;if(void 0!==t){var n=t[e];if("function"...
  function d (line 1) | function d(e,t){for(var n=new Array(t),r=0;r<t;++r)n[r]=e[r];return n}
  function m (line 1) | function m(e,t,n,r){if("function"==typeof e.on)r.once?e.once(t,n):e.on(t...
  function u (line 1) | function u(s,u,w){var k=u?0:4,T=u?4:0,E=u?0:3,C=u?1:2,S=u?2:1,B=u?3:0,I=...
  function c (line 1) | function c(e){var n=this.buffer,r=this.offset;return t=null,!1!==e&&s(n)...
  function f (line 1) | function f(e){var n=this.buffer,i=this.offset;return t=r,!1!==e&&r.isBuf...
  function h (line 1) | function h(e){var n=this.buffer,r=this.offset,a=n.buffer;if(t=i,!1!==e&&...
  function p (line 1) | function p(e,t){var n=e&&e.length;return t|=0,n&&t+8<=n&&"string"!=typeo...
  function d (line 1) | function d(e,t,n,r){t|=0,r|=0;for(var i=0;i<8;i++)e[t++]=255&n[r++]}
  function m (line 1) | function m(e,t){return Array.prototype.slice.call(e,t,t+8)}
  function y (line 1) | function y(e,t,n){for(var r=t+8;r>t;)e[--r]=255&n,n/=256}
  function g (line 1) | function g(e,t,n){var r=t+8;for(n++;r>t;)e[--r]=255&-n^255,n/=256}
  function v (line 1) | function v(e,t,n){for(var r=t+8;t<r;)e[t++]=255&n,n/=256}
  function b (line 1) | function b(e,t,n){var r=t+8;for(n++;t<r;)e[t++]=255&-n^255,n/=256}
  function e (line 1) | function e(){this._buffer=new o.Buffer(0),this._tag_stack=[],this._state...
  function e (line 1) | function e(){this._schema=o.byEbmlID,this._buffers=[],this._stack=[]}
  function n (line 1) | function n(){this.constructor=e}
  function t (line 1) | function t(){var t=e.call(this)||this;return t.logGroup="",t.hasLoggingS...
  function e (line 1) | function e(){}
  function l (line 1) | function l(e,n){var r=new t.Buffer(4);return r.writeUInt32LE(n.byteLengt...
  function u (line 1) | function u(e,t){for(var n=-1,r=0;r<t.length;r++){var i=t[r];if(i.name===...
  function c (line 1) | function c(e,t){for(var n=[],r=-1,i=0;i<t.length;i++){var o=t[i];if(o.na...
  function f (line 1) | function f(e){var t=new i.default;return e.reduce((function(e,n){return ...
  function h (line 1) | function h(e,n,r){var i=r.duration,o=r.clusterPtrs,a=r.cues,s=e.slice(0)...
  function p (line 1) | function p(e,t,n,r){void 0===r&&(r=!1);for(var i=-1,o=0;o<e.length;o++){...
  function d (line 1) | function d(e){return t.Buffer.concat(e)}
  function m (line 1) | function m(e){for(var n=1;e>=Math.pow(2,8*n);n++);if(n>=7)return console...
  function y (line 1) | function y(e){for(var n=1;e>=Math.pow(2,8*n);n++);if(n>=7)return console...
  function g (line 1) | function g(e,n){var r;if(void 0===n&&(n=8),8===n)return(r=new t.Buffer(8...
  function a (line 1) | function a(e){try{l(r.next(e))}catch(e){o(e)}}
  function s (line 1) | function s(e){try{l(r.throw(e))}catch(e){o(e)}}
  function l (line 1) | function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n(...
  function s (line 1) | function s(o){return function(s){return function(o){if(n)throw new TypeE...

FILE: umd/203.prod.js
  function $ (line 1) | function $(t,d,e){var r=new n.ZP(e).getCountryCodesForCallingCode(t);ret...
  function l (line 1) | function l(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function s (line 1) | function s(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new Ar...
  function c (line 1) | function c(t,d){var e=Object.keys(t);if(Object.getOwnPropertySymbols){va...
  function f (line 1) | function f(t){for(var d=1;d<arguments.length;d++){var e=null!=arguments[...
  function h (line 1) | function h(t,d,e){return d in t?Object.defineProperty(t,d,{value:e,enume...
  function m (line 1) | function m(t,d,e,r){if(e=e?f(f({},g),e):g,r=new n.ZP(r),t.country&&"001"...
  function y (line 1) | function y(t,d,e,n,r){var i=function(t,d){for(var e,n=l(t);!(e=n()).done...
  function p (line 1) | function p(t,d,e,n){return d?n(t,d,e):t}
  function v (line 1) | function v(t,d){var e=Object.keys(t);if(Object.getOwnPropertySymbols){va...
  function b (line 1) | function b(t){for(var d=1;d<arguments.length;d++){var e=null!=arguments[...
  function C (line 1) | function C(t,d,e){return d in t?Object.defineProperty(t,d,{value:e,enume...
  function N (line 1) | function N(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.en...
  function t (line 1) | function t(d,e,r){if(function(t,d){if(!(t instanceof d))throw new TypeEr...
  function r (line 1) | function r(t){return t.replace(new RegExp("[".concat(n.uv,"]+"),"g")," "...
  function n (line 1) | function n(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function r (line 1) | function r(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new Ar...
  function a (line 1) | function a(t,d){return i(t,void 0,d)}
  function i (line 1) | function i(t,d,e){var r=e.type(d),a=r&&r.possibleLengths()||e.possibleLe...
  function $ (line 1) | function $(t,d,e,$){if(!t)return{};var o;if("+"!==t[0]){var u=(0,n.Z)(t,...
  function $ (line 1) | function $(t,d,e,$){var o=d?(0,n.Gg)(d,$):e;if(0===t.indexOf(o)){($=new ...
  function i (line 1) | function i(t,d){var e=(0,n.Z)(t,d),i=e.carrierCode,$=e.nationalNumber;if...
  function n (line 1) | function n(t,d){if(t&&d.numberingPlan.nationalPrefixForParsing()){var e=...
  function a (line 1) | function a(t,d,e){var a=e.useInternationalFormat,i=e.withNationalPrefix,...
  function a (line 1) | function a(t,d){var e=d.nationalNumber,a=d.defaultCountry,i=d.metadata;i...
  function a (line 1) | function a(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function i (line 1) | function i(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new Ar...
  function $ (line 1) | function $(t,d){var e=d.countries,i=d.defaultCountry,$=d.metadata;$=new ...
  function a (line 1) | function a(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function i (line 1) | function i(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new Ar...
  function o (line 1) | function o(t,d,e){if(d=d||{},t.country||t.countryCallingCode){(e=new n.Z...
  function u (line 1) | function u(t,d,e){return!(!(d=e.type(d))||!d.pattern())&&(!(d.possibleLe...
  function r (line 1) | function r(t){return null!=t&&t.constructor===n}
  function n (line 1) | function n(t,d){return t=t||"",new RegExp("^(?:"+d+")$").test(t)}
  function n (line 1) | function n(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function r (line 1) | function r(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new Ar...
  function i (line 1) | function i(t){return a[t]}
  function $ (line 1) | function $(t){for(var d,e="",r=n(t.split(""));!(d=r()).done;){var a=i(d....
  function i (line 1) | function i(t,d,e,r){if(d){var i=new n.ZP(r);i.selectNumberingPlan(d,e);v...
  function a (line 1) | function a(t,d,e){if(void 0===d&&(d={}),e=new n.ZP(e),d.v2){if(!t.countr...
  function i (line 1) | function i(t,d){return"IS_POSSIBLE"===(0,r.Z)(t,d)}
  function n (line 1) | function n(t,d){t=t.split("-"),d=d.split("-");for(var e=t[0].split("."),...
  function a (line 1) | function a(t){return a="function"==typeof Symbol&&"symbol"==typeof Symbo...
  function i (line 1) | function i(t,d){if(!(t instanceof d))throw new TypeError("Cannot call a ...
  function $ (line 1) | function $(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.en...
  function o (line 1) | function o(t,d,e){return d&&$(t.prototype,d),e&&$(t,e),Object.defineProp...
  function t (line 1) | function t(d){i(this,t),function(t){if(!t)throw new Error("[libphonenumb...
  function t (line 1) | function t(d,e){i(this,t),this.globalMetadataObject=e,this.metadata=d,v....
  function t (line 1) | function t(d,e){i(this,t),this._format=d,this.metadata=e}
  function t (line 1) | function t(d,e){i(this,t),this.type=d,this.metadata=e}
  function m (line 1) | function m(t,d){switch(d){case"FIXED_LINE":return t[0];case"MOBILE":retu...
  function p (line 1) | function p(t,d){if((d=new s(d)).hasCountry(t))return d.country(t).countr...
  function v (line 1) | function v(t){var d=t.version;"number"==typeof d?(this.v1=1===d,this.v2=...
  function i (line 1) | function i(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.en...
  function t (line 1) | function t(d){var e=d.onCountryChange,n=d.onCallingCodeChange;!function(...
  function o (line 1) | function o(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function u (line 1) | function u(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new Ar...
  function c (line 1) | function c(t,d){if(d<1)return"";for(var e="";d>1;)1&d&&(e+=t),d>>=1,t+=t...
  function f (line 1) | function f(t,d){return")"===t[d]&&d++,function(t){var d=[],e=0;for(;e<t....
  function y (line 1) | function y(t,d,e){var n=e.metadata,r=e.shouldTryNationalPrefixFormatting...
  function p (line 1) | function p(t,d,e){var n=e.metadata,r=e.useNationalPrefixFormattingRule,a...
  function v (line 1) | function v(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.en...
  function t (line 1) | function t(){!function(t,d){if(!(t instanceof d))throw new TypeError("Ca...
  function C (line 1) | function C(t){for(var d=[],e=0;e<t.length;){if("-"===t[e]){if(0===e||e==...
  function x (line 1) | function x(t){return 1===t.length?t[0]:t}
  function S (line 1) | function S(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function O (line 1) | function O(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new Ar...
  function w (line 1) | function w(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.en...
  function t (line 1) | function t(d){!function(t,d){if(!(t instanceof d))throw new TypeError("C...
  function E (line 1) | function E(t,d,e){if("string"==typeof d){var n=t.join("");return 0===d.i...
  function M (line 1) | function M(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function F (line 1) | function F(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new Ar...
  function k (line 1) | function k(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.en...
  function t (line 1) | function t(d){d.state;var e=d.metadata;!function(t,d){if(!(t instanceof ...
  function W (line 1) | function W(t,d){return function(t){if(Array.isArray(t))return t}(t)||fun...
  function H (line 1) | function H(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new Ar...
  function V (line 1) | function V(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.en...
  function t (line 1) | function t(d){var e=d.defaultCountry,n=d.defaultCallingCode,r=d.metadata...
  function nt (line 1) | function nt(t,d){return function(t){if(Array.isArray(t))return t}(t)||fu...
  function rt (line 1) | function rt(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new A...
  function at (line 1) | function at(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.e...
  function t (line 1) | function t(d,e){!function(t,d){if(!(t instanceof d))throw new TypeError(...
  function $t (line 1) | function $t(t){return it.call(this,t,n.Z)}
  function a (line 1) | function a(t,d,e){if(d[t])return new r.Z(t,d[t],e)}
  function i (line 1) | function i(){return(0,n.Z)(a,arguments)}
  function a (line 1) | function a(t){return a="function"==typeof Symbol&&"symbol"==typeof Symbo...
  function i (line 1) | function i(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.en...
  function $ (line 1) | function $(t){var d=s();return function(){var e,n=f(t);if(d){var r=f(thi...
  function o (line 1) | function o(t){if(void 0===t)throw new ReferenceError("this hasn't been i...
  function u (line 1) | function u(t){var d="function"==typeof Map?new Map:void 0;return u=funct...
  function l (line 1) | function l(t,d,e){return l=s()?Reflect.construct:function(t,d,e){var n=[...
  function s (line 1) | function s(){if("undefined"==typeof Reflect||!Reflect.construct)return!1...
  function c (line 1) | function c(t,d){return c=Object.setPrototypeOf||function(t,d){return t._...
  function f (line 1) | function f(t){return f=Object.setPrototypeOf?Object.getPrototypeOf:funct...
  function a (line 1) | function a(t){var d;return function(t,d){if(!(t instanceof d))throw new ...
  function y (line 1) | function y(t){var d="[  \\t,]*",e="[:\\..]?[  \\t,-]*",n="#?",r="[  \\t]...
  function S (line 1) | function S(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function O (line 1) | function O(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new Ar...
  function w (line 1) | function w(t){for(var d,e="",n=S(t.split(""));!(d=n()).done;){e+=I(d.val...
  function I (line 1) | function I(t,d){if("+"===t){if(d)return;return"+"}return(0,x.xh)(t)}
  function K (line 1) | function K(t,d){var e,n=d.extractFormattedPhoneNumber,r=function(t){var ...
  function J (line 1) | function J(t,d,e){if(d=d||{},e=new g.ZP(e),d.defaultCountry&&!e.hasCount...
  function X (line 1) | function X(t,d){var e=Object.keys(t);if(Object.getOwnPropertySymbols){va...
  function Q (line 1) | function Q(t){for(var d=1;d<arguments.length;d++){var e=null!=arguments[...
  function q (line 1) | function q(t,d,e){return d in t?Object.defineProperty(t,d,{value:e,enume...
  function tt (line 1) | function tt(t,d){var e=Object.keys(t);if(Object.getOwnPropertySymbols){v...
  function dt (line 1) | function dt(t,d,e){return d in t?Object.defineProperty(t,d,{value:e,enum...
  function et (line 1) | function et(t,d){return function(t){if(Array.isArray(t))return t}(t)||fu...
  function nt (line 1) | function nt(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new A...
  function rt (line 1) | function rt(t){var d,e,n,r=et(Array.prototype.slice.call(t),4),a=r[0],i=...
  function at (line 1) | function at(){var t=rt(arguments);return function(t,d,e){return J(t,Q(Q(...
  function it (line 1) | function it(){return(0,n.Z)(at,arguments)}
  function r (line 1) | function r(t,d){var e=Array.prototype.slice.call(d);return e.push(n.Z),t...

FILE: umd/246.prod.js
  function l (line 1) | function l(e){var t=e.length;if(t%4>0)throw new Error("Invalid string. L...
  function u (line 1) | function u(e,t,r){for(var i,o,a=[],s=t;s<r;s+=3)i=(e[s]<<16&16711680)+(e...
  function s (line 1) | function s(e){if(e>a)throw new RangeError('The value "'+e+'" is invalid ...
  function l (line 1) | function l(e,t,n){if("number"==typeof e){if("string"==typeof t)throw new...
  function u (line 1) | function u(e,t,n){if("string"==typeof e)return function(e,t){"string"==t...
  function c (line 1) | function c(e){if("number"!=typeof e)throw new TypeError('"size" argument...
  function f (line 1) | function f(e){return c(e),s(e<0?0:0|d(e))}
  function h (line 1) | function h(e){const t=e.length<0?0:0|d(e.length),n=s(t);for(let r=0;r<t;...
  function p (line 1) | function p(e,t,n){if(t<0||e.byteLength<t)throw new RangeError('"offset" ...
  function d (line 1) | function d(e){if(e>=a)throw new RangeError("Attempt to allocate Buffer l...
  function m (line 1) | function m(e,t){if(l.isBuffer(e))return e.length;if(ArrayBuffer.isView(e...
  function y (line 1) | function y(e,t,n){let r=!1;if((void 0===t||t<0)&&(t=0),t>this.length)ret...
  function g (line 1) | function g(e,t,n){const r=e[t];e[t]=e[n],e[n]=r}
  function v (line 1) | function v(e,t,n,r,i){if(0===e.length)return-1;if("string"==typeof n?(r=...
  function b (line 1) | function b(e,t,n,r,i){let o,a=1,s=e.length,l=t.length;if(void 0!==r&&("u...
  function w (line 1) | function w(e,t,n,r){n=Number(n)||0;const i=e.length-n;r?(r=Number(r))>i&...
  function k (line 1) | function k(e,t,n,r){return X(W(t,e.length-n),e,n,r)}
  function T (line 1) | function T(e,t,n,r){return X(function(e){const t=[];for(let n=0;n<e.leng...
  function E (line 1) | function E(e,t,n,r){return X(G(t),e,n,r)}
  function C (line 1) | function C(e,t,n,r){return X(function(e,t){let n,r,i;const o=[];for(let ...
  function S (line 1) | function S(e,t,n){return 0===t&&n===e.length?r.fromByteArray(e):r.fromBy...
  function B (line 1) | function B(e,t,n){n=Math.min(e.length,n);const r=[];let i=t;for(;i<n;){c...
  function A (line 1) | function A(e,t,n){let r="";n=Math.min(e.length,n);for(let i=t;i<n;++i)r+...
  function D (line 1) | function D(e,t,n){let r="";n=Math.min(e.length,n);for(let i=t;i<n;++i)r+...
  function _ (line 1) | function _(e,t,n){const r=e.length;(!t||t<0)&&(t=0),(!n||n<0||n>r)&&(n=r...
  function x (line 1) | function x(e,t,n){const r=e.slice(t,n);let i="";for(let e=0;e<r.length-1...
  function P (line 1) | function P(e,t,n){if(e%1!=0||e<0)throw new RangeError("offset is not uin...
  function L (line 1) | function L(e,t,n,r,i,o){if(!l.isBuffer(e))throw new TypeError('"buffer" ...
  function U (line 1) | function U(e,t,n,r,i){j(t,r,i,e,n,7);let o=Number(t&BigInt(4294967295));...
  function O (line 1) | function O(e,t,n,r,i){j(t,r,i,e,n,7);let o=Number(t&BigInt(4294967295));...
  function M (line 1) | function M(e,t,n,r,i,o){if(n+r>e.length)throw new RangeError("Index out ...
  function R (line 1) | function R(e,t,n,r,o){return t=+t,n>>>=0,o||M(e,0,n,4),i.write(e,t,n,r,2...
  function N (line 1) | function N(e,t,n,r,o){return t=+t,n>>>=0,o||M(e,0,n,8),i.write(e,t,n,r,5...
  function V (line 1) | function V(e,t,n){F[e]=class extends n{constructor(){super(),Object.defi...
  function z (line 1) | function z(e){let t="",n=e.length;const r="-"===e[0]?1:0;for(;n>=r+4;n-=...
  function j (line 1) | function j(e,t,n,r,i,o){if(e>n||e<t){const r="bigint"==typeof t?"n":"";l...
  function H (line 1) | function H(e,t){if("number"!=typeof e)throw new F.ERR_INVALID_ARG_TYPE(t...
  function q (line 1) | function q(e,t,n){if(Math.floor(e)!==e)throw H(e,n),new F.ERR_OUT_OF_RAN...
  function W (line 1) | function W(e,t){let n;t=t||1/0;const r=e.length;let i=null;const o=[];fo...
  function G (line 1) | function G(e){return r.toByteArray(function(e){if((e=(e=e.split("=")[0])...
  function X (line 1) | function X(e,t,n,r){let i;for(i=0;i<r&&!(i+n>=t.length||i>=e.length);++i...
  function Y (line 1) | function Y(e,t){return e instanceof t||null!=e&&null!=e.constructor&&nul...
  function J (line 1) | function J(e){return e!=e}
  function Z (line 1) | function Z(e){return"undefined"==typeof BigInt?Q:e}
  function Q (line 1) | function Q(){throw new Error("BigInt not supported")}
  function i (line 1) | function i(e){this.buffer=e,this.offset=0}
  function o (line 1) | function o(){o.init.call(this)}
  function i (line 1) | function i(n){e.removeListener(t,o),r(n)}
  function o (line 1) | function o(){"function"==typeof e.removeListener&&e.removeListener("erro...
  function s (line 1) | function s(e){if("function"!=typeof e)throw new TypeError('The "listener...
  function l (line 1) | function l(e){return void 0===e._maxListeners?o.defaultMaxListeners:e._m...
  function u (line 1) | function u(e,t,n,r){var i,o,a,u;if(s(n),void 0===(o=e._events)?(o=e._eve...
  function c (line 1) | function c(){if(!this.fired)return this.target.removeListener(this.type,...
  function f (line 1) | function f(e,t,n){var r={fired:!1,wrapFn:void 0,target:e,type:t,listener...
  function h (line 1) | function h(e,t,n){var r=e._events;if(void 0===r)return[];var i=r[t];retu...
  function p (line 1) | function p(e){var t=this._events;if(void 0!==t){var n=t[e];if("function"...
  function d (line 1) | function d(e,t){for(var n=new Array(t),r=0;r<t;++r)n[r]=e[r];return n}
  function m (line 1) | function m(e,t,n,r){if("function"==typeof e.on)r.once?e.once(t,n):e.on(t...
  function c (line 1) | function c(s,c,k){var T=c?0:4,E=c?4:0,C=c?0:3,S=c?1:2,B=c?2:1,I=c?3:0,A=...
  function f (line 1) | function f(e){var n=this.buffer,r=this.offset;return t=null,!1!==e&&s(n)...
  function h (line 1) | function h(e){var n=this.buffer,i=this.offset;return t=r,!1!==e&&r.isBuf...
  function p (line 1) | function p(e){var n=this.buffer,r=this.offset,a=n.buffer;if(t=i,!1!==e&&...
  function d (line 1) | function d(e,t){var n=e&&e.length;return t|=0,n&&t+8<=n&&"string"!=typeo...
  function m (line 1) | function m(e,t,n,r){t|=0,r|=0;for(var i=0;i<8;i++)e[t++]=255&n[r++]}
  function y (line 1) | function y(e,t){return Array.prototype.slice.call(e,t,t+8)}
  function g (line 1) | function g(e,t,n){for(var r=t+8;r>t;)e[--r]=255&n,n/=256}
  function v (line 1) | function v(e,t,n){var r=t+8;for(n++;r>t;)e[--r]=255&-n^255,n/=256}
  function b (line 1) | function b(e,t,n){for(var r=t+8;t<r;)e[t++]=255&n,n/=256}
  function w (line 1) | function w(e,t,n){var r=t+8;for(n++;t<r;)e[t++]=255&-n^255,n/=256}
  function e (line 1) | function e(){this._buffer=new o.Buffer(0),this._tag_stack=[],this._state...
  function e (line 1) | function e(){this._schema=o.byEbmlID,this._buffers=[],this._stack=[]}
  function n (line 1) | function n(){this.constructor=e}
  function t (line 1) | function t(){var t=e.call(this)||this;return t.logGroup="",t.hasLoggingS...
  function e (line 1) | function e(){}
  function l (line 1) | function l(e,n){var r=new t.Buffer(4);return r.writeUInt32LE(n.byteLengt...
  function u (line 1) | function u(e,t){for(var n=-1,r=0;r<t.length;r++){var i=t[r];if(i.name===...
  function c (line 1) | function c(e,t){for(var n=[],r=-1,i=0;i<t.length;i++){var o=t[i];if(o.na...
  function f (line 1) | function f(e){var t=new i.default;return e.reduce((function(e,n){return ...
  function h (line 1) | function h(e,n,r){var i=r.duration,o=r.clusterPtrs,a=r.cues,s=e.slice(0)...
  function p (line 1) | function p(e,t,n,r){void 0===r&&(r=!1);for(var i=-1,o=0;o<e.length;o++){...
  function d (line 1) | function d(e){return t.Buffer.concat(e)}
  function m (line 1) | function m(e){for(var n=1;e>=Math.pow(2,8*n);n++);if(n>=7)return console...
  function y (line 1) | function y(e){for(var n=1;e>=Math.pow(2,8*n);n++);if(n>=7)return console...
  function g (line 1) | function g(e,n){var r;if(void 0===n&&(n=8),8===n)return(r=new t.Buffer(8...
  function a (line 1) | function a(e){try{l(r.next(e))}catch(e){o(e)}}
  function s (line 1) | function s(e){try{l(r.throw(e))}catch(e){o(e)}}
  function l (line 1) | function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n(...
  function s (line 1) | function s(o){return function(s){return function(o){if(n)throw new TypeE...

FILE: umd/252.prod.js
  class f (line 1) | class f extends a().PureComponent{constructor(e){super(e),this.state={en...
    method constructor (line 1) | constructor(e){super(e),this.state={enabled:!0,audioRecord:null,record...
    method componentDidMount (line 1) | componentDidMount(){this.stream=null,this.mediaRecorder=null,this.audi...
    method componentWillUnmount (line 1) | componentWillUnmount(){this.startedOn=null,this.stream&&this.cleanUp()}
    method visualize (line 1) | visualize(){this.initCanvas();const e=new Uint8Array(this.analyser.fre...
    method handlePause (line 1) | handlePause(e){e.preventDefault(),this.mediaRecorder.pause(),this.medi...
    method handleResume (line 1) | handleResume(e){e.preventDefault(),this.state.enabled&&(this.startedOn...
    method handleDelete (line 1) | handleDelete(e){e.preventDefault(),this.durationMillis=0,this.startedO...
    method handleDone (line 1) | handleDone(e){e.preventDefault(),this.setState({recording:!1}),this.st...
    method initCanvas (line 1) | initCanvas(){this.canvasRef.current.width=2*this.canvasRef.current.off...
    method initMediaRecording (line 1) | initMediaRecording(e){return this.stream=e,p.some((t=>!!MediaRecorder....
    method getRecording (line 1) | getRecording(e){e=e||m;let t=new Blob(this.audioChunks,{type:e});retur...
    method createPreview (line 1) | createPreview(e){const t=e.getChannelData(0),i=Math.min(t.length,96),s...
    method cleanUp (line 1) | cleanUp(){this.audioInput&&this.audioInput.disconnect(),this.stream.ge...
    method render (line 1) | render(){const{formatMessage:e}=this.props.intl,t="material-icons "+(t...

FILE: umd/271.prod.js
  class m (line 1) | class m extends d().PureComponent{constructor(e){super(e),this.state={co...
    method constructor (line 1) | constructor(e){super(e),this.state={code:"",tel:"",email:"",sent:!1},t...
    method formatPhoneNumber (line 1) | static formatPhoneNumber(e){let a;try{a=(0,o.L)(e)}catch(e){}return a?...
    method handleEmailChange (line 1) | handleEmailChange(e){this.setState({email:e.target.value})}
    method handlePhoneChange (line 1) | handlePhoneChange(e){this.setState({tel:e})}
    method handleCodeChange (line 1) | handleCodeChange(e){this.setState({code:e.target.value.replace(/[^\d]/...
    method handleSubmit (line 1) | handleSubmit(e){e.preventDefault();const a="email"==this.props.method?...
    method render (line 1) | render(){const e=this.state.sent||!this.props.done,a=e?this.state.tel|...
  function g (line 1) | function g(e,a){return(0,p.W5)(e,a)}
  class C (line 1) | class C extends d().Component{constructor(e){super(e);const a=this.props...
    method constructor (line 1) | constructor(e){super(e);const a=this.props.tinode.getMeTopic();this.st...
    method componentDidMount (line 1) | componentDidMount(){const e=this.props.tinode.getMeTopic();e.onCredsUp...
    method componentWillUnmount (line 1) | componentWillUnmount(){this.props.tinode.getMeTopic().onCredsUpdated=n...
    method render (line 1) | render(){if(this.state.credEdit)return d().createElement(h,{method:thi...
  class u (line 1) | class u extends d().PureComponent{constructor(e){super(e),this.codeMap={...
    method constructor (line 1) | constructor(e){super(e),this.codeMap={},r.forEach(e=>{this.codeMap[e.c...
    method handleChange (line 1) | handleChange(e){const a=`+${this.state.dialCode}`;let t=(new s.Q).inpu...
    method handleFinished (line 1) | handleFinished(e){e.preventDefault();const a=`${this.state.dialCode}${...
    method handleKeyDown (line 1) | handleKeyDown(e){"Enter"===e.key&&this.handleFinished(e)}
    method showCountrySelector (line 1) | showCountrySelector(){this.props.onShowCountrySelector(this.state.coun...
    method filterNumber (line 1) | filterNumber(e){return e?e.replace(/[^-\s().\d]/g,""):e}
    method placeholderNumber (line 1) | placeholderNumber(e,a){const t=(0,c.a)(e,n.A);return t?t.formatInterna...
    method render (line 1) | render(){return d().createElement(d().Fragment,null,d().createElement(...

FILE: umd/290.prod.js
  class s (line 1) | class s extends l().PureComponent{constructor(d){super(d),this.countries...
    method constructor (line 1) | constructor(d){super(d),this.countries=[];const{formatDisplayName:e}=d...
    method componentDidMount (line 1) | componentDidMount(){this.selectedRef&&this.selectedRef.scrollIntoView(...
    method render (line 1) | render(){const d=[],e=this.props.selected||"US";return this.countries....

FILE: umd/311.prod.js
  class n (line 1) | class n extends l().PureComponent{constructor(e){super(e),this.state={te...
    method constructor (line 1) | constructor(e){super(e),this.state={tel:"",email:"",password:"",sent:!...
    method componentDidMount (line 1) | componentDidMount(){const e=c.Z.parseUrlHash(window.location.hash),d={...
    method componentDidUpdate (line 1) | componentDidUpdate(e,d){e.reqCredMethod!=this.props.reqCredMethod&&thi...
    method handleSubmit (line 1) | handleSubmit(e){if(e.preventDefault(),this.state.token)this.props.onRe...
    method handleEmailChange (line 1) | handleEmailChange(e){this.setState({email:e.target.value})}
    method handlePasswordChange (line 1) | handlePasswordChange(e){this.setState({password:e.target.value})}
    method handleCodeChange (line 1) | handleCodeChange(e){this.setState({code:e.target.value.replace(/[^\d]/...
    method handleShowCodeField (line 1) | handleShowCodeField(e){e.preventDefault(),this.setState({haveCode:!0})}
    method render (line 1) | render(){const e=!((this.state.token||this.state.code&&this.props.reqC...
  class u (line 1) | class u extends l().PureComponent{constructor(e){super(e),this.codeMap={...
    method constructor (line 1) | constructor(e){super(e),this.codeMap={},n.forEach((e=>{this.codeMap[e....
    method handleChange (line 1) | handleChange(e){const d=`+${this.state.dialCode}`;let a=(new i.R).inpu...
    method handleFinished (line 1) | handleFinished(e){e.preventDefault();const d=`${this.state.dialCode}${...
    method handleKeyDown (line 1) | handleKeyDown(e){"Enter"===e.key&&this.handleFinished(e)}
    method showCountrySelector (line 1) | showCountrySelector(){this.props.onShowCountrySelector(this.state.coun...
    method filterNumber (line 1) | filterNumber(e){return e?e.replace(/[^-\s().\d]/g,""):e}
    method placeholderNumber (line 1) | placeholderNumber(e,d){const a=(0,c.L)(e,r.Z);return a?a.formatInterna...
    method render (line 1) | render(){return l().createElement(l().Fragment,null,l().createElement(...

FILE: umd/316.prod.js
  class s (line 1) | class s extends l().PureComponent{constructor(d){super(d),this.countries...
    method constructor (line 1) | constructor(d){super(d),this.countries=[];const{formatDisplayName:e}=d...
    method componentDidMount (line 1) | componentDidMount(){this.selectedRef&&this.selectedRef.scrollIntoView(...
    method render (line 1) | render(){const d=[],e=this.props.selected||"US";return this.countries....

FILE: umd/327.prod.js
  class g (line 1) | class g extends t().PureComponent{constructor(e){super(e),this.state={lo...
    method constructor (line 1) | constructor(e){super(e),this.state={login:"",password:"",meth:"",email...
    method handleLoginChange (line 1) | handleLoginChange(e){this.setState({login:e.target.value})}
    method handlePasswordChange (line 1) | handlePasswordChange(e){this.setState({password:e})}
    method handleEmailChange (line 1) | handleEmailChange(e){this.setState({meth:"email",email:e.target.value})}
    method handlePhoneChange (line 1) | handlePhoneChange(e){this.setState({meth:"tel",tel:e})}
    method handleFnChange (line 1) | handleFnChange(e){this.setState({fn:e.target.value})}
    method handleImageChanged (line 1) | handleImageChanged(e,a){this.setState({newAvatar:a,newAvatarMime:e})}
    method handleToggleSaveToken (line 1) | handleToggleSaveToken(){h.Z.setObject("keep-logged-in",!this.state.sav...
    method handleSubmit (line 1) | handleSubmit(e){e.preventDefault(),this.props.onCreateAccount(this.sta...
    method handleAvatarCropped (line 1) | handleAvatarCropped(e,a,d,l){const t=a?URL.createObjectURL(a):null;thi...
    method handleAvatarCropCancel (line 1) | handleAvatarCropCancel(){this.setState({newAvatar:null,newAvatarMime:n...
    method uploadAvatar (line 1) | uploadAvatar(e,a,d,l){const t=e=>{let{mime:a,blob:d}=e;if(this.setStat...
    method render (line 1) | render(){if(this.state.newAvatar)return t().createElement(o.Z,{avatar:...
  class u (line 1) | class u extends t().PureComponent{constructor(e){super(e),this.codeMap={...
    method constructor (line 1) | constructor(e){super(e),this.codeMap={},r.forEach((e=>{this.codeMap[e....
    method handleChange (line 1) | handleChange(e){const a=`+${this.state.dialCode}`;let d=(new o.R).inpu...
    method handleFinished (line 1) | handleFinished(e){e.preventDefault();const a=`${this.state.dialCode}${...
    method handleKeyDown (line 1) | handleKeyDown(e){"Enter"===e.key&&this.handleFinished(e)}
    method showCountrySelector (line 1) | showCountrySelector(){this.props.onShowCountrySelector(this.state.coun...
    method filterNumber (line 1) | filterNumber(e){return e?e.replace(/[^-\s().\d]/g,""):e}
    method placeholderNumber (line 1) | placeholderNumber(e,a){const d=(0,s.L)(e,n.Z);return d?d.formatInterna...
    method render (line 1) | render(){return t().createElement(t().Fragment,null,t().createElement(...

FILE: umd/330.prod.js
  function o (line 1) | function o(t){return o="function"==typeof Symbol&&"symbol"==typeof Symbo...
  function l (line 1) | function l(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.en...
  function u (line 1) | function u(t){var e=function(t,e){if("object"!=o(t)||!t)return t;var n=t...
  function f (line 1) | function f(t,e){var n="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function c (line 1) | function c(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,r=Array(...
  function g (line 1) | function g(t,e){if(e<1)return"";for(var n="";e>1;)1&e&&(n+=t),e>>=1,t+=t...
  function d (line 1) | function d(t,e){return")"===t[e]&&e++,function(t){var e=[],n=0;for(;n<t....
  function b (line 1) | function b(t,e,n){var r=n.metadata,i=n.shouldTryNationalPrefixFormatting...
  function N (line 1) | function N(t,e,n){var r=n.metadata,i=n.useNationalPrefixFormattingRule,a...
  function C (line 1) | function C(t){return C="function"==typeof Symbol&&"symbol"==typeof Symbo...
  function S (line 1) | function S(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.en...
  function x (line 1) | function x(t){var e=function(t,e){if("object"!=C(t)||!t)return t;var n=t...
  function w (line 1) | function w(t){for(var e=[],n=0;n<t.length;){if("-"===t[n]){if(0===n||n==...
  function T (line 1) | function T(t){return 1===t.length?t[0]:t}
  function I (line 1) | function I(t,e){var n="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function k (line 1) | function k(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,r=Array(...
  function E (line 1) | function E(t){return E="function"==typeof Symbol&&"symbol"==typeof Symbo...
  function D (line 1) | function D(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.en...
  function M (line 1) | function M(t){var e=function(t,e){if("object"!=E(t)||!t)return t;var n=t...
  function R (line 1) | function R(t,e,n){if("string"==typeof e){var r=t.join("");return 0===e.i...
  function G (line 1) | function G(t){return G="function"==typeof Symbol&&"symbol"==typeof Symbo...
  function L (line 1) | function L(t,e){var n="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function W (line 1) | function W(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,r=Array(...
  function U (line 1) | function U(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.en...
  function K (line 1) | function K(t){var e=function(t,e){if("object"!=G(t)||!t)return t;var n=t...
  function z (line 1) | function z(t){return z="function"==typeof Symbol&&"symbol"==typeof Symbo...
  function tt (line 1) | function tt(t,e){return function(t){if(Array.isArray(t))return t}(t)||fu...
  function et (line 1) | function et(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,r=Array...
  function nt (line 1) | function nt(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.e...
  function rt (line 1) | function rt(t){var e=function(t,e){if("object"!=z(t)||!t)return t;var n=...
  function mt (line 1) | function mt(t){return mt="function"==typeof Symbol&&"symbol"==typeof Sym...
  function gt (line 1) | function gt(t,e){return function(t){if(Array.isArray(t))return t}(t)||fu...
  function dt (line 1) | function dt(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,r=Array...
  function yt (line 1) | function yt(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.e...
  function pt (line 1) | function pt(t){var e=function(t,e){if("object"!=mt(t)||!t)return t;var n...
  function bt (line 1) | function bt(t){return vt.call(this,t,r.A)}
  function a (line 1) | function a(t,e,n){if(e[t])return new i.A(t,e[t],n)}
  function o (line 1) | function o(){return(0,r.A)(a,arguments)}

FILE: umd/352.prod.js
  class c (line 1) | class c extends l().Component{constructor(e){super(e);const t=this.props...
    method constructor (line 1) | constructor(e){super(e);const t=this.props.tinode.getMeTopic();let a=0...
    method handlePasswordUpdate (line 1) | handlePasswordUpdate(e){this.setState({password:e}),this.props.onUpdat...
    method handleLaunchPermissionsEditor (line 1) | handleLaunchPermissionsEditor(e){this.setState({showPermissionEditorFo...
    method handleHidePermissionsEditor (line 1) | handleHidePermissionsEditor(){this.setState({showPermissionEditorFor:v...
    method handlePermissionsChanged (line 1) | handlePermissionsChanged(e){let t={};t[this.state.showPermissionEditor...
    method handleCheckboxClick (line 1) | handleCheckboxClick(e,t){this.props.onToggleIncognitoMode(t)}
    method handleDeleteAccount (line 1) | handleDeleteAccount(e){e.preventDefault();const{formatMessage:t}=this....
    method render (line 1) | render(){return l().createElement(l().Fragment,null,this.state.showPer...
    method constructor (line 1) | constructor(e){super(e),this.state={mode:(e.mode||"").replace("N","")}...
    method handleChange (line 1) | handleChange(e){let t=this.state.mode;-1==t.indexOf(e)?t+=e:t=t.replac...
    method handleSubmit (line 1) | handleSubmit(){const e=(this.state.mode||"N").split("").sort().join(""...
    method handleCancel (line 1) | handleCancel(){this.props.onCancel()}
    method render (line 1) | render(){const{formatMessage:e}=this.props.intl,t="JRWPASDO",a={J:e(d....
  class c (line 1) | class c extends l().Component{constructor(e){super(e),this.state={mode:(...
    method constructor (line 1) | constructor(e){super(e);const t=this.props.tinode.getMeTopic();let a=0...
    method handlePasswordUpdate (line 1) | handlePasswordUpdate(e){this.setState({password:e}),this.props.onUpdat...
    method handleLaunchPermissionsEditor (line 1) | handleLaunchPermissionsEditor(e){this.setState({showPermissionEditorFo...
    method handleHidePermissionsEditor (line 1) | handleHidePermissionsEditor(){this.setState({showPermissionEditorFor:v...
    method handlePermissionsChanged (line 1) | handlePermissionsChanged(e){let t={};t[this.state.showPermissionEditor...
    method handleCheckboxClick (line 1) | handleCheckboxClick(e,t){this.props.onToggleIncognitoMode(t)}
    method handleDeleteAccount (line 1) | handleDeleteAccount(e){e.preventDefault();const{formatMessage:t}=this....
    method render (line 1) | render(){return l().createElement(l().Fragment,null,this.state.showPer...
    method constructor (line 1) | constructor(e){super(e),this.state={mode:(e.mode||"").replace("N","")}...
    method handleChange (line 1) | handleChange(e){let t=this.state.mode;-1==t.indexOf(e)?t+=e:t=t.replac...
    method handleSubmit (line 1) | handleSubmit(){const e=(this.state.mode||"N").split("").sort().join(""...
    method handleCancel (line 1) | handleCancel(){this.props.onCancel()}
    method render (line 1) | render(){const{formatMessage:e}=this.props.intl,t="JRWPASDO",a={J:e(d....

FILE: umd/365.prod.js
  class u (line 1) | class u extends l().PureComponent{constructor(e){super(e),this.state={co...
    method constructor (line 1) | constructor(e){super(e),this.state={code:"",tel:"",email:"",sent:!1},t...
    method formatPhoneNumber (line 1) | static formatPhoneNumber(e){let a;try{a=(0,o.h)(e)}catch(e){}return a?...
    method handleEmailChange (line 1) | handleEmailChange(e){this.setState({email:e.target.value})}
    method handlePhoneChange (line 1) | handlePhoneChange(e){this.setState({tel:e})}
    method handleCodeChange (line 1) | handleCodeChange(e){this.setState({code:e.target.value.replace(/[^\d]/...
    method handleSubmit (line 1) | handleSubmit(e){e.preventDefault();const a="email"==this.props.method?...
    method render (line 1) | render(){const e=this.state.sent||!this.props.done,a=e?this.state.tel|...
    method constructor (line 1) | constructor(e){super(e),this.codeMap={},r.forEach((e=>{this.codeMap[e....
    method handleChange (line 1) | handleChange(e){const a=`+${this.state.dialCode}`;let t=(new o.R).inpu...
    method handleFinished (line 1) | handleFinished(e){e.preventDefault();const a=`${this.state.dialCode}${...
    method handleKeyDown (line 1) | handleKeyDown(e){"Enter"===e.key&&this.handleFinished(e)}
    method showCountrySelector (line 1) | showCountrySelector(){this.props.onShowCountrySelector(this.state.coun...
    method filterNumber (line 1) | filterNumber(e){return e?e.replace(/[^-\s().\d]/g,""):e}
    method placeholderNumber (line 1) | placeholderNumber(e,a){const t=(0,c.L)(e,n.Z);return t?t.formatInterna...
    method render (line 1) | render(){return l().createElement(l().Fragment,null,l().createElement(...
  function E (line 1) | function E(e,a){return e&&e.substring(0,a)}
  class g (line 1) | class g extends l().Component{constructor(e){super(e);const a=this.props...
    method constructor (line 1) | constructor(e){super(e);const a=this.props.tinode.getMeTopic();this.st...
    method componentDidMount (line 1) | componentDidMount(){const e=this.props.tinode.getMeTopic();e.onCredsUp...
    method componentWillUnmount (line 1) | componentWillUnmount(){this.props.tinode.getMeTopic().onCredsUpdated=n...
    method render (line 1) | render(){if(this.state.credEdit)return l().createElement(p,{method:thi...
  class u (line 1) | class u extends l().PureComponent{constructor(e){super(e),this.codeMap={...
    method constructor (line 1) | constructor(e){super(e),this.state={code:"",tel:"",email:"",sent:!1},t...
    method formatPhoneNumber (line 1) | static formatPhoneNumber(e){let a;try{a=(0,o.h)(e)}catch(e){}return a?...
    method handleEmailChange (line 1) | handleEmailChange(e){this.setState({email:e.target.value})}
    method handlePhoneChange (line 1) | handlePhoneChange(e){this.setState({tel:e})}
    method handleCodeChange (line 1) | handleCodeChange(e){this.setState({code:e.target.value.replace(/[^\d]/...
    method handleSubmit (line 1) | handleSubmit(e){e.preventDefault();const a="email"==this.props.method?...
    method render (line 1) | render(){const e=this.state.sent||!this.props.done,a=e?this.state.tel|...
    method constructor (line 1) | constructor(e){super(e),this.codeMap={},r.forEach((e=>{this.codeMap[e....
    method handleChange (line 1) | handleChange(e){const a=`+${this.state.dialCode}`;let t=(new o.R).inpu...
    method handleFinished (line 1) | handleFinished(e){e.preventDefault();const a=`${this.state.dialCode}${...
    method handleKeyDown (line 1) | handleKeyDown(e){"Enter"===e.key&&this.handleFinished(e)}
    method showCountrySelector (line 1) | showCountrySelector(){this.props.onShowCountrySelector(this.state.coun...
    method filterNumber (line 1) | filterNumber(e){return e?e.replace(/[^-\s().\d]/g,""):e}
    method placeholderNumber (line 1) | placeholderNumber(e,a){const t=(0,c.L)(e,n.Z);return t?t.formatInterna...
    method render (line 1) | render(){return l().createElement(l().Fragment,null,l().createElement(...

FILE: umd/371.prod.js
  class d (line 1) | class d extends o().PureComponent{constructor(e){super(e),this.videoRef=...
    method constructor (line 1) | constructor(e){super(e),this.videoRef=o().createRef(),this.handleSendV...
    method componentDidMount (line 1) | componentDidMount(){document.addEventListener("keydown",this.handleKey...
    method componentWillUnmount (line 1) | componentWillUnmount(){document.removeEventListener("keydown",this.han...
    method handleKeyDown (line 1) | handleKeyDown(e){this.props.onSendMessage||(e.preventDefault(),"Escape...
    method handleSendVideo (line 1) | handleSendVideo(e){this.props.onClose();const t={width:this.videoRef.c...
    method render (line 1) | render(){if(!this.props.content)return null;const e=this.props.content...

FILE: umd/372.prod.js
  class n (line 1) | class n extends l().PureComponent{constructor(e){super(e),this.state={te...
    method constructor (line 1) | constructor(e){super(e),this.state={tel:"",email:"",password:"",sent:!...
    method componentDidMount (line 1) | componentDidMount(){const e=c.c.parseUrlHash(window.location.hash),d={...
    method componentDidUpdate (line 1) | componentDidUpdate(e,d){e.reqCredMethod!=this.props.reqCredMethod&&thi...
    method handleSubmit (line 1) | handleSubmit(e){if(e.preventDefault(),this.state.token)this.props.onRe...
    method handleEmailChange (line 1) | handleEmailChange(e){this.setState({email:e.target.value})}
    method handlePasswordChange (line 1) | handlePasswordChange(e){this.setState({password:e.target.value})}
    method handleCodeChange (line 1) | handleCodeChange(e){this.setState({code:e.target.value.replace(/[^\d]/...
    method handleShowCodeField (line 1) | handleShowCodeField(e){e.preventDefault(),this.setState({haveCode:!0})}
    method render (line 1) | render(){const e=!((this.state.token||this.state.code&&this.props.reqC...
  class u (line 1) | class u extends l().PureComponent{constructor(e){super(e),this.codeMap={...
    method constructor (line 1) | constructor(e){super(e),this.codeMap={},n.forEach((e=>{this.codeMap[e....
    method handleChange (line 1) | handleChange(e){const d=`+${this.state.dialCode}`;let a=(new i.C).inpu...
    method handleFinished (line 1) | handleFinished(e){e.preventDefault();const d=`${this.state.dialCode}${...
    method handleKeyDown (line 1) | handleKeyDown(e){"Enter"===e.key&&this.handleFinished(e)}
    method showCountrySelector (line 1) | showCountrySelector(){this.props.onShowCountrySelector(this.state.coun...
    method filterNumber (line 1) | filterNumber(e){return e?e.replace(/[^-\s().\d]/g,""):e}
    method placeholderNumber (line 1) | placeholderNumber(e,d){const a=(0,c.M)(e,r.c);return a?a.formatInterna...
    method render (line 1) | render(){return l().createElement(l().Fragment,null,l().createElement(...

FILE: umd/429.prod.js
  class c (line 1) | class c extends a().PureComponent{constructor(e){super(e),this.state={qu...
    method constructor (line 1) | constructor(e){super(e),this.state={quote:null,message:"",audioRec:!1,...
    method componentDidMount (line 1) | componentDidMount(){this.messageEditArea&&(this.messageEditArea.addEve...
    method componentWillUnmount (line 1) | componentWillUnmount(){this.messageEditArea&&this.messageEditArea.remo...
    method componentDidUpdate (line 1) | componentDidUpdate(e){if(this.messageEditArea&&("all"==window.getCompu...
    method formatReply (line 1) | formatReply(){return this.props.reply?l.Drafty.format(this.props.reply...
    method handlePasteEvent (line 1) | handlePasteEvent(e){this.props.disabled||(0,o.iJ)(e,e=>{this.props.onA...
    method handleAttachImage (line 1) | handleAttachImage(e){e.target.files&&e.target.files.length>0&&this.pro...
    method handleAttachFile (line 1) | handleAttachFile(e){e.target.files&&e.target.files.length>0&&this.prop...
    method handleDropAttach (line 1) | handleDropAttach(e){e&&e.length>0&&this.props.onAttachFile(e[0])}
    method handleAttachAudio (line 1) | handleAttachAudio(e,t,s){this.setState({audioRec:!1}),this.props.onAtt...
    method handleSend (line 1) | handleSend(e){e.preventDefault();const t=this.state.message.trim();(t|...
    method handleKeyPress (line 1) | handleKeyPress(e){if(this.state.audioRec)return e.preventDefault(),voi...
    method handleMessageTyping (line 1) | handleMessageTyping(e){if(this.setState({message:e.target.value}),this...
    method handleQuoteClick (line 1) | handleQuoteClick(e){if(e.preventDefault(),e.stopPropagation(),this.pro...
    method render (line 1) | render(){const{formatMessage:e}=this.props.intl,t=this.props.disabled?...
  class d (line 1) | class d extends a().Component{constructor(e){super(e),this.state={downlo...
    method constructor (line 1) | constructor(e){super(e),this.state={downloader:null,progress:0},this.d...
    method downloadFile (line 1) | downloadFile(e,t,s){if(!e)return void this.props.onError("Invalid down...
    method handleCancel (line 1) | handleCancel(){this.props.uploading?this.props.onCancelUpload():this.s...
    method render (line 1) | render(){let e=this.props.filename||"file_attachment";e.length>36&&(e=...
  class u (line 1) | class u extends a().PureComponent{render(){const{formatMessage:e}=this.p...
    method render (line 1) | render(){const{formatMessage:e}=this.props.intl;let t;t=this.props.rec...
  function v (line 1) | function v(){return v=Object.assign?Object.assign.bind():function(e){for...
  class y (line 1) | class y extends a().PureComponent{constructor(e){super(e),this.state={pr...
    method constructor (line 1) | constructor(e){super(e),this.state={progress:0},e.uploader&&(e.uploade...
    method handleExpandImage (line 1) | handleExpandImage(e){e.preventDefault(),this.props.onExpandMedia({url:...
    method handlePlayVideo (line 1) | handlePlayVideo(e){e.preventDefault(),this.props.onExpandMedia({video:...
    method handleFormButtonClick (line 1) | handleFormButtonClick(e){e.preventDefault();const t={seq:this.props.se...
    method handleContextClick (line 1) | handleContextClick(e){e.preventDefault(),e.stopPropagation();const t=[...
    method handleProgress (line 1) | handleProgress(e){this.setState({progress:e})}
    method handleCancelUpload (line 1) | handleCancelUpload(){this.props.onCancelUpload(this.props.seq,this.pro...
    method handleQuoteClick (line 1) | handleQuoteClick(e){e.preventDefault(),e.stopPropagation();const t=thi...
    method render (line 1) | render(){const e=this.props.sequence+" "+(this.props.response?"left":"...
  class w (line 1) | class w extends a().Component{constructor(e){super(e)}render(){const e=[...
    method constructor (line 1) | constructor(e){super(e)}
    method render (line 1) | render(){const e=[],t=(this.props.subscribers||[]).length,s=Math.min(C...
  class A (line 1) | class A extends a().PureComponent{constructor(e){super(e),this.handleBut...
    method constructor (line 1) | constructor(e){super(e),this.handleButtonAction=this.handleButtonActio...
    method handleButtonAction (line 1) | handleButtonAction(e,t){e.preventDefault(),this.props.onAction(t)}
    method render (line 1) | render(){return a().createElement("div",{className:"accept-invite-pane...
  class D (line 1) | class D extends a().PureComponent{render(){const e=C.C3+" ("+l.Tinode.ge...
    method render (line 1) | render(){const e=C.C3+" ("+l.Tinode.getLibrary()+")";return a().create...
  class P (line 1) | class P extends a().PureComponent{constructor(e){super(e)}render(){let e...
    method constructor (line 1) | constructor(e){super(e)}
    method render (line 1) | render(){let e=null,t="bubble";return this.props.date&&(e=a().createEl...
  class R (line 1) | class R extends a().PureComponent{constructor(e){super(e),this.touchX=nu...
    method constructor (line 1) | constructor(e){super(e),this.touchX=null,this.touchY=null,this.touchSu...
    method componentDidMount (line 1) | componentDidMount(){this.touchSurface.current.addEventListener("touchs...
    method componentWillUnmount (line 1) | componentWillUnmount(){this.touchSurface.current.removeEventListener("...
    method getSelectedIndex (line 1) | getSelectedIndex(){return(this.props.pins||[]).length-this.props.selec...
    method handleCancel (line 1) | handleCancel(e){e.preventDefault(),this.props.onCancel(this.props.pins...
    method handleSelected (line 1) | handleSelected(e){e.preventDefault(),this.props.onSelected(this.props....
    method handleMoveNext (line 1) | handleMoveNext(e,t){t||e.preventDefault(),e.stopPropagation();const s=...
    method handleMovePrev (line 1) | handleMovePrev(e,t){t||e.preventDefault(),e.stopPropagation();const s=...
    method handleTouchEventStart (line 1) | handleTouchEventStart(e){1==e.touches.length&&(this.touchX=e.touches[0...
    method handleTouchEventEnd (line 1) | handleTouchEventEnd(e){if(null===this.touchX||1!=e.changedTouches.leng...
    method handleTouchCancel (line 1) | handleTouchCancel(){this.touchX=null}
    method render (line 1) | render(){const e=this.getSelectedIndex();let t=(this.props.messages||[...
  function O (line 1) | function O(e){if(e){const t=e.getExcessive()||"";return e.isJoiner("give...
  function Q (line 1) | function Q(e){if(e){const t=e.getMissing()||"";return e.isJoiner("want")...
  function V (line 1) | function V(e){return e==I.No||e==I.d1}
  class H (line 1) | class H extends a().Component{constructor(e){super(e),this.state=H.getDe...
    method constructor (line 1) | constructor(e){super(e),this.state=H.getDerivedStateFromProps(e,{}),th...
    method getOrCreateMessageRef (line 1) | getOrCreateMessageRef(e){if(this.chatMessageRefs[e])return this.chatMe...
    method getVisibleMessageRange (line 1) | getVisibleMessageRange(e){let t=Number.MAX_SAFE_INTEGER,s=-1,i=!1;retu...
    method componentDidMount (line 1) | componentDidMount(){this.messagesScroller&&this.messagesScroller.addEv...
    method componentWillUnmount (line 1) | componentWillUnmount(){this.messagesScroller&&this.messagesScroller.re...
    method componentDidUpdate (line 1) | componentDidUpdate(e,t){!this.messagesScroller||t.topic==this.state.to...
    method componentSetup (line 1) | componentSetup(e,t){const s=this.props.tinode?this.props.tinode.getTop...
    method getDerivedStateFromProps (line 1) | static getDerivedStateFromProps(e,t){let s={};if(e.topic)if(e.topic!=t...
    method subscribe (line 1) | subscribe(e){if(e.isSubscribed()||!this.props.ready)return;const t=thi...
    method leave (line 1) | leave(e){if(!e||!this.props.tinode.isTopicCached(e))return;const t=thi...
    method handleScrollReference (line 1) | handleScrollReference(e){e&&(e.addEventListener("scroll",this.handleSc...
    method handleScrollEvent (line 1) | handleScrollEvent(e){const t=e.target.scrollHeight-e.target.scrollTop-...
    method mountDnDEvents (line 1) | mountDnDEvents(e){e&&(e.addEventListener("dragstart",this.handleDragSt...
    method goToLatestMessage (line 1) | goToLatestMessage(){this.setState({scrollPosition:0}),this.messagesScr...
    method handleDescChange (line 1) | handleDescChange(e){l.Tinode.isSelfTopicName(this.props.topic)?this.se...
    method postReadNotification (line 1) | postReadNotification(e){if(!this.props.applicationVisible||!this.state...
    method clearNotificationQueue (line 1) | clearNotificationQueue(){this.readNotificationQueue=[],this.readNotifi...
    method handleSubsUpdated (line 1) | handleSubsUpdated(){if(this.state.topic){const e=[],t=this.props.tinod...
    method handleMessageUpdate (line 1) | handleMessageUpdate(e){if(!this.state.topic)return;const t=this.props....
    method handleAllMessagesReceived (line 1) | handleAllMessagesReceived(e){if(this.setState({fetchingMessages:!1}),!...
    method handleAuxUpdate (line 1) | handleAuxUpdate(e){const t=(e.pins||[]).slice();let s=this.state.selec...
    method handleInfoReceipt (line 1) | handleInfoReceipt(e){switch(e.what){case"kp":clearTimeout(this.keyPres...
    method handleExpandMedia (line 1) | handleExpandMedia(e){e&&(e.video?this.setState({videoPostview:e}):this...
    method handleClosePreview (line 1) | handleClosePreview(){this.state.imagePreview&&this.state.imagePreview....
    method handleFormResponse (line 1) | handleFormResponse(e,t,s){if("pub"==e)this.sendMessage(l.Drafty.attach...
    method handleContextClick (line 1) | handleContextClick(e){e.preventDefault(),e.stopPropagation(),this.prop...
    method handleShowMessageContextMenu (line 1) | handleShowMessageContextMenu(e,t){"chan"==e.userFrom&&(e.userFrom=this...
    method handleNewChatAcceptance (line 1) | handleNewChatAcceptance(e){this.props.onNewChat(this.state.topic,e)}
    method handleEnablePeer (line 1) | handleEnablePeer(e){e.preventDefault(),this.props.onChangePermissions(...
    method sendKeyPress (line 1) | sendKeyPress(e){const t=this.props.tinode.getTopic(this.state.topic);t...
    method sendMessage (line 1) | sendMessage(e,t,s){let i;if(!e&&this.props.forwardMessage)e=this.props...
    method retrySend (line 1) | retrySend(e){this.props.sendMessage(e.content,void 0,void 0,e.head).th...
    method sendFileAttachment (line 1) | sendFileAttachment(e){const t=.75*this.props.tinode.getServerParam("ma...
    method sendTheCardAttachment (line 1) | sendTheCardAttachment(e,t){return!(e.size>t)&&(e.type==l.TheCard.conte...
    method handleAttachFile (line 1) | handleAttachFile(e){const t=this.props.tinode.getServerParam("maxFileU...
    method handleCallHangup (line 1) | handleCallHangup(e,t){this.props.onVideoCallClosed(),this.setState({rt...
    method handleCallPanelToggle (line 1) | handleCallPanelToggle(){this.setState({minimizedCallPanel:!this.state....
    method sendImageAttachment (line 1) | sendImageAttachment(e,t){const s=this.state.imagePreview.mime,i=this.s...
    method sendVideoAttachment (line 1) | sendVideoAttachment(e,t,s,i){const a=i.width,n=i.height,r=.75*this.pro...
    method handleAttachImageOrVideo (line 1) | handleAttachImageOrVideo(e){const t=this.props.tinode.getServerParam("...
    method handleFileDrop (line 1) | handleFileDrop(e){if(!e||0==e.length)return;const t=e[0];t.type&&t.typ...
    method sendAudioAttachment (line 1) | sendAudioAttachment(e,t,s){fetch(e).then(e=>e.blob()).then(e=>{const i...
    method handleCancelUpload (line 1) | handleCancelUpload(e,t){const s=this.props.tinode.getTopic(this.state....
    method handlePickReply (line 1) | handlePickReply(e,t,s,i){e&&t?(t="string"==typeof t?l.Drafty.init(t):t...
    method handleEditMessage (line 1) | handleEditMessage(e,t){if(!e||!t)return void this.setState({reply:null...
    method handleCancelReply (line 1) | handleCancelReply(){this.setState({reply:null,contentToEdit:null}),thi...
    method handleQuoteClick (line 1) | handleQuoteClick(e){const t=this.getOrCreateMessageRef(e);t&&t.current...
    method handleUnpinMessage (line 1) | handleUnpinMessage(e){this.props.tinode.getTopic(this.state.topic).pin...
    method isDragEnabled (line 1) | isDragEnabled(){return this.state.isWriter&&!this.state.unconfirmed&&!...
    method handleDragStart (line 1) | handleDragStart(e){e.preventDefault(),e.stopPropagation(),e.dataTransf...
    method handleDragIn (line 1) | handleDragIn(e){e.preventDefault(),e.stopPropagation(),this.dragCounte...
    method handleDragOut (line 1) | handleDragOut(e){e.preventDefault(),e.stopPropagation(),this.dragCount...
    method handleDrag (line 1) | handleDrag(e){e.preventDefault(),e.stopPropagation()}
    method handleDrop (line 1) | handleDrop(e){e.preventDefault(),e.stopPropagation(),this.setState({dr...
    method render (line 1) | render(){const{formatMessage:e}=this.props.intl,t=this.state.rtcPanel&...

FILE: umd/440.prod.js
  class f (line 1) | class f extends a().PureComponent{constructor(e){super(e),this.state={en...
    method constructor (line 1) | constructor(e){super(e),this.state={enabled:!0,audioRecord:null,record...
    method componentDidMount (line 1) | componentDidMount(){this.stream=null,this.mediaRecorder=null,this.audi...
    method componentWillUnmount (line 1) | componentWillUnmount(){this.startedOn=null,this.stream&&this.cleanUp()}
    method visualize (line 1) | visualize(){this.initCanvas();const e=new Uint8Array(this.analyser.fre...
    method handlePause (line 1) | handlePause(e){e.preventDefault(),this.mediaRecorder.pause(),this.medi...
    method handleResume (line 1) | handleResume(e){e.preventDefault(),this.state.enabled&&(this.startedOn...
    method handleDelete (line 1) | handleDelete(e){e.preventDefault(),this.durationMillis=0,this.startedO...
    method handleDone (line 1) | handleDone(e){e.preventDefault(),this.setState({recording:!1}),this.st...
    method initCanvas (line 1) | initCanvas(){this.canvasRef.current.width=2*this.canvasRef.current.off...
    method initMediaRecording (line 1) | initMediaRecording(e){return this.stream=e,p.some((t=>!!MediaRecorder....
    method getRecording (line 1) | getRecording(e){e=e||m;let t=new Blob(this.audioChunks,{type:e});retur...
    method createPreview (line 1) | createPreview(e){const t=e.getChannelData(0),i=Math.min(t.length,96),s...
    method cleanUp (line 1) | cleanUp(){this.audioInput&&this.audioInput.disconnect(),this.stream.ge...
    method render (line 1) | render(){const{formatMessage:e}=this.props.intl,t="material-icons "+(t...

FILE: umd/472.prod.js
  class r (line 1) | class r extends l().PureComponent{constructor(e){super(e),this.handleSen...
    method constructor (line 1) | constructor(e){super(e),this.handleSendDoc=this.handleSendDoc.bind(thi...
    method componentDidMount (line 1) | componentDidMount(){document.addEventListener("keydown",this.handleKey...
    method componentWillUnmount (line 1) | componentWillUnmount(){document.removeEventListener("keydown",this.han...
    method handleKeyDown (line 1) | handleKeyDown(e){e.preventDefault(),"Escape"===e.key&&this.props.onClo...
    method handleSendDoc (line 1) | handleSendDoc(e){this.props.onClose(),this.props.onSendMessage(this.pr...
    method render (line 1) | render(){return this.props.content?l().createElement("div",{id:"image-...

FILE: umd/501.prod.js
  function o (line 1) | function o(t,d,e){var r=new n.ZP(e).getCountryCodesForCallingCode(t);ret...
  function s (line 1) | function s(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function c (line 1) | function c(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new Ar...
  function f (line 1) | function f(t,d){var e=Object.keys(t);if(Object.getOwnPropertySymbols){va...
  function h (line 1) | function h(t){for(var d=1;d<arguments.length;d++){var e=null!=arguments[...
  function g (line 1) | function g(t,d,e){return d in t?Object.defineProperty(t,d,{value:e,enume...
  function y (line 1) | function y(t,d,e,r){if(e=e?h(h({},m),e):m,r=new n.ZP(r),t.country&&"001"...
  function p (line 1) | function p(t,d,e,n,r){var i=function(t,d){for(var e,n=s(t);!(e=n()).done...
  function v (line 1) | function v(t,d,e,n){return d?n(t,d,e):t}
  function b (line 1) | function b(t,d){var e=Object.keys(t);if(Object.getOwnPropertySymbols){va...
  function C (line 1) | function C(t){for(var d=1;d<arguments.length;d++){var e=null!=arguments[...
  function N (line 1) | function N(t,d,e){return d in t?Object.defineProperty(t,d,{value:e,enume...
  function P (line 1) | function P(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.en...
  function t (line 1) | function t(d,e,r){if(function(t,d){if(!(t instanceof d))throw new TypeEr...
  function r (line 1) | function r(t,d){return function(t){if(Array.isArray(t))return t}(t)||fun...
  function a (line 1) | function a(t,d){if(t){if("string"==typeof t)return i(t,d);var e=Object.p...
  function i (line 1) | function i(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new Ar...
  function o (line 1) | function o(t){for(var d,e,i,o=function(t,d){var e="undefined"!=typeof Sy...
  function $ (line 1) | function $(t){var d=t.number,e=t.ext;if(!d)return"";if("+"!==d[0])throw ...
  function r (line 1) | function r(t){return t.replace(new RegExp("[".concat(n.uv,"]+"),"g")," "...
  function n (line 1) | function n(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function r (line 1) | function r(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new Ar...
  function a (line 1) | function a(t,d){return i(t,void 0,d)}
  function i (line 1) | function i(t,d,e){var r=e.type(d),a=r&&r.possibleLengths()||e.possibleLe...
  function i (line 1) | function i(t){var d="[  \\t,]*",e="[:\\..]?[  \\t,-]*",n="#?",i="[  \\t]...
  function o (line 1) | function o(t,d,e,o){if(!t)return{};if("+"!==t[0]){var $=(0,n.Z)(t,d,e,o)...
  function o (line 1) | function o(t,d,e,o){var $=d?(0,n.Gg)(d,o):e;if(0===t.indexOf($)){(o=new ...
  function i (line 1) | function i(t,d){var e=(0,n.Z)(t,d),i=e.carrierCode,o=e.nationalNumber;if...
  function n (line 1) | function n(t,d){if(t&&d.numberingPlan.nationalPrefixForParsing()){var e=...
  function a (line 1) | function a(t,d,e){var a=e.useInternationalFormat,i=e.withNationalPrefix,...
  function a (line 1) | function a(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function i (line 1) | function i(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new Ar...
  function $ (line 1) | function $(t,d,e){if(o&&e.isNonGeographicCallingCode(t))return"001";var ...
  function a (line 1) | function a(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function i (line 1) | function i(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new Ar...
  function $ (line 1) | function $(t,d,e){if(d=d||{},t.country){(e=new n.ZP(e)).selectNumberingP...
  function u (line 1) | function u(t,d,e){return!(!(d=e.type(d))||!d.pattern())&&(!(d.possibleLe...
  function l (line 1) | function l(t){return t.length>=n.ex&&u.test(t)}
  function s (line 1) | function s(t){return o.test(t)}
  function n (line 1) | function n(t,d){return t=t||"",new RegExp("^(?:"+d+")$").test(t)}
  function n (line 1) | function n(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function r (line 1) | function r(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new Ar...
  function i (line 1) | function i(t){return a[t]}
  function o (line 1) | function o(t){for(var d,e="",r=n(t.split(""));!(d=r()).done;){var a=i(d....
  function i (line 1) | function i(t,d,e,r){if(d){var i=new n.ZP(r);i.selectNumberingPlan(d,e);v...
  function a (line 1) | function a(t,d,e){if(void 0===d&&(d={}),e=new n.ZP(e),d.v2){if(!t.countr...
  function i (line 1) | function i(t,d){return"IS_POSSIBLE"===(0,r.Z)(t,d)}
  function n (line 1) | function n(t,d){t=t.split("-"),d=d.split("-");for(var e=t[0].split("."),...
  function r (line 1) | function r(t){return r="function"==typeof Symbol&&"symbol"==typeof Symbo...
  function a (line 1) | function a(t,d){if(!(t instanceof d))throw new TypeError("Cannot call a ...
  function i (line 1) | function i(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.en...
  function o (line 1) | function o(t,d,e){return d&&i(t.prototype,d),e&&i(t,e),Object.defineProp...
  function t (line 1) | function t(d){a(this,t),function(t){if(!t)throw new Error("[libphonenumb...
  function t (line 1) | function t(d,e){a(this,t),this.globalMetadataObject=e,this.metadata=d,C....
  function t (line 1) | function t(d,e){a(this,t),this._format=d,this.metadata=e}
  function t (line 1) | function t(d,e){a(this,t),this.type=d,this.metadata=e}
  function y (line 1) | function y(t,d){switch(d){case"FIXED_LINE":return t[0];case"MOBILE":retu...
  function b (line 1) | function b(t,d){if((d=new c(d)).hasCountry(t))return d.country(t).countr...
  function C (line 1) | function C(t){var d=t.version;"number"==typeof d?(this.v1=1===d,this.v2=...
  function i (line 1) | function i(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.en...
  function t (line 1) | function t(d){var e=d.onCountryChange,n=d.onCallingCodeChange;!function(...
  function $ (line 1) | function $(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function u (line 1) | function u(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new Ar...
  function c (line 1) | function c(t,d){if(d<1)return"";for(var e="";d>1;)1&d&&(e+=t),d>>=1,t+=t...
  function f (line 1) | function f(t,d){return")"===t[d]&&d++,function(t){var d=[],e=0;for(;e<t....
  function y (line 1) | function y(t,d,e){var n=e.metadata,r=e.shouldTryNationalPrefixFormatting...
  function p (line 1) | function p(t,d,e){var n=e.metadata,r=e.useNationalPrefixFormattingRule,a...
  function v (line 1) | function v(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.en...
  function t (line 1) | function t(){!function(t,d){if(!(t instanceof d))throw new TypeError("Ca...
  function C (line 1) | function C(t){for(var d=[],e=0;e<t.length;){if("-"===t[e]){if(0===e||e==...
  function x (line 1) | function x(t){return 1===t.length?t[0]:t}
  function S (line 1) | function S(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function w (line 1) | function w(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new Ar...
  function O (line 1) | function O(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.en...
  function t (line 1) | function t(d){!function(t,d){if(!(t instanceof d))throw new TypeError("C...
  function A (line 1) | function A(t,d,e){if("string"==typeof d){var n=t.join("");return 0===d.i...
  function F (line 1) | function F(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function M (line 1) | function M(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new Ar...
  function k (line 1) | function k(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.en...
  function t (line 1) | function t(d){d.state;var e=d.metadata;!function(t,d){if(!(t instanceof ...
  function W (line 1) | function W(t,d){return function(t){if(Array.isArray(t))return t}(t)||fun...
  function H (line 1) | function H(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new Ar...
  function V (line 1) | function V(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.en...
  function t (line 1) | function t(d){var e=d.defaultCountry,n=d.defaultCallingCode,r=d.metadata...
  function dt (line 1) | function dt(t){return dt="function"==typeof Symbol&&"symbol"==typeof Sym...
  function et (line 1) | function et(t,d){return function(t){if(Array.isArray(t))return t}(t)||fu...
  function nt (line 1) | function nt(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new A...
  function rt (line 1) | function rt(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.e...
  function t (line 1) | function t(d,e){!function(t,d){if(!(t instanceof d))throw new TypeError(...
  function it (line 1) | function it(t){return at.call(this,t,n.Z)}
  function a (line 1) | function a(t,d,e){if(d[t])return new r.Z(t,d[t],e)}
  function i (line 1) | function i(){return(0,n.Z)(a,arguments)}
  function a (line 1) | function a(t){return a="function"==typeof Symbol&&"symbol"==typeof Symbo...
  function i (line 1) | function i(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.en...
  function o (line 1) | function o(t){var d=s();return function(){var e,n=f(t);if(d){var r=f(thi...
  function $ (line 1) | function $(t){if(void 0===t)throw new ReferenceError("this hasn't been i...
  function u (line 1) | function u(t){var d="function"==typeof Map?new Map:void 0;return u=funct...
  function l (line 1) | function l(t,d,e){return l=s()?Reflect.construct:function(t,d,e){var n=[...
  function s (line 1) | function s(){if("undefined"==typeof Reflect||!Reflect.construct)return!1...
  function c (line 1) | function c(t,d){return c=Object.setPrototypeOf||function(t,d){return t._...
  function f (line 1) | function f(t){return f=Object.setPrototypeOf?Object.getPrototypeOf:funct...
  function a (line 1) | function a(t){var d;return function(t,d){if(!(t instanceof d))throw new ...
  function b (line 1) | function b(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function C (line 1) | function C(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new Ar...
  function N (line 1) | function N(t){for(var d,e="",n=b(t.split(""));!(d=n()).done;){e+=P(d.val...
  function P (line 1) | function P(t,d){if("+"===t){if(d)return;return"+"}return(0,v.xh)(t)}
  function R (line 1) | function R(t,d,e){if(d=d||{},e=new g.ZP(e),d.defaultCountry&&!e.hasCount...
  function D (line 1) | function D(t,d){var e=Object.keys(t);if(Object.getOwnPropertySymbols){va...
  function j (line 1) | function j(t){for(var d=1;d<arguments.length;d++){var e=null!=arguments[...
  function L (line 1) | function L(t,d,e){return d in t?Object.defineProperty(t,d,{value:e,enume...
  function Z (line 1) | function Z(t){return Z="function"==typeof Symbol&&"symbol"==typeof Symbo...
  function G (line 1) | function G(t,d){var e=Object.keys(t);if(Object.getOwnPropertySymbols){va...
  function B (line 1) | function B(t,d,e){return d in t?Object.defineProperty(t,d,{value:e,enume...
  function _ (line 1) | function _(t,d){return function(t){if(Array.isArray(t))return t}(t)||fun...
  function U (line 1) | function U(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new Ar...
  function K (line 1) | function K(t){var d,e,n,r=_(Array.prototype.slice.call(t),4),a=r[0],i=r[...
  function H (line 1) | function H(){var t=K(arguments);return function(t,d,e){return R(t,j(j({}...
  function V (line 1) | function V(){return(0,n.Z)(H,arguments)}
  function r (line 1) | function r(t,d){var e=Array.prototype.slice.call(d);return e.push(n.Z),t...

FILE: umd/537.prod.js
  function n (line 1) | function n(){this.constructor=e}
  function t (line 1) | function t(){var t=e.call(this)||this;return t.logGroup="",t.hasLoggingS...
  function l (line 1) | function l(e,n){var r=new t.Buffer(4);return r.writeUInt32LE(n.byteLengt...
  function u (line 1) | function u(e,t){for(var n=-1,r=0;r<t.length;r++){var i=t[r];if(i.name===...
  function c (line 1) | function c(e,t){for(var n=[],r=-1,i=0;i<t.length;i++){var o=t[i];if(o.na...
  function f (line 1) | function f(e){var t=new i.default;return e.reduce(function(e,n){return e...
  function h (line 1) | function h(e,n,r){var i=r.duration,o=r.clusterPtrs,a=r.cues,s=e.slice(0)...
  function p (line 1) | function p(e,t,n,r){void 0===r&&(r=!1);for(var i=-1,o=0;o<e.length;o++){...
  function d (line 1) | function d(e){return t.Buffer.concat(e)}
  function m (line 1) | function m(e){for(var n=1;e>=Math.pow(2,8*n);n++);if(n>=7)return console...
  function y (line 1) | function y(e){for(var n=1;e>=Math.pow(2,8*n);n++);if(n>=7)return console...
  function g (line 1) | function g(e,n){var r;if(void 0===n&&(n=8),8===n)return(r=new t.Buffer(8...
  function i (line 1) | function i(e){this.buffer=e,this.offset=0}
  function a (line 1) | function a(e){try{l(r.next(e))}catch(e){o(e)}}
  function s (line 1) | function s(e){try{l(r.throw(e))}catch(e){o(e)}}
  function l (line 1) | function l(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n(...
  function s (line 1) | function s(o){return function(s){return function(o){if(n)throw new TypeE...
  function e (line 1) | function e(){}
  function u (line 1) | function u(s,u,w){var k=u?0:4,T=u?4:0,E=u?0:3,C=u?1:2,S=u?2:1,B=u?3:0,I=...
  function c (line 1) | function c(e){var n=this.buffer,r=this.offset;return t=null,!1!==e&&s(n)...
  function f (line 1) | function f(e){var n=this.buffer,i=this.offset;return t=r,!1!==e&&r.isBuf...
  function h (line 1) | function h(e){var n=this.buffer,r=this.offset,a=n.buffer;if(t=i,!1!==e&&...
  function p (line 1) | function p(e,t){var n=e&&e.length;return t|=0,n&&t+8<=n&&"string"!=typeo...
  function d (line 1) | function d(e,t,n,r){t|=0,r|=0;for(var i=0;i<8;i++)e[t++]=255&n[r++]}
  function m (line 1) | function m(e,t){return Array.prototype.slice.call(e,t,t+8)}
  function y (line 1) | function y(e,t,n){for(var r=t+8;r>t;)e[--r]=255&n,n/=256}
  function g (line 1) | function g(e,t,n){var r=t+8;for(n++;r>t;)e[--r]=255&-n^255,n/=256}
  function v (line 1) | function v(e,t,n){for(var r=t+8;t<r;)e[t++]=255&n,n/=256}
  function b (line 1) | function b(e,t,n){var r=t+8;for(n++;t<r;)e[t++]=255&-n^255,n/=256}
  function o (line 1) | function o(){o.init.call(this)}
  function i (line 1) | function i(n){e.removeListener(t,o),r(n)}
  function o (line 1) | function o(){"function"==typeof e.removeListener&&e.removeListener("erro...
  function s (line 1) | function s(e){if("function"!=typeof e)throw new TypeError('The "listener...
  function l (line 1) | function l(e){return void 0===e._maxListeners?o.defaultMaxListeners:e._m...
  function u (line 1) | function u(e,t,n,r){var i,o,a,u;if(s(n),void 0===(o=e._events)?(o=e._eve...
  function c (line 1) | function c(){if(!this.fired)return this.target.removeListener(this.type,...
  function f (line 1) | function f(e,t,n){var r={fired:!1,wrapFn:void 0,target:e,type:t,listener...
  function h (line 1) | function h(e,t,n){var r=e._events;if(void 0===r)return[];var i=r[t];retu...
  function p (line 1) | function p(e){var t=this._events;if(void 0!==t){var n=t[e];if("function"...
  function d (line 1) | function d(e,t){for(var n=new Array(t),r=0;r<t;++r)n[r]=e[r];return n}
  function m (line 1) | function m(e,t,n,r){if("function"==typeof e.on)r.once?e.once(t,n):e.on(t...
  function s (line 1) | function s(e){var t=e.length;if(t%4>0)throw new Error("Invalid string. L...
  function l (line 1) | function l(e){return n[e>>18&63]+n[e>>12&63]+n[e>>6&63]+n[63&e]}
  function u (line 1) | function u(e,t,n){for(var r,i=[],o=t;o<n;o+=3)r=(e[o]<<16&16711680)+(e[o...
  function e (line 1) | function e(){this._schema=o.byEbmlID,this._buffers=[],this._stack=[]}
  function s (line 1) | function s(e){if(e>a)throw new RangeError('The value "'+e+'" is invalid ...
  function l (line 1) | function l(e,t,n){if("number"==typeof e){if("string"==typeof t)throw new...
  function u (line 1) | function u(e,t,n){if("string"==typeof e)return function(e,t){"string"==t...
  function c (line 1) | function c(e){if("number"!=typeof e)throw new TypeError('"size" argument...
  function f (line 1) | function f(e){return c(e),s(e<0?0:0|d(e))}
  function h (line 1) | function h(e){const t=e.length<0?0:0|d(e.length),n=s(t);for(let r=0;r<t;...
  function p (line 1) | function p(e,t,n){if(t<0||e.byteLength<t)throw new RangeError('"offset" ...
  function d (line 1) | function d(e){if(e>=a)throw new RangeError("Attempt to allocate Buffer l...
  function m (line 1) | function m(e,t){if(l.isBuffer(e))return e.length;if(ArrayBuffer.isView(e...
  function y (line 1) | function y(e,t,n){let r=!1;if((void 0===t||t<0)&&(t=0),t>this.length)ret...
  function g (line 1) | function g(e,t,n){const r=e[t];e[t]=e[n],e[n]=r}
  function v (line 1) | function v(e,t,n,r,i){if(0===e.length)return-1;if("string"==typeof n?(r=...
  function b (line 1) | function b(e,t,n,r,i){let o,a=1,s=e.length,l=t.length;if(void 0!==r&&("u...
  function w (line 1) | function w(e,t,n,r){n=Number(n)||0;const i=e.length-n;r?(r=Number(r))>i&...
  function k (line 1) | function k(e,t,n,r){return X(W(t,e.length-n),e,n,r)}
  function T (line 1) | function T(e,t,n,r){return X(function(e){const t=[];for(let n=0;n<e.leng...
  function E (line 1) | function E(e,t,n,r){return X(G(t),e,n,r)}
  function C (line 1) | function C(e,t,n,r){return X(function(e,t){let n,r,i;const o=[];for(let ...
  function S (line 1) | function S(e,t,n){return 0===t&&n===e.length?r.fromByteArray(e):r.fromBy...
  function B (line 1) | function B(e,t,n){n=Math.min(e.length,n);const r=[];let i=t;for(;i<n;){c...
  function A (line 1) | function A(e,t,n){let r="";n=Math.min(e.length,n);for(let i=t;i<n;++i)r+...
  function D (line 1) | function D(e,t,n){let r="";n=Math.min(e.length,n);for(let i=t;i<n;++i)r+...
  function _ (line 1) | function _(e,t,n){const r=e.length;(!t||t<0)&&(t=0),(!n||n<0||n>r)&&(n=r...
  function x (line 1) | function x(e,t,n){const r=e.slice(t,n);let i="";for(let e=0;e<r.length-1...
  function P (line 1) | function P(e,t,n){if(e%1!=0||e<0)throw new RangeError("offset is not uin...
  function L (line 1) | function L(e,t,n,r,i,o){if(!l.isBuffer(e))throw new TypeError('"buffer" ...
  function U (line 1) | function U(e,t,n,r,i){j(t,r,i,e,n,7);let o=Number(t&BigInt(4294967295));...
  function O (line 1) | function O(e,t,n,r,i){j(t,r,i,e,n,7);let o=Number(t&BigInt(4294967295));...
  function M (line 1) | function M(e,t,n,r,i,o){if(n+r>e.length)throw new RangeError("Index out ...
  function R (line 1) | function R(e,t,n,r,o){return t=+t,n>>>=0,o||M(e,0,n,4),i.write(e,t,n,r,2...
  function N (line 1) | function N(e,t,n,r,o){return t=+t,n>>>=0,o||M(e,0,n,8),i.write(e,t,n,r,5...
  function V (line 1) | function V(e,t,n){F[e]=class extends n{constructor(){super(),Object.defi...
  function z (line 1) | function z(e){let t="",n=e.length;const r="-"===e[0]?1:0;for(;n>=r+4;n-=...
  function j (line 1) | function j(e,t,n,r,i,o){if(e>n||e<t){const r="bigint"==typeof t?"n":"";l...
  function H (line 1) | function H(e,t){if("number"!=typeof e)throw new F.ERR_INVALID_ARG_TYPE(t...
  function q (line 1) | function q(e,t,n){if(Math.floor(e)!==e)throw H(e,n),new F.ERR_OUT_OF_RAN...
  function W (line 1) | function W(e,t){let n;t=t||1/0;const r=e.length;let i=null;const o=[];fo...
  function G (line 1) | function G(e){return r.toByteArray(function(e){if((e=(e=e.split("=")[0])...
  function X (line 1) | function X(e,t,n,r){let i;for(i=0;i<r&&!(i+n>=t.length||i>=e.length);++i...
  function Y (line 1) | function Y(e,t){return e instanceof t||null!=e&&null!=e.constructor&&nul...
  function J (line 1) | function J(e){return e!=e}
  function Z (line 1) | function Z(e){return"undefined"==typeof BigInt?Q:e}
  function Q (line 1) | function Q(){throw new Error("BigInt not supported")}
  function e (line 1) | function e(){this._buffer=new o.Buffer(0),this._tag_stack=[],this._state...

FILE: umd/688.prod.js
  function $ (line 1) | function $(t,d,e){var r=new n.cp(e).getCountryCodesForCallingCode(t);ret...
  function l (line 1) | function l(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function c (line 1) | function c(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new Ar...
  function s (line 1) | function s(t,d){var e=Object.keys(t);if(Object.getOwnPropertySymbols){va...
  function f (line 1) | function f(t){for(var d=1;d<arguments.length;d++){var e=null!=arguments[...
  function h (line 1) | function h(t,d,e){return d in t?Object.defineProperty(t,d,{value:e,enume...
  function m (line 1) | function m(t,d,e,r){if(e=e?f(f({},g),e):g,r=new n.cp(r),t.country&&"001"...
  function y (line 1) | function y(t,d,e,n,r){var i=function(t,d){for(var e,n=l(t);!(e=n()).done...
  function p (line 1) | function p(t,d,e,n){return d?n(t,d,e):t}
  function v (line 1) | function v(t,d){var e=Object.keys(t);if(Object.getOwnPropertySymbols){va...
  function b (line 1) | function b(t){for(var d=1;d<arguments.length;d++){var e=null!=arguments[...
  function C (line 1) | function C(t,d,e){return d in t?Object.defineProperty(t,d,{value:e,enume...
  function N (line 1) | function N(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.en...
  function t (line 1) | function t(d,e,r){if(function(t,d){if(!(t instanceof d))throw new TypeEr...
  function r (line 1) | function r(t){return t.replace(new RegExp("[".concat(n.e6,"]+"),"g")," "...
  function n (line 1) | function n(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function r (line 1) | function r(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new Ar...
  function a (line 1) | function a(t,d){return i(t,void 0,d)}
  function i (line 1) | function i(t,d,e){var r=e.type(d),a=r&&r.possibleLengths()||e.possibleLe...
  function $ (line 1) | function $(t,d,e,$){if(!t)return{};var o;if("+"!==t[0]){var u=(0,n.c)(t,...
  function $ (line 1) | function $(t,d,e,$){var o=d?(0,n.i0)(d,$):e;if(0===t.indexOf(o)){($=new ...
  function i (line 1) | function i(t,d){var e=(0,n.c)(t,d),i=e.carrierCode,$=e.nationalNumber;if...
  function n (line 1) | function n(t,d){if(t&&d.numberingPlan.nationalPrefixForParsing()){var e=...
  function a (line 1) | function a(t,d,e){var a=e.useInternationalFormat,i=e.withNationalPrefix,...
  function a (line 1) | function a(t,d){var e=d.nationalNumber,a=d.defaultCountry,i=d.metadata;i...
  function a (line 1) | function a(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function i (line 1) | function i(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new Ar...
  function $ (line 1) | function $(t,d){var e=d.countries,i=d.defaultCountry,$=d.metadata;$=new ...
  function a (line 1) | function a(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function i (line 1) | function i(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new Ar...
  function o (line 1) | function o(t,d,e){if(d=d||{},t.country||t.countryCallingCode){(e=new n.c...
  function u (line 1) | function u(t,d,e){return!(!(d=e.type(d))||!d.pattern())&&(!(d.possibleLe...
  function r (line 1) | function r(t){return null!=t&&t.constructor===n}
  function n (line 1) | function n(t,d){return t=t||"",new RegExp("^(?:"+d+")$").test(t)}
  function n (line 1) | function n(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function r (line 1) | function r(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new Ar...
  function i (line 1) | function i(t){return a[t]}
  function $ (line 1) | function $(t){for(var d,e="",r=n(t.split(""));!(d=r()).done;){var a=i(d....
  function i (line 1) | function i(t,d,e,r){if(d){var i=new n.cp(r);i.selectNumberingPlan(d,e);v...
  function a (line 1) | function a(t,d,e){if(void 0===d&&(d={}),e=new n.cp(e),d.v2){if(!t.countr...
  function i (line 1) | function i(t,d){return"IS_POSSIBLE"===(0,r.c)(t,d)}
  function n (line 1) | function n(t,d){t=t.split("-"),d=d.split("-");for(var e=t[0].split("."),...
  function a (line 1) | function a(t){return a="function"==typeof Symbol&&"symbol"==typeof Symbo...
  function i (line 1) | function i(t,d){if(!(t instanceof d))throw new TypeError("Cannot call a ...
  function $ (line 1) | function $(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.en...
  function o (line 1) | function o(t,d,e){return d&&$(t.prototype,d),e&&$(t,e),Object.defineProp...
  function t (line 1) | function t(d){i(this,t),function(t){if(!t)throw new Error("[libphonenumb...
  function t (line 1) | function t(d,e){i(this,t),this.globalMetadataObject=e,this.metadata=d,v....
  function t (line 1) | function t(d,e){i(this,t),this._format=d,this.metadata=e}
  function t (line 1) | function t(d,e){i(this,t),this.type=d,this.metadata=e}
  function m (line 1) | function m(t,d){switch(d){case"FIXED_LINE":return t[0];case"MOBILE":retu...
  function p (line 1) | function p(t,d){if((d=new c(d)).hasCountry(t))return d.country(t).countr...
  function v (line 1) | function v(t){var d=t.version;"number"==typeof d?(this.v1=1===d,this.v2=...
  function i (line 1) | function i(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.en...
  function t (line 1) | function t(d){var e=d.onCountryChange,n=d.onCallingCodeChange;!function(...
  function o (line 1) | function o(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function u (line 1) | function u(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new Ar...
  function s (line 1) | function s(t,d){if(d<1)return"";for(var e="";d>1;)1&d&&(e+=t),d>>=1,t+=t...
  function f (line 1) | function f(t,d){return")"===t[d]&&d++,function(t){var d=[],e=0;for(;e<t....
  function y (line 1) | function y(t,d,e){var n=e.metadata,r=e.shouldTryNationalPrefixFormatting...
  function p (line 1) | function p(t,d,e){var n=e.metadata,r=e.useNationalPrefixFormattingRule,a...
  function v (line 1) | function v(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.en...
  function t (line 1) | function t(){!function(t,d){if(!(t instanceof d))throw new TypeError("Ca...
  function C (line 1) | function C(t){for(var d=[],e=0;e<t.length;){if("-"===t[e]){if(0===e||e==...
  function x (line 1) | function x(t){return 1===t.length?t[0]:t}
  function S (line 1) | function S(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function O (line 1) | function O(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new Ar...
  function w (line 1) | function w(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.en...
  function t (line 1) | function t(d){!function(t,d){if(!(t instanceof d))throw new TypeError("C...
  function A (line 1) | function A(t,d,e){if("string"==typeof d){var n=t.join("");return 0===d.i...
  function M (line 1) | function M(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function F (line 1) | function F(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new Ar...
  function k (line 1) | function k(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.en...
  function t (line 1) | function t(d){d.state;var e=d.metadata;!function(t,d){if(!(t instanceof ...
  function H (line 1) | function H(t,d){return function(t){if(Array.isArray(t))return t}(t)||fun...
  function V (line 1) | function V(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new Ar...
  function Z (line 1) | function Z(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.en...
  function t (line 1) | function t(d){var e=d.defaultCountry,n=d.defaultCallingCode,r=d.metadata...
  function nt (line 1) | function nt(t,d){return function(t){if(Array.isArray(t))return t}(t)||fu...
  function rt (line 1) | function rt(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new A...
  function at (line 1) | function at(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.e...
  function t (line 1) | function t(d,e){!function(t,d){if(!(t instanceof d))throw new TypeError(...
  function $t (line 1) | function $t(t){return it.call(this,t,n.c)}
  function a (line 1) | function a(t,d,e){if(d[t])return new r.c(t,d[t],e)}
  function i (line 1) | function i(){return(0,n.c)(a,arguments)}
  function a (line 1) | function a(t){return a="function"==typeof Symbol&&"symbol"==typeof Symbo...
  function i (line 1) | function i(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.en...
  function $ (line 1) | function $(t){var d=c();return function(){var e,n=f(t);if(d){var r=f(thi...
  function o (line 1) | function o(t){if(void 0===t)throw new ReferenceError("this hasn't been i...
  function u (line 1) | function u(t){var d="function"==typeof Map?new Map:void 0;return u=funct...
  function l (line 1) | function l(t,d,e){return l=c()?Reflect.construct:function(t,d,e){var n=[...
  function c (line 1) | function c(){if("undefined"==typeof Reflect||!Reflect.construct)return!1...
  function s (line 1) | function s(t,d){return s=Object.setPrototypeOf||function(t,d){return t._...
  function f (line 1) | function f(t){return f=Object.setPrototypeOf?Object.getPrototypeOf:funct...
  function a (line 1) | function a(t){var d;return function(t,d){if(!(t instanceof d))throw new ...
  function y (line 1) | function y(t){var d="[  \\t,]*",e="[:\\..]?[  \\t,-]*",n="#?",r="[  \\t]...
  function S (line 1) | function S(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function O (line 1) | function O(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new Ar...
  function w (line 1) | function w(t){for(var d,e="",n=S(t.split(""));!(d=n()).done;){e+=I(d.val...
  function I (line 1) | function I(t,d,e){return"+"===t?d?void("function"==typeof e&&e("end")):"...
  function W (line 1) | function W(t,d){var e,n=d.extractFormattedPhoneNumber,r=function(t){var ...
  function J (line 1) | function J(t,d,e){if(d=d||{},e=new g.cp(e),d.defaultCountry&&!e.hasCount...
  function X (line 1) | function X(t,d){var e=Object.keys(t);if(Object.getOwnPropertySymbols){va...
  function Q (line 1) | function Q(t){for(var d=1;d<arguments.length;d++){var e=null!=arguments[...
  function q (line 1) | function q(t,d,e){return d in t?Object.defineProperty(t,d,{value:e,enume...
  function tt (line 1) | function tt(t,d){var e=Object.keys(t);if(Object.getOwnPropertySymbols){v...
  function dt (line 1) | function dt(t,d,e){return d in t?Object.defineProperty(t,d,{value:e,enum...
  function et (line 1) | function et(t,d){return function(t){if(Array.isArray(t))return t}(t)||fu...
  function nt (line 1) | function nt(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=new A...
  function rt (line 1) | function rt(t){var d,e,n,r=et(Array.prototype.slice.call(t),4),a=r[0],i=...
  function at (line 1) | function at(){var t=rt(arguments);return function(t,d,e){return J(t,Q(Q(...
  function it (line 1) | function it(){return(0,n.c)(at,arguments)}
  function r (line 1) | function r(t,d){var e=Array.prototype.slice.call(d);return e.push(n.c),t...

FILE: umd/747.prod.js
  class d (line 1) | class d extends i().Component{constructor(e){super(e),this.state={mode:(...
    method constructor (line 1) | constructor(e){super(e),this.state={mode:(e.mode||"").replace("N","")}...
    method handleChange (line 1) | handleChange(e){let t=this.state.mode;-1==t.indexOf(e)?t+=e:t=t.replac...
    method handleSubmit (line 1) | handleSubmit(){const e=(this.state.mode||"N").split("").sort().join(""...
    method handleCancel (line 1) | handleCancel(){this.props.onCancel()}
    method render (line 1) | render(){const{formatMessage:e}=this.props.intl,t="JRWPASDO",s={J:e(c....
  class u (line 1) | class u extends i().Component{constructor(e){super(e),this.state={member...
    method constructor (line 1) | constructor(e){super(e),this.state={members:e.members,index:u.indexMem...
    method indexMembers (line 1) | static indexMembers(e){let t={};return e.forEach(e=>{t[e.user]={delta:...
    method staticMembers (line 1) | static staticMembers(e,t,s){let a=[];return e.forEach(e=>{(t||e.user==...
    method selectedContacts (line 1) | static selectedContacts(e){let t=[];return e.forEach(e=>{t.push(e.user...
    method handleContactSelected (line 1) | handleContactSelected(e,t){let s=this.state.index[e];if(s){if(s.presen...
    method handleMemberRemoved (line 1) | handleMemberRemoved(e,t){const s=this.state.index[e];if(!s||!s.present...
    method handleContactFilter (line 1) | handleContactFilter(e){const{formatMessage:t}=this.props.intl,s=e?t(m....
    method doContactFiltering (line 1) | static doContactFiltering(e,t){if(e){for(let s=0;s<t.length;s++)if(t[s...
    method handleSubmit (line 1) | handleSubmit(){const e=[],t=[],s=[];Object.keys(this.state.index).forE...
    method handleCancel (line 1) | handleCancel(){this.props.onCancel()}
    method render (line 1) | render(){return i().createElement("div",{id:"group-manager"},i().creat...
  class M (line 1) | class M extends i().PureComponent{constructor(e){super(e),this.qrCodeRef...
    method constructor (line 1) | constructor(e){super(e),this.qrCodeRef=i().createRef()}
    method componentDidMount (line 1) | componentDidMount(){new(_())(this.qrCodeRef.current,{text:this.props.u...
    method render (line 1) | render(){return i().createElement("div",{className:"panel-form-column"...
  class N (line 1) | class N extends i().PureComponent{constructor(e){super(e),this.handleDel...
    method constructor (line 1) | constructor(e){super(e),this.handleDeleteTopic=this.handleDeleteTopic....
    method handleDeleteTopic (line 1) | handleDeleteTopic(e){e.preventDefault();const{formatMessage:t}=this.pr...
    method handleDeleteMessages (line 1) | handleDeleteMessages(e){e.preventDefault();const{formatMessage:t}=this...
    method handleLeave (line 1) | handleLeave(e){e.preventDefault();const{formatMessage:t}=this.props.in...
    method handleBlock (line 1) | handleBlock(e){e.preventDefault();const{formatMessage:t}=this.props.in...
    method handleReport (line 1) | handleReport(e){e.preventDefault();const{formatMessage:t}=this.props.i...
    method render (line 1) | render(){const{formatMessage:e}=this.props.intl;return i().createEleme...
  class D (line 1) | class D extends i().Component{constructor(e){super(e),this.state={topic:...
    method constructor (line 1) | constructor(e){super(e),this.state={topic:null,owner:!1,admin:!1,share...
    method propsUpdated (line 1) | propsUpdated(e){const t=this.props.tinode.getTopic(e.topic);t&&(this.o...
    method componentDidMount (line 1) | componentDidMount(){this.propsUpdated(this.props)}
    method componentDidUpdate (line 1) | componentDidUpdate(e){this.propsUpdated(e)}
    method componentWillUnmount (line 1) | componentWillUnmount(){const e=this.props.tinode.getTopic(this.props.t...
    method resetSubs (line 1) | resetSubs(e,t){const s={contactList:[]};if("p2p"==e.getType()){const a...
    method resetDesc (line 1) | resetDesc(e,t){const s=e.getDefaultAccess()||{},a=e.getAccessMode(),i=...
    method resetTags (line 1) | resetTags(e){if("grp"!=e.getType())return;const t=e.getAccessMode();t&...
    method onMetaDesc (line 1) | onMetaDesc(e){const t=this.props.tinode.getTopic(this.props.topic);t&&...
    method onSubsUpdated (line 1) | onSubsUpdated(e){const t=this.props.tinode.getTopic(this.props.topic);...
    method handleImageChanged (line 1) | handleImageChanged(e,t){this.setState({avatar:t}),this.props.onTopicDe...
    method handleMuted (line 1) | handleMuted(e,t){this.setState({muted:t}),this.props.onChangePermissio...
    method handleUnarchive (line 1) | handleUnarchive(e,t){this.props.onTopicUnArchive(this.props.topic)}
    method handlePermissionsChanged (line 1) | handlePermissionsChanged(e,t){switch(e){case"auth":this.props.onTopicD...
    method handleLaunchPermissionsEditor (line 1) | handleLaunchPermissionsEditor(e,t){const{formatMessage:s}=this.props.i...
    method handleShowQRCode (line 1) | handleShowQRCode(e){e.preventDefault(),this.props.onNavigate("qrcode")}
    method handleCopyToClipboard (line 1) | handleCopyToClipboard(e,t){e.preventDefault(),navigator.clipboard.writ...
    method handleShare (line 1) | handleShare(e){e.preventDefault();const t=new l.TheCard(this.state.ful...
    method handleShowAddMembers (line 1) | handleShowAddMembers(e){e.preventDefault(),this.props.onInitFind(),thi...
    method handleMemberUpdateRequest (line 1) | handleMemberUpdateRequest(e,t,s){this.props.onMemberUpdateRequest(this...
    method handleMemberSelected (line 1) | handleMemberSelected(e){this.setState({selectedContact:e})}
    method handleBackNavigate (line 1) | handleBackNavigate(){const e=(this.props.panel||"info").split("/");"in...
    method handleContextMenu (line 1) | handleContextMenu(e){const{formatMessage:t}=this.props.intl,s=this.pro...
    method render (line 1) | render(){const e=(this.props.panel||"info").split("/"),t=e[0];e.shift(...

FILE: umd/752.prod.js
  class u (line 1) | class u extends l().PureComponent{constructor(e){super(e),this.state={co...
    method constructor (line 1) | constructor(e){super(e),this.state={code:"",tel:"",email:"",sent:!1},t...
    method formatPhoneNumber (line 1) | static formatPhoneNumber(e){let a;try{a=(0,o._)(e)}catch(e){}return a?...
    method handleEmailChange (line 1) | handleEmailChange(e){this.setState({email:e.target.value})}
    method handlePhoneChange (line 1) | handlePhoneChange(e){this.setState({tel:e})}
    method handleCodeChange (line 1) | handleCodeChange(e){this.setState({code:e.target.value.replace(/[^\d]/...
    method handleSubmit (line 1) | handleSubmit(e){e.preventDefault();const a="email"==this.props.method?...
    method render (line 1) | render(){const e=this.state.sent||!this.props.done,a=e?this.state.tel|...
    method constructor (line 1) | constructor(e){super(e),this.codeMap={},r.forEach((e=>{this.codeMap[e....
    method handleChange (line 1) | handleChange(e){const a=`+${this.state.dialCode}`;let t=(new o.C).inpu...
    method handleFinished (line 1) | handleFinished(e){e.preventDefault();const a=`${this.state.dialCode}${...
    method handleKeyDown (line 1) | handleKeyDown(e){"Enter"===e.key&&this.handleFinished(e)}
    method showCountrySelector (line 1) | showCountrySelector(){this.props.onShowCountrySelector(this.state.coun...
    method filterNumber (line 1) | filterNumber(e){return e?e.replace(/[^-\s().\d]/g,""):e}
    method placeholderNumber (line 1) | placeholderNumber(e,a){const t=(0,c.M)(e,n.c);return t?t.formatInterna...
    method render (line 1) | render(){return l().createElement(l().Fragment,null,l().createElement(...
  function E (line 1) | function E(e,a){return e&&e.substring(0,a)}
  class g (line 1) | class g extends l().Component{constructor(e){super(e);const a=this.props...
    method constructor (line 1) | constructor(e){super(e);const a=this.props.tinode.getMeTopic();this.st...
    method componentDidMount (line 1) | componentDidMount(){const e=this.props.tinode.getMeTopic();e.onCredsUp...
    method componentWillUnmount (line 1) | componentWillUnmount(){this.props.tinode.getMeTopic().onCredsUpdated=n...
    method render (line 1) | render(){if(this.state.credEdit)return l().createElement(p,{method:thi...
  class u (line 1) | class u extends l().PureComponent{constructor(e){super(e),this.codeMap={...
    method constructor (line 1) | constructor(e){super(e),this.state={code:"",tel:"",email:"",sent:!1},t...
    method formatPhoneNumber (line 1) | static formatPhoneNumber(e){let a;try{a=(0,o._)(e)}catch(e){}return a?...
    method handleEmailChange (line 1) | handleEmailChange(e){this.setState({email:e.target.value})}
    method handlePhoneChange (line 1) | handlePhoneChange(e){this.setState({tel:e})}
    method handleCodeChange (line 1) | handleCodeChange(e){this.setState({code:e.target.value.replace(/[^\d]/...
    method handleSubmit (line 1) | handleSubmit(e){e.preventDefault();const a="email"==this.props.method?...
    method render (line 1) | render(){const e=this.state.sent||!this.props.done,a=e?this.state.tel|...
    method constructor (line 1) | constructor(e){super(e),this.codeMap={},r.forEach((e=>{this.codeMap[e....
    method handleChange (line 1) | handleChange(e){const a=`+${this.state.dialCode}`;let t=(new o.C).inpu...
    method handleFinished (line 1) | handleFinished(e){e.preventDefault();const a=`${this.state.dialCode}${...
    method handleKeyDown (line 1) | handleKeyDown(e){"Enter"===e.key&&this.handleFinished(e)}
    method showCountrySelector (line 1) | showCountrySelector(){this.props.onShowCountrySelector(this.state.coun...
    method filterNumber (line 1) | filterNumber(e){return e?e.replace(/[^-\s().\d]/g,""):e}
    method placeholderNumber (line 1) | placeholderNumber(e,a){const t=(0,c.M)(e,n.c);return t?t.formatInterna...
    method render (line 1) | render(){return l().createElement(l().Fragment,null,l().createElement(...

FILE: umd/827.prod.js
  class p (line 1) | class p extends s().PureComponent{constructor(e){super(e);const t=(0,d.M...
    method constructor (line 1) | constructor(e){super(e);const t=(0,d.MC)(this.props.wallpaper),a=(0,d....
    method handleTabClick (line 1) | handleTabClick(e){e.preventDefault(),n.A.navigateTo(n.A.addUrlParam(wi...
    method handleWallpaperSelected (line 1) | handleWallpaperSelected(e){let t,a,l;if(e)e.preventDefault(),a=this.st...
    method handleBlurChanged (line 1) | handleBlurChanged(e){e.preventDefault();const t=e.currentTarget.value;...
    method hasChanged (line 1) | hasChanged(){return this.state.selectedType!=i.S.type||this.state.wall...
    method render (line 1) | render(){return s().createElement("div",{className:"flex-column"},s()....

FILE: umd/836.prod.js
  class u (line 1) | class u extends i().PureComponent{constructor(e){super(e),this.state={lo...
    method constructor (line 1) | constructor(e){super(e),this.state={localStream:void 0,remoteStream:vo...
    method componentDidMount (line 1) | componentDidMount(){const e=this.props.tinode.getTopic(this.props.topi...
    method componentWillUnmount (line 1) | componentWillUnmount(){this.props.tinode.getTopic(this.props.topic).on...
    method handleVideoCallAccepted (line 1) | handleVideoCallAccepted(e){c.pause();const t=this.createPeerConnection...
    method onInfo (line 1) | onInfo(e){if("call"==e.what)switch(e.event){case"accept":this.handleVi...
    method emptyVideoTrack (line 1) | emptyVideoTrack(){const e=Object.assign(document.createElement("canvas...
    method start (line 1) | start(){this.state.localStream?this.props.onError(this.props.intl.form...
    method stop (line 1) | stop(){d.pause(),d.currentTime=0,c.pause(),c.currentTime=0,this.stopTr...
    method disconnectMedia (line 1) | disconnectMedia(e){e&&(e.srcObject=null,e.src="")}
    method stopTracks (line 1) | stopTracks(e){if(!e)return;let t=e.getTracks();t&&t.forEach(e=>{e.stop...
    method handleDataChannelError (line 1) | handleDataChannelError(e){console.error("data channel error",e)}
    method handleDataChannelMessage (line 1) | handleDataChannelMessage(e){switch(e.data){case m:this.setState({remot...
    method handleDataChannelOpen (line 1) | handleDataChannelOpen(e){this.state.audioOnly||e.target.send(g)}
    method handleDataChannelClose (line 1) | handleDataChannelClose(e){console.info("close data channel:",e)}
    method handleDataChannelEvent (line 1) | handleDataChannelEvent(e){console.info("data channel event:",e);const ...
    method createPeerConnection (line 1) | createPeerConnection(e){const t=this.props.tinode.getServerParam("iceS...
    method handleVideoAnswerMsg (line 1) | handleVideoAnswerMsg(e){const t=new RTCSessionDescription(e.payload);t...
    method reportError (line 1) | reportError(e){this.props.onError(e.message,"err")}
    method canSendOffer (line 1) | canSendOffer(){return this.isOutgoingCall||this.state.callInitialSetup...
    method handleNegotiationNeededEvent (line 1) | handleNegotiationNeededEvent(e){const t=e.target;this.canSendOffer()&&...
    method handleIceCandidateErrorEvent (line 1) | handleIceCandidateErrorEvent(e){console.warn("ICE candidate error:",e)}
    method handleICECandidateEvent (line 1) | handleICECandidateEvent(e){e.candidate&&this.props.onIceCandidate(this...
    method handleNewICECandidateMsg (line 1) | handleNewICECandidateMsg(e){const t=new RTCIceCandidate(e.payload);thi...
    method drainRemoteIceCandidatesCache (line 1) | drainRemoteIceCandidatesCache(){this.remoteIceCandidatesCache.forEach(...
    method handleICEConnectionStateChangeEvent (line 1) | handleICEConnectionStateChangeEvent(e){switch(e.target.iceConnectionSt...
    method handleSignalingStateChangeEvent (line 1) | handleSignalingStateChangeEvent(e){"closed"==e.target.signalingState&&...
    method handleICEGatheringStateChangeEvent (line 1) | handleICEGatheringStateChangeEvent(e){}
    method handleTrackEvent (line 1) | handleTrackEvent(e){this.remoteRef.current.srcObject=e.streams[0],this...
    method handleGetUserMediaError (line 1) | handleGetUserMediaError(e){switch(console.error("Error opening camera ...
    method handleVideoOfferMsg (line 1) | handleVideoOfferMsg(e){let t=null;const a=this.state.pc?this.state.pc:...
    method handleRemoteHangup (line 1) | handleRemoteHangup(){this.state.waitingForPeer?(this.setState({waiting...
    method handleCloseClick (line 1) | handleCloseClick(){this.stop(),this.props.onHangup(this.props.topic,th...
    method muteVideo (line 1) | muteVideo(){if(!this.state.pc||!this.state.dataChannel)return;const e=...
    method unmuteVideo (line 1) | unmuteVideo(){this.state.pc&&this.state.dataChannel&&navigator.mediaDe...
    method handleToggleCameraClick (line 1) | handleToggleCameraClick(){if(this.state.videoToggleInProgress)return;c...
    method handleToggleMicClick (line 1) | handleToggleMicClick(){const e=this.state.localStream.getAudioTracks()...
    method render (line 1) | render(){const e=this.state.localStream&&this.state.localStream.getAud...

FILE: umd/868.prod.js
  class g (line 1) | class g extends t().PureComponent{constructor(e){super(e),this.state={lo...
    method constructor (line 1) | constructor(e){super(e),this.state={login:"",password:"",meth:"",email...
    method handleLoginChange (line 1) | handleLoginChange(e){this.setState({login:e.target.value})}
    method handlePasswordChange (line 1) | handlePasswordChange(e){this.setState({password:e})}
    method handleEmailChange (line 1) | handleEmailChange(e){this.setState({meth:"email",email:e.target.value})}
    method handlePhoneChange (line 1) | handlePhoneChange(e){this.setState({meth:"tel",tel:e})}
    method handleFnChange (line 1) | handleFnChange(e){this.setState({fn:e.target.value})}
    method handleImageChanged (line 1) | handleImageChanged(e,a){this.setState({newAvatar:a,newAvatarMime:e})}
    method handleToggleSaveToken (line 1) | handleToggleSaveToken(){h.c.setObject("keep-logged-in",!this.state.sav...
    method handleSubmit (line 1) | handleSubmit(e){e.preventDefault(),this.props.onCreateAccount(this.sta...
    method handleAvatarCropped (line 1) | handleAvatarCropped(e,a,d,l){const t=a?URL.createObjectURL(a):null;thi...
    method handleAvatarCropCancel (line 1) | handleAvatarCropCancel(){this.setState({newAvatar:null,newAvatarMime:n...
    method uploadAvatar (line 1) | uploadAvatar(e,a,d,l){const t=e=>{let{mime:a,blob:d}=e;if(this.setStat...
    method render (line 1) | render(){if(this.state.newAvatar)return t().createElement(o.c,{avatar:...
  class u (line 1) | class u extends t().PureComponent{constructor(e){super(e),this.codeMap={...
    method constructor (line 1) | constructor(e){super(e),this.codeMap={},r.forEach((e=>{this.codeMap[e....
    method handleChange (line 1) | handleChange(e){const a=`+${this.state.dialCode}`;let d=(new o.C).inpu...
    method handleFinished (line 1) | handleFinished(e){e.preventDefault();const a=`${this.state.dialCode}${...
    method handleKeyDown (line 1) | handleKeyDown(e){"Enter"===e.key&&this.handleFinished(e)}
    method showCountrySelector (line 1) | showCountrySelector(){this.props.onShowCountrySelector(this.state.coun...
    method filterNumber (line 1) | filterNumber(e){return e?e.replace(/[^-\s().\d]/g,""):e}
    method placeholderNumber (line 1) | placeholderNumber(e,a){const d=(0,s.M)(e,n.c);return d?d.formatInterna...
    method render (line 1) | render(){return t().createElement(t().Fragment,null,t().createElement(...

FILE: umd/884.prod.js
  class s (line 1) | class s extends l().PureComponent{constructor(d){super(d),this.countries...
    method constructor (line 1) | constructor(d){super(d),this.countries=[];const{formatDisplayName:e}=d...
    method componentDidMount (line 1) | componentDidMount(){this.selectedRef&&this.selectedRef.scrollIntoView(...
    method render (line 1) | render(){const d=[],e=this.props.selected||"US";return this.countries....

FILE: umd/889.prod.js
  class d (line 1) | class d extends i().PureComponent{constructor(e){super(e),this.state={wi...
    method constructor (line 1) | constructor(e){super(e),this.state={width:0,height:0},this.handleSendI...
    method componentDidMount (line 1) | componentDidMount(){document.addEventListener("keydown",this.handleKey...
    method componentWillUnmount (line 1) | componentWillUnmount(){document.removeEventListener("keydown",this.han...
    method handleKeyDown (line 1) | handleKeyDown(e){this.props.onSendMessage||(e.preventDefault(),"Escape...
    method assignWidth (line 1) | assignWidth(e){if(e&&!this.state.width){const t=e.getBoundingClientRec...
    method handleSendImage (line 1) | handleSendImage(e){this.props.onClose(),this.props.onSendMessage(e,thi...
    method render (line 1) | render(){if(!this.props.content)return null;const e=(0,r.ae)(this.prop...

FILE: umd/892.prod.js
  function i (line 1) | function i(d,$,t){var e=new n.Ay(t).getCountryCodesForCallingCode(d);ret...
  function s (line 1) | function s(d,$,t,e){if(t=t?function(){for(var d=1,$=arguments.length,t=n...
  function y (line 1) | function y(d,$,t,n,e){var o,i,a=(o=n.formats(),i=d,function(d,$){for(var...
  function h (line 1) | function h(d,$,t,n){return $?n(d,$,t):d}
  function m (line 1) | function m(d){return m="function"==typeof Symbol&&"symbol"==typeof Symbo...
  function g (line 1) | function g(d,$){var t=Object.keys(d);if(Object.getOwnPropertySymbols){va...
  function v (line 1) | function v(d){for(var $=1;$<arguments.length;$++){var t=null!=arguments[...
  function b (line 1) | function b(d,$,t){return($=C($))in d?Object.defineProperty(d,$,{value:t,...
  function p (line 1) | function p(d,$){for(var t=0;t<$.length;t++){var n=$[t];n.enumerable=n.en...
  function C (line 1) | function C(d){var $=function(d,$){if("object"!=m(d)||!d)return d;var t=d...
  function i (line 1) | function i(d,$,t,i,a){var u=$||t?(0,n.Ko)($||t,a):i;if(0===d.indexOf(u))...
  function e (line 1) | function e(d){return null!=d&&d.constructor===n}
  function e (line 1) | function e(d){return d.replace(new RegExp("[".concat(n.uD,"]+"),"g")," "...
  function n (line 1) | function n(d,$){if(d&&$.numberingPlan.nationalPrefixForParsing()){var t=...
  function r (line 1) | function r(d,$,t){var r=t.useInternationalFormat,o=t.withNationalPrefix,...
  function e (line 1) | function e(d,$){var t="undefined"!=typeof Symbol&&d[Symbol.iterator]||d[...
  function r (line 1) | function r(d,$){(null==$||$>d.length)&&($=d.length);for(var t=0,n=Array(...
  function o (line 1) | function o(d,$,t){return i(d,$,void 0,t)}
  function i (line 1) | function i(d,$,t,r){$&&(r=new n.Ay(r.metadata)).selectNumberingPlan($);v...
  function r (line 1) | function r(d,$,t){if(void 0===$&&($={}),t=new n.Ay(t),$.v2){if(!d.countr...
  function o (line 1) | function o(d,$,t){return"IS_POSSIBLE"===(0,e.A)(d,$,t)}
  function n (line 1) | function n(d,$){d=d.split("-"),$=$.split("-");for(var t=d[0].split("."),...
  function r (line 1) | function r(d){return r="function"==typeof Symbol&&"symbol"==typeof Symbo...
  function o (line 1) | function o(d,$){if(!(d instanceof $))throw new TypeError("Cannot call a ...
  function i (line 1) | function i(d,$){for(var t=0;t<$.length;t++){var n=$[t];n.enumerable=n.en...
  function a (line 1) | function a(d,$,t){return $&&i(d.prototype,$),t&&i(d,t),Object.defineProp...
  function u (line 1) | function u(d){var $=function(d,$){if("object"!=r(d)||!d)return d;var t=d...
  function g (line 1) | function g(d,$){switch($){case"FIXED_LINE":return d[0];case"MOBILE":retu...
  function v (line 1) | function v(d){if(!d)throw new Error("[libphonenumber-js] `metadata` argu...
  function p (line 1) | function p(d,$){if(($=new f($)).hasCountry(d))return $.selectNumberingPl...
  function C (line 1) | function C(d){var $=d.version;"number"==typeof $?(this.v1=1===$,this.v2=...
  function n (line 1) | function n(d,$){var t="undefined"!=typeof Symbol&&d[Symbol.iterator]||d[...
  function e (line 1) | function e(d,$){(null==$||$>d.length)&&($=d.length);for(var t=0,n=Array(...
  function o (line 1) | function o(d){return r[d]}
  function i (line 1) | function i(d){for(var $,t="",e=n(d.split(""));!($=e()).done;){var r=o($....
  function n (line 1) | function n(d,$){return d=d||"",new RegExp("^(?:"+$+")$").test(d)}
  function i (line 1) | function i(d,$,t){var i=(0,n.A)(d,t),a=i.carrierCode,u=i.nationalNumber;...
  function e (line 1) | function e(d,$){var t=Array.prototype.slice.call($);return t.push(n.A),d...
  function r (line 1) | function r(d,$){var t="undefined"!=typeof Symbol&&d[Symbol.iterator]||d[...
  function o (line 1) | function o(d,$){(null==$||$>d.length)&&($=d.length);for(var t=0,n=Array(...
  function i (line 1) | function i(d,$){var t=$.countries,o=$.metadata;o=new n.Ay(o);for(var i,a...
  function o (line 1) | function o(d,$,t,e){if($){var o=new n.Ay(e);o.selectNumberingPlan($,t);v...
  function r (line 1) | function r(d){return r="function"==typeof Symbol&&"symbol"==typeof Symbo...
  function o (line 1) | function o(d,$){for(var t=0;t<$.length;t++){var n=$[t];n.enumerable=n.en...
  function i (line 1) | function i(d){var $=function(d,$){if("object"!=r(d)||!d)return d;var t=d...
  function a (line 1) | function a(d,$,t){return $=f($),function(d,$){if($&&("object"==r($)||"fu...
  function u (line 1) | function u(d){var $="function"==typeof Map?new Map:void 0;return u=funct...
  function l (line 1) | function l(){try{var d=!Boolean.prototype.valueOf.call(Reflect.construct...
  function c (line 1) | function c(d,$){return c=Object.setPrototypeOf?Object.setPrototypeOf.bin...
  function f (line 1) | function f(d){return f=Object.setPrototypeOf?Object.getPrototypeOf.bind(...
  function $ (line 1) | function $(d){var t;return function(d,$){if(!(d instanceof $))throw new ...
  function m (line 1) | function m(d){var $="[  \\t,]*",t="[:\\..]?[  \\t,-]*",n="#?",e="[  \\t]...
  function O (line 1) | function O(d,$){var t="undefined"!=typeof Symbol&&d[Symbol.iterator]||d[...
  function N (line 1) | function N(d,$){(null==$||$>d.length)&&($=d.length);for(var t=0,n=Array(...
  function w (line 1) | function w(d){for(var $,t="",n=O(d.split(""));!($=n()).done;){t+=E($.val...
  function E (line 1) | function E(d,$,t){return"+"===d?$?void("function"==typeof t&&t("end")):"...
  function K (line 1) | function K(d,$){var t,n=$.extractFormattedPhoneNumber,e=function(d){var ...
  function Y (line 1) | function Y(d,$,t){if($=$||{},t=new y.Ay(t),$.defaultCountry&&!t.hasCount...
  function J (line 1) | function J(d){return J="function"==typeof Symbol&&"symbol"==typeof Symbo...
  function X (line 1) | function X(d,$){var t=Object.keys(d);if(Object.getOwnPropertySymbols){va...
  function Q (line 1) | function Q(d){for(var $=1;$<arguments.length;$++){var t=null!=arguments[...
  function q (line 1) | function q(d,$,t){return($=function(d){var $=function(d,$){if("object"!=...
  function dd (line 1) | function dd(d){return dd="function"==typeof Symbol&&"symbol"==typeof Sym...
  function $d (line 1) | function $d(d,$){var t=Object.keys(d);if(Object.getOwnPropertySymbols){v...
  function td (line 1) | function td(d,$,t){return($=function(d){var $=function(d,$){if("object"!...
  function nd (line 1) | function nd(d,$){return function(d){if(Array.isArray(d))return d}(d)||fu...
  function ed (line 1) | function ed(d,$){(null==$||$>d.length)&&($=d.length);for(var t=0,n=Array...
  function rd (line 1) | function rd(d){var $,t,n,e=nd(Array.prototype.slice.call(d),4),r=e[0],o=...
  function od (line 1) | function od(){var d=rd(arguments);return function(d,$,t){return Y(d,Q(Q(...
  function id (line 1) | function id(){return(0,n.A)(od,arguments)}
  function r (line 1) | function r(d,$){var t=$.nationalNumber,r=$.metadata;if(e&&r.isNonGeograp...
  function r (line 1) | function r(d,$){var t="undefined"!=typeof Symbol&&d[Symbol.iterator]||d[...
  function o (line 1) | function o(d,$){(null==$||$>d.length)&&($=d.length);for(var t=0,n=Array(...
  function a (line 1) | function a(d,$,t){if($=$||{},d.country||d.countryCallingCode){(t=new n.A...
  function u (line 1) | function u(d,$,t){return!(!($=t.type($))||!$.pattern())&&(!($.possibleLe...
  function i (line 1) | function i(d,$,t,i,a){if(!d)return{};var u;if("+"!==d[0]){var l=(0,n.A)(...

FILE: umd/942.prod.js
  class p (line 1) | class p extends l().PureComponent{constructor(e){super(e),this.state={co...
    method constructor (line 1) | constructor(e){super(e),this.state={content:e.content.object},e.conten...
    method componentDidMount (line 1) | componentDidMount(){document.addEventListener("keydown",this.handleKey...
    method componentWillUnmount (line 1) | componentWillUnmount(){document.removeEventListener("keydown",this.han...
    method handleKeyDown (line 1) | handleKeyDown(e){e.preventDefault(),"Escape"===e.key&&this.props.onClo...
    method handleSendCard (line 1) | handleSendCard(){this.props.onClose(),this.props.onSendMessage(this.pr...
    method render (line 1) | render(){const e=this.state.content,t=d.TheCard.getFn(e),a=d.TheCard.g...

FILE: umd/961.prod.js
  function o (line 1) | function o(t,d,e){var r=new n.Ay(e).getCountryCodesForCallingCode(t);ret...
  function f (line 1) | function f(t,d,e,r){if(e=e?function(){for(var t=1,d=arguments.length,e=n...
  function h (line 1) | function h(t,d,e,n,r){var a,o,$=(a=n.formats(),o=t,function(t,d){for(var...
  function m (line 1) | function m(t,d,e,n){return d?n(t,d,e):t}
  function g (line 1) | function g(t){return g="function"==typeof Symbol&&"symbol"==typeof Symbo...
  function y (line 1) | function y(t,d){var e=Object.keys(t);if(Object.getOwnPropertySymbols){va...
  function v (line 1) | function v(t){for(var d=1;d<arguments.length;d++){var e=null!=arguments[...
  function b (line 1) | function b(t,d,e){return(d=C(d))in t?Object.defineProperty(t,d,{value:e,...
  function p (line 1) | function p(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.en...
  function C (line 1) | function C(t){var d=function(t,d){if("object"!=g(t)||!t)return t;var e=t...
  function o (line 1) | function o(t,d,e,o,$){var u=d||e?(0,n.Ko)(d||e,$):o;if(0===t.indexOf(u))...
  function r (line 1) | function r(t){return null!=t&&t.constructor===n}
  function r (line 1) | function r(t){return t.replace(new RegExp("[".concat(n.uD,"]+"),"g")," "...
  function n (line 1) | function n(t,d){if(t&&d.numberingPlan.nationalPrefixForParsing()){var e=...
  function i (line 1) | function i(t,d,e){var i=e.useInternationalFormat,a=e.withNationalPrefix,...
  function r (line 1) | function r(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function i (line 1) | function i(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=Array(...
  function a (line 1) | function a(t,d,e){return o(t,d,void 0,e)}
  function o (line 1) | function o(t,d,e,i){d&&(i=new n.Ay(i.metadata)).selectNumberingPlan(d);v...
  function i (line 1) | function i(t,d,e){if(void 0===d&&(d={}),e=new n.Ay(e),d.v2){if(!t.countr...
  function a (line 1) | function a(t,d,e){return"IS_POSSIBLE"===(0,r.A)(t,d,e)}
  function n (line 1) | function n(t,d){t=t.split("-"),d=d.split("-");for(var e=t[0].split("."),...
  function i (line 1) | function i(t){return i="function"==typeof Symbol&&"symbol"==typeof Symbo...
  function a (line 1) | function a(t,d){if(!(t instanceof d))throw new TypeError("Cannot call a ...
  function o (line 1) | function o(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.en...
  function $ (line 1) | function $(t,d,e){return d&&o(t.prototype,d),e&&o(t,e),Object.defineProp...
  function u (line 1) | function u(t){var d=function(t,d){if("object"!=i(t)||!t)return t;var e=t...
  function y (line 1) | function y(t,d){switch(d){case"FIXED_LINE":return t[0];case"MOBILE":retu...
  function v (line 1) | function v(t){if(!t)throw new Error("[libphonenumber-js] `metadata` argu...
  function p (line 1) | function p(t,d){if((d=new s(d)).hasCountry(t))return d.selectNumberingPl...
  function C (line 1) | function C(t){var d=t.version;"number"==typeof d?(this.v1=1===d,this.v2=...
  function n (line 1) | function n(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function r (line 1) | function r(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=Array(...
  function a (line 1) | function a(t){return i[t]}
  function o (line 1) | function o(t){for(var d,e="",r=n(t.split(""));!(d=r()).done;){var i=a(d....
  function n (line 1) | function n(t,d){return t=t||"",new RegExp("^(?:"+d+")$").test(t)}
  function o (line 1) | function o(t,d,e){var o=(0,n.A)(t,e),$=o.carrierCode,u=o.nationalNumber;...
  function a (line 1) | function a(t){return a="function"==typeof Symbol&&"symbol"==typeof Symbo...
  function o (line 1) | function o(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.en...
  function $ (line 1) | function $(t){var d=function(t,d){if("object"!=a(t)||!t)return t;var e=t...
  function l (line 1) | function l(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function c (line 1) | function c(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=Array(...
  function h (line 1) | function h(t,d){if(d<1)return"";for(var e="";d>1;)1&d&&(e+=t),d>>=1,t+=t...
  function m (line 1) | function m(t,d){return")"===t[d]&&d++,function(t){var d=[],e=0;for(;e<t....
  function b (line 1) | function b(t,d,e){var n=e.metadata,r=e.shouldTryNationalPrefixFormatting...
  function p (line 1) | function p(t,d,e){var n=e.metadata,r=e.useNationalPrefixFormattingRule,i...
  function C (line 1) | function C(t){return C="function"==typeof Symbol&&"symbol"==typeof Symbo...
  function N (line 1) | function N(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.en...
  function P (line 1) | function P(t){var d=function(t,d){if("object"!=C(t)||!t)return t;var e=t...
  function A (line 1) | function A(t){for(var d=[],e=0;e<t.length;){if("-"===t[e]){if(0===e||e==...
  function O (line 1) | function O(t){return 1===t.length?t[0]:t}
  function I (line 1) | function I(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function E (line 1) | function E(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=Array(...
  function T (line 1) | function T(t){return T="function"==typeof Symbol&&"symbol"==typeof Symbo...
  function F (line 1) | function F(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.en...
  function M (line 1) | function M(t){var d=function(t,d){if("object"!=T(t)||!t)return t;var e=t...
  function D (line 1) | function D(t,d,e){if("string"==typeof d){var n=t.join("");return 0===d.i...
  function j (line 1) | function j(t){return j="function"==typeof Symbol&&"symbol"==typeof Symbo...
  function G (line 1) | function G(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function B (line 1) | function B(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=Array(...
  function _ (line 1) | function _(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.en...
  function U (line 1) | function U(t){var d=function(t,d){if("object"!=j(t)||!t)return t;var e=t...
  function z (line 1) | function z(t){return z="function"==typeof Symbol&&"symbol"==typeof Symbo...
  function tt (line 1) | function tt(t,d){return function(t){if(Array.isArray(t))return t}(t)||fu...
  function dt (line 1) | function dt(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=Array...
  function et (line 1) | function et(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.e...
  function nt (line 1) | function nt(t){var d=function(t,d){if("object"!=z(t)||!t)return t;var e=...
  function ft (line 1) | function ft(t){return ft="function"==typeof Symbol&&"symbol"==typeof Sym...
  function ht (line 1) | function ht(t,d){return function(t){if(Array.isArray(t))return t}(t)||fu...
  function mt (line 1) | function mt(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=Array...
  function gt (line 1) | function gt(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.e...
  function yt (line 1) | function yt(t){var d=function(t,d){if("object"!=ft(t)||!t)return t;var e...
  function bt (line 1) | function bt(t){return vt.call(this,t,n.A)}
  function r (line 1) | function r(t,d){var e=Array.prototype.slice.call(d);return e.push(n.A),t...
  function i (line 1) | function i(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function a (line 1) | function a(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=Array(...
  function o (line 1) | function o(t,d){var e=d.countries,a=d.metadata;a=new n.Ay(a);for(var o,$...
  function i (line 1) | function i(t,d,e){if(d[t])return new r.A(t,d[t],e)}
  function a (line 1) | function a(){return(0,n.A)(i,arguments)}
  function a (line 1) | function a(t,d,e,r){if(d){var a=new n.Ay(r);a.selectNumberingPlan(d,e);v...
  function i (line 1) | function i(t){return i="function"==typeof Symbol&&"symbol"==typeof Symbo...
  function a (line 1) | function a(t,d){for(var e=0;e<d.length;e++){var n=d[e];n.enumerable=n.en...
  function o (line 1) | function o(t){var d=function(t,d){if("object"!=i(t)||!t)return t;var e=t...
  function $ (line 1) | function $(t,d,e){return d=s(d),function(t,d){if(d&&("object"==i(d)||"fu...
  function u (line 1) | function u(t){var d="function"==typeof Map?new Map:void 0;return u=funct...
  function l (line 1) | function l(){try{var t=!Boolean.prototype.valueOf.call(Reflect.construct...
  function c (line 1) | function c(t,d){return c=Object.setPrototypeOf?Object.setPrototypeOf.bin...
  function s (line 1) | function s(t){return s=Object.setPrototypeOf?Object.getPrototypeOf.bind(...
  function d (line 1) | function d(t){var e;return function(t,d){if(!(t instanceof d))throw new ...
  function g (line 1) | function g(t){var d="[  \\t,]*",e="[:\\..]?[  \\t,-]*",n="#?",r="[  \\t]...
  function S (line 1) | function S(t,d){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t[...
  function A (line 1) | function A(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=Array(...
  function w (line 1) | function w(t){for(var d,e="",n=S(t.split(""));!(d=n()).done;){e+=x(d.val...
  function x (line 1) | function x(t,d,e){return"+"===t?d?void("function"==typeof e&&e("end")):"...
  function K (line 1) | function K(t,d){var e,n=d.extractFormattedPhoneNumber,r=function(t){var ...
  function Y (line 1) | function Y(t,d,e){if(d=d||{},e=new h.Ay(e),d.defaultCountry&&!e.hasCount...
  function J (line 1) | function J(t){return J="function"==typeof Symbol&&"symbol"==typeof Symbo...
  function X (line 1) | function X(t,d){var e=Object.keys(t);if(Object.getOwnPropertySymbols){va...
  function Q (line 1) | function Q(t){for(var d=1;d<arguments.length;d++){var e=null!=arguments[...
  function q (line 1) | function q(t,d,e){return(d=function(t){var d=function(t,d){if("object"!=...
  function tt (line 1) | function tt(t){return tt="function"==typeof Symbol&&"symbol"==typeof Sym...
  function dt (line 1) | function dt(t,d){var e=Object.keys(t);if(Object.getOwnPropertySymbols){v...
  function et (line 1) | function et(t,d,e){return(d=function(t){var d=function(t,d){if("object"!...
  function nt (line 1) | function nt(t,d){return function(t){if(Array.isArray(t))return t}(t)||fu...
  function rt (line 1) | function rt(t,d){(null==d||d>t.length)&&(d=t.length);for(var e=0,n=Array...
  function it (line 1) | function it(t){var d,e,n,r=nt(Array.prototype.slice.call(t),4),i=r[0],a=...
  function at (line 1) | function at(){var t=it(arguments);return function(t,d,e){return Y(t,Q(Q(...
  function ot (line 1) | function ot(){return(0,n.A)(at,arguments)}
  function i (line 1) | function i(t,d){var e=d.nationalNumber,i=d.metadata;if(r&&i.isNonGeograp...
  func
Condensed preview — 256 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (7,234K chars).
[
  {
    "path": ".babelrc",
    "chars": 236,
    "preview": "{\n  \"presets\": [\"@babel/preset-react\", \"@babel/preset-env\"],\n  \"comments\": false,\n  \"plugins\": [\n    [\n      \"formatjs\","
  },
  {
    "path": ".gitattributes",
    "chars": 77,
    "preview": "umd/* binary\npackage-lock.json binary\n*.min.css binary\nsrc/i18n.min/* binary\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 1034,
    "preview": "---\nname: Bug report\nabout: Create a report to help us improve TinodeWeb\ntitle: ''\nlabels: bug\nassignees: ''\n\n---\n\nIf yo"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 709,
    "preview": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: feature request\nassignees: ''\n\n---\n\n"
  },
  {
    "path": ".gitignore",
    "chars": 75,
    "preview": ".DS_Store\nnode_modules\nsrc/i18n/srci/\nwebapp.code-workspace.code-workspace\n"
  },
  {
    "path": ".well-known/assetlinks.json",
    "chars": 739,
    "preview": "[{\n  \"relation\": [\"delegate_permission/common.handle_all_urls\"],\n  \"target\": {\n    \"namespace\": \"android_app\",\n    \"pack"
  },
  {
    "path": "LICENSE",
    "chars": 11357,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "README.md",
    "chars": 4692,
    "preview": "# Tinode Web\n\n## Briefing\n\nSingle-page web chat application for [Tinode](https://github.com/tinode/chat/). The app is bu"
  },
  {
    "path": "css/base.css",
    "chars": 87452,
    "preview": ":root {\n  color-scheme: light dark;\n\n  /* Size of text in message bubbles */\n  --message-text-size: 10pt;\n\n  /* Height o"
  },
  {
    "path": "firebase-init.js",
    "chars": 863,
    "preview": "// Get these values for your project from the https://console.firebase.google.com/\nconst FIREBASE_INIT = {\n  // Set up a"
  },
  {
    "path": "img/bkg/index.json",
    "chars": 1402,
    "preview": "{\n  \"patt\": [\n    {\"name\": \"a00.png\", \"size\": 200}, {\"name\": \"a01.jpg\", \"size\": 384}, {\"name\": \"a02.jpg\", \"size\": 384},\n"
  },
  {
    "path": "index-dev.html",
    "chars": 3143,
    "preview": "<!-- DEVELOPMENT version of the web app. -->\n<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <title>Tinode</title>\n    <me"
  },
  {
    "path": "index.html",
    "chars": 2471,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n<title>Tinode</title>\n<meta charset=\"utf-8\" />\n<meta name=\"viewport\" content=\"width=device"
  },
  {
    "path": "manifest.json",
    "chars": 1068,
    "preview": "{\n  \"name\": \"Tinode\",\n  \"short_name\": \"Tinode\",\n  \"description\": \"Tinode Web App.\\nSee more at https://tinode.co/\",\n  \"c"
  },
  {
    "path": "package.json",
    "chars": 2671,
    "preview": "{\n  \"name\": \"tinode-webapp\",\n  \"description\": \"Tinode messenger for the web\",\n  \"version\": \"0.25.2\",\n  \"repository\": {\n "
  },
  {
    "path": "postcss.config.js",
    "chars": 116,
    "preview": "module.exports = {\n    plugins: [\n        require('cssnano')({\n            preset: 'default',\n        }),\n    ],\n};\n"
  },
  {
    "path": "push.md",
    "chars": 1244,
    "preview": "# Push notifications\n\nIf you want to use the app with your own server and want web push notification to work you have to"
  },
  {
    "path": "scripts/gen-version.js",
    "chars": 465,
    "preview": "const fs = require('fs');\nconst version = require('../package.json').version;\n\nfunction writeVersion(fileName, useExport"
  },
  {
    "path": "scripts/i18n.js",
    "chars": 4538,
    "preview": "// 1. Updates translations files with new messages, mark no longer needed translations as obsolete.\n// 2. Takes all tran"
  },
  {
    "path": "service-worker.js",
    "chars": 5944,
    "preview": "// Must be located at the root.\nimportScripts('https://cdn.jsdelivr.net/npm/firebase@9.14.0/firebase-app-compat.js');\nim"
  },
  {
    "path": "src/config.js",
    "chars": 7032,
    "preview": "import { PACKAGE_VERSION } from './version.js';\n\n// Name of this application, used in the User-Agent.\nexport const APP_N"
  },
  {
    "path": "src/constants.js",
    "chars": 292,
    "preview": "// Video call states.\nexport const CALL_STATE_NONE = 0;\nexport const CALL_STATE_OUTGOING_INITATED = 1;\nexport const CALL"
  },
  {
    "path": "src/dcodes.json",
    "chars": 6510,
    "preview": "[{\"dial\":\"93\",\"code\":\"AF\"},{\"dial\":\"355\",\"code\":\"AL\"},{\"dial\":\"213\",\"code\":\"DZ\"},{\"dial\":\"1-684\",\"code\":\"AS\"},{\"dial\":\"3"
  },
  {
    "path": "src/i18n/ar.json",
    "chars": 59784,
    "preview": "{\n  \"action_block_contact\": {\n    \"translation\": \"حظر جهة الاتصال\",\n    \"defaultMessage\": \"Block Contact\",\n    \"descript"
  },
  {
    "path": "src/i18n/de.json",
    "chars": 60783,
    "preview": "{\n  \"action_block_contact\": {\n    \"translation\": \"Kontakt blockieren\",\n    \"defaultMessage\": \"Block Contact\",\n    \"descr"
  },
  {
    "path": "src/i18n/en.json",
    "chars": 59563,
    "preview": "{\n  \"action_block_contact\": {\n    \"translation\": \"Block Contact\",\n    \"defaultMessage\": \"Block Contact\",\n    \"descriptio"
  },
  {
    "path": "src/i18n/es.json",
    "chars": 60736,
    "preview": "{\n  \"action_block_contact\": {\n    \"translation\": \"Bloquear contacto\",\n    \"defaultMessage\": \"Block Contact\",\n    \"descri"
  },
  {
    "path": "src/i18n/ex/base-en.json",
    "chars": 36204,
    "preview": "{\n  \"action_block_contact\": {\n    \"defaultMessage\": \"Block Contact\",\n    \"description\": \"Flat button [Block Contact]\"\n  "
  },
  {
    "path": "src/i18n/fr.json",
    "chars": 60808,
    "preview": "{\n  \"action_block_contact\": {\n    \"translation\": \"Bloquer le Contact\",\n    \"defaultMessage\": \"Block Contact\",\n    \"descr"
  },
  {
    "path": "src/i18n/it.json",
    "chars": 60689,
    "preview": "{\n  \"action_block_contact\": {\n    \"translation\": \"Bloccare contatto\",\n    \"defaultMessage\": \"Block Contact\",\n    \"descri"
  },
  {
    "path": "src/i18n/ko.json",
    "chars": 57343,
    "preview": "{\n  \"action_block_contact\": {\n    \"translation\": \"연락차단\",\n    \"defaultMessage\": \"Block Contact\",\n    \"description\": \"Flat"
  },
  {
    "path": "src/i18n/ro.json",
    "chars": 60279,
    "preview": "{\n  \"action_block_contact\": {\n    \"translation\": \"Blochează contact\",\n    \"defaultMessage\": \"Block Contact\",\n    \"descri"
  },
  {
    "path": "src/i18n/ru.json",
    "chars": 60142,
    "preview": "{\n  \"action_block_contact\": {\n    \"translation\": \"Заблокировать контакт\",\n    \"defaultMessage\": \"Block Contact\",\n    \"de"
  },
  {
    "path": "src/i18n/th.json",
    "chars": 59330,
    "preview": "{\n  \"action_block_contact\": {\n    \"translation\": \"บล็อครายชื่อ\",\n    \"defaultMessage\": \"Block Contact\",\n    \"description"
  },
  {
    "path": "src/i18n/uk.json",
    "chars": 60197,
    "preview": "{\n  \"action_block_contact\": {\n    \"translation\": \"Заблокувати контакт\",\n    \"defaultMessage\": \"Block Contact\",\n    \"desc"
  },
  {
    "path": "src/i18n/vi.json",
    "chars": 59805,
    "preview": "{\n  \"action_block_contact\": {\n    \"translation\": \"Chặn liên hệ\",\n    \"defaultMessage\": \"Block Contact\",\n    \"description"
  },
  {
    "path": "src/i18n/zh-TW.json",
    "chars": 56988,
    "preview": "{\n  \"action_block_contact\": {\n    \"translation\": \"封鎖聯絡人\",\n    \"defaultMessage\": \"Block Contact\",\n    \"description\": \"Fla"
  },
  {
    "path": "src/i18n/zh.json",
    "chars": 56934,
    "preview": "{\n  \"action_block_contact\": {\n    \"translation\": \"屏蔽联系人\",\n    \"defaultMessage\": \"Block Contact\",\n    \"description\": \"Fla"
  },
  {
    "path": "src/i18n.min/ar.json",
    "chars": 11090,
    "preview": "{\"action_block_contact\":\"حظر جهة الاتصال\",\"action_cancel\":\"إلغاء\",\"action_clear_messages\":\"مسح الرسائل\",\"action_delete_m"
  },
  {
    "path": "src/i18n.min/de.json",
    "chars": 12089,
    "preview": "{\"action_block_contact\":\"Kontakt blockieren\",\"action_cancel\":\"Abbrechen\",\"action_clear_messages\":\"Nachrichten leeren\",\"a"
  },
  {
    "path": "src/i18n.min/en.json",
    "chars": 10869,
    "preview": "{\"action_block_contact\":\"Block Contact\",\"action_cancel\":\"cancel\",\"action_clear_messages\":\"Clear Messages\",\"action_delete"
  },
  {
    "path": "src/i18n.min/es.json",
    "chars": 12042,
    "preview": "{\"action_block_contact\":\"Bloquear contacto\",\"action_cancel\":\"cancelar\",\"action_clear_messages\":\"Borrar mensajes\",\"action"
  },
  {
    "path": "src/i18n.min/fr.json",
    "chars": 12114,
    "preview": "{\"action_block_contact\":\"Bloquer le Contact\",\"action_cancel\":\"annuler\",\"action_clear_messages\":\"Effacer les Messages\",\"a"
  },
  {
    "path": "src/i18n.min/it.json",
    "chars": 11995,
    "preview": "{\"action_block_contact\":\"Bloccare contatto\",\"action_cancel\":\"cancella\",\"action_clear_messages\":\"Cancella messaggi\",\"acti"
  },
  {
    "path": "src/i18n.min/ko.json",
    "chars": 8649,
    "preview": "{\"action_block_contact\":\"연락차단\",\"action_cancel\":\"취소\",\"action_clear_messages\":\"메시지지우기\",\"action_delete_messages\":\"모든메시지지우기\""
  },
  {
    "path": "src/i18n.min/ro.json",
    "chars": 11585,
    "preview": "{\"action_block_contact\":\"Blochează contact\",\"action_cancel\":\"anulează\",\"action_clear_messages\":\"Șterge mesajele\",\"action"
  },
  {
    "path": "src/i18n.min/ru.json",
    "chars": 11448,
    "preview": "{\"action_block_contact\":\"Заблокировать контакт\",\"action_cancel\":\"отменить\",\"action_clear_messages\":\"Удалить сообщения\",\""
  },
  {
    "path": "src/i18n.min/th.json",
    "chars": 10636,
    "preview": "{\"action_block_contact\":\"บล็อครายชื่อ\",\"action_cancel\":\"ยกเลิก\",\"action_clear_messages\":\"ล้างข้อความ\",\"action_delete_mes"
  },
  {
    "path": "src/i18n.min/uk.json",
    "chars": 11503,
    "preview": "{\"action_block_contact\":\"Заблокувати контакт\",\"action_cancel\":\"Скасувати\",\"action_clear_messages\":\"Очистити повідомлення"
  },
  {
    "path": "src/i18n.min/vi.json",
    "chars": 11111,
    "preview": "{\"action_block_contact\":\"Chặn liên hệ\",\"action_cancel\":\"hủy\",\"action_clear_messages\":\"Xóa tin nhắn\",\"action_delete_messa"
  },
  {
    "path": "src/i18n.min/zh-TW.json",
    "chars": 8294,
    "preview": "{\"action_block_contact\":\"封鎖聯絡人\",\"action_cancel\":\"取消\",\"action_clear_messages\":\"清除訊息\",\"action_delete_messages\":\"為所有人清除訊息\","
  },
  {
    "path": "src/i18n.min/zh.json",
    "chars": 8240,
    "preview": "{\"action_block_contact\":\"屏蔽联系人\",\"action_cancel\":\"取消\",\"action_clear_messages\":\"删除讯息\",\"action_delete_messages\":\"删除所有帖子\",\"a"
  },
  {
    "path": "src/index.js",
    "chars": 3016,
    "preview": "// Put all packages together.\n// Used to generate umd/index.prod.js\n\nimport React from 'react';\nimport { createRoot } fr"
  },
  {
    "path": "src/lib/blob-helpers.js",
    "chars": 10209,
    "preview": "// File and image helper functions.\nimport { TheCard } from 'tinode-sdk';\n\n// Supported image MIME types and correspondi"
  },
  {
    "path": "src/lib/formatters.js",
    "chars": 17519,
    "preview": "import React from 'react';\nimport { defineMessages } from 'react-intl';\n\nimport { Drafty, TheCard } from 'tinode-sdk';\n\n"
  },
  {
    "path": "src/lib/host-name.js",
    "chars": 848,
    "preview": "import { KNOWN_HOSTS, DEFAULT_HOST } from '../config.js';\n\n// Detect server address from the URL\nexport function detectS"
  },
  {
    "path": "src/lib/local-storage.js",
    "chars": 726,
    "preview": "// Helper functions for storing values in localStorage.\n// By default localStorage can store only strings, not objects o"
  },
  {
    "path": "src/lib/navigation.js",
    "chars": 2673,
    "preview": "// Utility class for hash navigation.\n\nexport default class HashNavigation {\n  // Parse hash as in http://www.example.co"
  },
  {
    "path": "src/lib/strformat.js",
    "chars": 4631,
    "preview": "// Short representation of time in the past.\nexport function shortDateFormat(then, locale) {\n  locale = locale || window"
  },
  {
    "path": "src/lib/strformat.test.js",
    "chars": 5827,
    "preview": "import {\n  shortDateFormat,\n  relativeDateFormat,\n  secondsToTime,\n  bytesToHumanSize,\n  shortenFileName,\n  idToColorCla"
  },
  {
    "path": "src/lib/utils.js",
    "chars": 8357,
    "preview": "// Odds and ends\n\nimport { Tinode } from 'tinode-sdk';\nimport { WALLPAPER_DEFAULTS } from '../config.js';\n\n// Make short"
  },
  {
    "path": "src/lib/utils.test.js",
    "chars": 5596,
    "preview": "import {\n  arrayEqual,\n  asEmail,\n  asPhone,\n  isUrlRelative,\n  sanitizeUrl,\n  sanitizeUrlForMime,\n  urlAsAttachment\n} f"
  },
  {
    "path": "src/version.js",
    "chars": 83,
    "preview": "// This is a generated file. Don't edit.\n\nexport const PACKAGE_VERSION = \"0.25.2\";\n"
  },
  {
    "path": "src/views/acc-general-view.jsx",
    "chars": 7302,
    "preview": "// Edit account parameters.\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nexport default cl"
  },
  {
    "path": "src/views/acc-notifications-view.jsx",
    "chars": 1852,
    "preview": "// Edit account parameters.\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport CheckBox f"
  },
  {
    "path": "src/views/acc-security-view.jsx",
    "chars": 6823,
    "preview": "// Edit account parameters.\nimport React from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'rea"
  },
  {
    "path": "src/views/acc-support-view.jsx",
    "chars": 2375,
    "preview": "// Edit account parameters.\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport { Tinode }"
  },
  {
    "path": "src/views/account-settings-view.jsx",
    "chars": 7185,
    "preview": "// Edit account parameters.\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\nimport { parsePhon"
  },
  {
    "path": "src/views/contacts-view.jsx",
    "chars": 3114,
    "preview": "/* ContactsView holds all contacts-related stuff */\nimport React from 'react';\nimport { FormattedMessage, defineMessages"
  },
  {
    "path": "src/views/create-account-view.jsx",
    "chars": 9026,
    "preview": "// Account registration.\nimport React, { Suspense } from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport"
  },
  {
    "path": "src/views/info-view.jsx",
    "chars": 27322,
    "preview": "// InfoView: panel with topic/user info.\nimport React from 'react';\nimport { FormattedMessage, FormattedNumber, defineMe"
  },
  {
    "path": "src/views/login-view.jsx",
    "chars": 3161,
    "preview": "// Login form.\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport CheckBox from '../widge"
  },
  {
    "path": "src/views/logo-view.jsx",
    "chars": 962,
    "preview": "/* This is just a static page to display when no conversation is selected. */\nimport React from 'react';\nimport { Format"
  },
  {
    "path": "src/views/messages-view.jsx",
    "chars": 70869,
    "preview": "// Panel with a chat.\n\nimport React, { Suspense } from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } "
  },
  {
    "path": "src/views/new-topic-view.jsx",
    "chars": 6278,
    "preview": "// Create new topic and invite users or send an invite.\nimport React from 'react';\nimport { FormattedMessage, defineMess"
  },
  {
    "path": "src/views/password-reset-view.jsx",
    "chars": 8534,
    "preview": "// A password reset form.\nimport React from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'react"
  },
  {
    "path": "src/views/settings-view.jsx",
    "chars": 3444,
    "preview": "// Tinode config panel.\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport CheckBox from "
  },
  {
    "path": "src/views/sidepanel-view.jsx",
    "chars": 11865,
    "preview": "import React, { Suspense } from 'react';\nimport { defineMessages, FormattedMessage, injectIntl } from 'react-intl';\n\nimp"
  },
  {
    "path": "src/views/tinode-web.jsx",
    "chars": 85498,
    "preview": "// The top-level class to hold all functionality together.\nimport React, { Suspense } from 'react';\nimport { FormattedMe"
  },
  {
    "path": "src/views/topic-common-view.jsx",
    "chars": 2098,
    "preview": "// View for editing topic parameters (including 'me' topic).\n\nimport React from 'react';\n\nimport TopicDescEdit from '../"
  },
  {
    "path": "src/views/validation-view.jsx",
    "chars": 3897,
    "preview": "// ValidationView: panel for confirming credentials, like email or phone.\nimport React from 'react';\nimport { FormattedM"
  },
  {
    "path": "src/views/wallpapers.jsx",
    "chars": 5760,
    "preview": "// Edit account parameters.\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\nimport HashNavigat"
  },
  {
    "path": "src/widgets/alert.jsx",
    "chars": 1018,
    "preview": "import React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nexport default class Alert extends React.Pure"
  },
  {
    "path": "src/widgets/attachment.jsx",
    "chars": 3192,
    "preview": "import React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport FileProgress from './file-progress.jsx"
  },
  {
    "path": "src/widgets/audio-player.jsx",
    "chars": 8509,
    "preview": "// Audio recorder widget.\n\nimport React from 'react';\nimport { defineMessages, injectIntl } from 'react-intl';\n\nimport {"
  },
  {
    "path": "src/widgets/audio-recorder.jsx",
    "chars": 13484,
    "preview": "// Audio recorder widget.\n\nimport React from 'react';\nimport { defineMessages, injectIntl } from 'react-intl';\n\nimport A"
  },
  {
    "path": "src/widgets/avatar-crop.jsx",
    "chars": 1832,
    "preview": "// Edit account parameters.\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport Cropper fr"
  },
  {
    "path": "src/widgets/avatar-upload.jsx",
    "chars": 2416,
    "preview": "import React from 'react';\n\nimport LetterTile from './letter-tile.jsx';\nimport LoadSpinner from './load-spinner.jsx';\n\ni"
  },
  {
    "path": "src/widgets/badge-list.jsx",
    "chars": 1346,
    "preview": "import React from 'react';\nimport { defineMessages, injectIntl } from 'react-intl';\n\nconst icon_mapping = {'staff': 'ver"
  },
  {
    "path": "src/widgets/button-back.jsx",
    "chars": 320,
    "preview": "// The <- button to be displayed in title bars.\nimport React from 'react';\n\nexport default class ButtonBack extends Reac"
  },
  {
    "path": "src/widgets/call-incoming.jsx",
    "chars": 4380,
    "preview": "// IncomingCall: displays Accept & Reject buttons for incoming calls.\nimport React from 'react';\n\nimport BadgeList from "
  },
  {
    "path": "src/widgets/call-message.jsx",
    "chars": 2201,
    "preview": "// Chat message describing a video or voice call.\n\nimport React from 'react';\nimport { FormattedMessage } from 'react-in"
  },
  {
    "path": "src/widgets/call-panel.jsx",
    "chars": 25124,
    "preview": "// CallPanel displays call in progress: local and remote viewports and controls.\nimport React from 'react';\nimport { For"
  },
  {
    "path": "src/widgets/call-status.jsx",
    "chars": 2128,
    "preview": "// The counter of unread messages in the topic.\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl'"
  },
  {
    "path": "src/widgets/chat-message.jsx",
    "chars": 9853,
    "preview": "// Single chat message bubble, sent or received.\n\nimport React from 'react';\nimport { FormattedMessage, injectIntl } fro"
  },
  {
    "path": "src/widgets/checkbox.jsx",
    "chars": 1374,
    "preview": "import React from 'react';\n\n/* CheckBox: styled three-state checkbox, either clickable or static */\nexport default class"
  },
  {
    "path": "src/widgets/chip-input.jsx",
    "chars": 4240,
    "preview": "import React from 'react';\n\nimport Chip from './chip.jsx';\n\nimport { makeImageUrl } from '../lib/blob-helpers.js';\n\n/* B"
  },
  {
    "path": "src/widgets/chip.jsx",
    "chars": 1090,
    "preview": "import React from 'react';\n\nimport LetterTile from './letter-tile.jsx';\n\nexport default class Chip extends React.PureCom"
  },
  {
    "path": "src/widgets/contact-action.jsx",
    "chars": 693,
    "preview": "// A panel included into a list of contacts with an action text.\nimport React from 'react';\nimport { injectIntl } from '"
  },
  {
    "path": "src/widgets/contact-badges.jsx",
    "chars": 805,
    "preview": "import React from 'react';\n\nconst icon_mapping = {'muted': 'notifications_off', 'banned': 'block', 'staff': 'verified_us"
  },
  {
    "path": "src/widgets/contact-list.jsx",
    "chars": 6272,
    "preview": "// ContactList: component for showing a list of contacts,\n// such as a list of group members in a group chat.\nimport Rea"
  },
  {
    "path": "src/widgets/contact.jsx",
    "chars": 5850,
    "preview": "// A single topic or user.\nimport React from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'reac"
  },
  {
    "path": "src/widgets/context-menu.jsx",
    "chars": 18106,
    "preview": "// Context Menu: popup/dropdown menu.\nimport React from 'react';\nimport { injectIntl, defineMessages } from 'react-intl'"
  },
  {
    "path": "src/widgets/credential-edit.jsx",
    "chars": 6399,
    "preview": "// Enter one credential at a time.\n\nimport React from 'react';\nimport { defineMessages, FormattedMessage, injectIntl } f"
  },
  {
    "path": "src/widgets/cropper.jsx",
    "chars": 10085,
    "preview": "// Image zoom and crop widget.\n\nimport React from 'react';\n\nconst DEFAULT_MAX_ZOOM = 8;\n\nexport default class Cropper ex"
  },
  {
    "path": "src/widgets/doc-preview.jsx",
    "chars": 2660,
    "preview": "import React from 'react';\nimport { FormattedMessage } from 'react-intl';\nimport SendMessage from '../widgets/send-messa"
  },
  {
    "path": "src/widgets/error-panel.jsx",
    "chars": 1306,
    "preview": "import React from 'react';\n\nimport MenuCancel from './menu-cancel.jsx';\n\nexport default class ErrorPanel extends React.P"
  },
  {
    "path": "src/widgets/file-progress.jsx",
    "chars": 848,
    "preview": "// File uload/download progress indicator with a cancel inside.\nimport React from 'react';\nimport { FormattedMessage } f"
  },
  {
    "path": "src/widgets/forward-dialog.jsx",
    "chars": 2983,
    "preview": "// Forward Menu: message forwarding popup/dropdown menu.\nimport React from 'react';\nimport { FormattedMessage } from 're"
  },
  {
    "path": "src/widgets/group-manager.jsx",
    "chars": 6164,
    "preview": "// GroupMembers: control for managing a list of group members.\nimport React from 'react';\nimport { FormattedMessage, def"
  },
  {
    "path": "src/widgets/group-subs.jsx",
    "chars": 1534,
    "preview": "// GroupSubs: a list of group subscribers currently online.\n// Show in the topic title bar\nimport React from 'react';\nim"
  },
  {
    "path": "src/widgets/host-selector.jsx",
    "chars": 1515,
    "preview": "import React from 'react';\n\nimport { KNOWN_HOSTS } from '../config.js';\n\n/* Combobox for selecting host name */\n\nexport "
  },
  {
    "path": "src/widgets/image-preview.jsx",
    "chars": 4292,
    "preview": "import React from 'react';\nimport { FormattedMessage } from 'react-intl';\nimport SendMessage from './send-message.jsx';\n"
  },
  {
    "path": "src/widgets/in-place-edit.jsx",
    "chars": 5066,
    "preview": "// In-place text editor. Shows text with an icon which toggles it into an input field.\nimport React from 'react';\n\nimpor"
  },
  {
    "path": "src/widgets/inline-video.jsx",
    "chars": 1163,
    "preview": "// Element which shows static video preview:\n// an image with duration and a play button in the middle.\n\nimport React fr"
  },
  {
    "path": "src/widgets/invitation.jsx",
    "chars": 1614,
    "preview": "// A single topic or user.\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nexport default cla"
  },
  {
    "path": "src/widgets/lazy-image.jsx",
    "chars": 1451,
    "preview": "// Image with a placeholder which is replaced when the promise is resolved.\nimport React from 'react';\n\nexport default c"
  },
  {
    "path": "src/widgets/letter-tile.jsx",
    "chars": 1669,
    "preview": "import React from 'react';\n\nimport { Tinode } from 'tinode-sdk';\n\nimport { idToColorClass } from '../lib/strformat.js';\n"
  },
  {
    "path": "src/widgets/load-spinner.jsx",
    "chars": 392,
    "preview": "import React from 'react';\n\nexport default class LoadSpinner extends React.PureComponent {\n  render() {\n    const classN"
  },
  {
    "path": "src/widgets/menu-cancel.jsx",
    "chars": 314,
    "preview": "// The X menu to be displayed in title bars.\nimport React from 'react';\n\nexport default class MenuCancel extends React.P"
  },
  {
    "path": "src/widgets/menu-contacts.jsx",
    "chars": 430,
    "preview": "import React from 'react';\n\nexport default class MenuContacts extends React.PureComponent {\n  render() {\n    return (\n  "
  },
  {
    "path": "src/widgets/menu-start.jsx",
    "chars": 441,
    "preview": "import React from 'react';\n\nexport default class MenuStart extends React.PureComponent {\n  render() {\n    return (\n     "
  },
  {
    "path": "src/widgets/meta-message.jsx",
    "chars": 689,
    "preview": "// Message bubble with non-payload content, such as an indicator of deleted content or a date stamp.\n\nimport React from "
  },
  {
    "path": "src/widgets/new-topic-by-id.jsx",
    "chars": 2525,
    "preview": "import QRCode from 'qrcodejs';\nimport React from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from '"
  },
  {
    "path": "src/widgets/new-topic-group.jsx",
    "chars": 7876,
    "preview": "import React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport AvatarCrop from './avatar-crop.jsx';\ni"
  },
  {
    "path": "src/widgets/permissions-editor.jsx",
    "chars": 5180,
    "preview": "// PermissionsEditor: Component for editing permissions\n// <PermissionsEditor mode=\"JWROD\" skip=\"O\" onChange={this.handl"
  },
  {
    "path": "src/widgets/phone-country-selector.jsx",
    "chars": 1704,
    "preview": "// Selector for country dialing code.\n\nimport React from 'react';\nimport { injectIntl } from 'react-intl';\n\nimport * as "
  },
  {
    "path": "src/widgets/phone-edit.jsx",
    "chars": 3492,
    "preview": "// Editor for a phone number.\n\nimport React from 'react';\nimport { defineMessages, injectIntl } from 'react-intl';\nimpor"
  },
  {
    "path": "src/widgets/pinned-messages.jsx",
    "chars": 5592,
    "preview": "// Send message form.\nimport React from 'react';\nimport { defineMessages, injectIntl } from 'react-intl';\nimport { Draft"
  },
  {
    "path": "src/widgets/received-marker.jsx",
    "chars": 1706,
    "preview": "// Received/read indicator.\nimport React from 'react';\nimport { defineMessages, injectIntl } from 'react-intl';\n\nimport "
  },
  {
    "path": "src/widgets/search-contacts.jsx",
    "chars": 1984,
    "preview": "import React from 'react';\n\nimport { Tinode } from 'tinode-sdk';\n\nexport default class SearchContacts extends React.Pure"
  },
  {
    "path": "src/widgets/send-message.jsx",
    "chars": 11166,
    "preview": "// Send message form.\nimport React, { Suspense } from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } f"
  },
  {
    "path": "src/widgets/show-qrcode.jsx",
    "chars": 906,
    "preview": "import QRCode from 'qrcodejs';\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport { QRCOD"
  },
  {
    "path": "src/widgets/side-navbar.jsx",
    "chars": 1640,
    "preview": "import React from 'react';\n\nimport LetterTile from './letter-tile.jsx';\nimport ButtonBack from './button-back.jsx';\nimpo"
  },
  {
    "path": "src/widgets/tag-manager.jsx",
    "chars": 5702,
    "preview": "// TagManager: edit topic or user tags.\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimpor"
  },
  {
    "path": "src/widgets/the-card-mini.jsx",
    "chars": 3305,
    "preview": "import React from 'react';\nimport { defineMessages, FormattedMessage, injectIntl } from 'react-intl';\nimport { TheCard }"
  },
  {
    "path": "src/widgets/the-card-preview.jsx",
    "chars": 5792,
    "preview": "import React from 'react';\nimport { defineMessages, FormattedMessage } from 'react-intl';\nimport { parsePhoneNumber } fr"
  },
  {
    "path": "src/widgets/topic-desc-edit.jsx",
    "chars": 14771,
    "preview": "// Widget for editing topic description.\n\nimport React from 'react';\nimport { defineMessages, FormattedMessage, injectIn"
  },
  {
    "path": "src/widgets/topic-security.jsx",
    "chars": 9686,
    "preview": "// Edit account parameters.\nimport React from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'rea"
  },
  {
    "path": "src/widgets/unread-badge.jsx",
    "chars": 296,
    "preview": "// The counter of unread messages in the topic.\nimport React from 'react';\n\nexport default class UnreadBadge extends Rea"
  },
  {
    "path": "src/widgets/uploading-image.jsx",
    "chars": 535,
    "preview": "// Image view with progress bar and a cancel button.\nimport React from 'react';\n\nimport FileProgress from './file-progre"
  },
  {
    "path": "src/widgets/video-preview.jsx",
    "chars": 4287,
    "preview": "import React from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'react-intl';\nimport SendMessage"
  },
  {
    "path": "src/widgets/visible-password.jsx",
    "chars": 2466,
    "preview": "// Password with a visiblity toggle.\nimport React from 'react';\n\nexport default class VisiblePassword extends React.Pure"
  },
  {
    "path": "umd/0.prod.js",
    "chars": 7231,
    "preview": "\"use strict\";(self.webpackChunktinode_webapp=self.webpackChunktinode_webapp||[]).push([[0],{4e3:function(e,t,i){i.r(t);v"
  },
  {
    "path": "umd/107.prod.js",
    "chars": 10566,
    "preview": "\"use strict\";(globalThis.webpackChunktinode_webapp=globalThis.webpackChunktinode_webapp||[]).push([[107],{107:e=>{e.expo"
  },
  {
    "path": "umd/128.prod.js",
    "chars": 9652,
    "preview": "\"use strict\";(globalThis.webpackChunktinode_webapp=globalThis.webpackChunktinode_webapp||[]).push([[128],{6128:e=>{e.exp"
  },
  {
    "path": "umd/140.prod.js",
    "chars": 108654,
    "preview": "(globalThis.webpackChunktinode_webapp=globalThis.webpackChunktinode_webapp||[]).push([[140],{5704:(e,t)=>{\"use strict\";t"
  },
  {
    "path": "umd/143.prod.js",
    "chars": 11235,
    "preview": "\"use strict\";(self.webpackChunktinode_webapp=self.webpackChunktinode_webapp||[]).push([[143],{7143:function(e){e.exports"
  },
  {
    "path": "umd/175.prod.js",
    "chars": 12234,
    "preview": "\"use strict\";(self.webpackChunktinode_webapp=self.webpackChunktinode_webapp||[]).push([[175],{2175:function(e){e.exports"
  },
  {
    "path": "umd/178.prod.js",
    "chars": 9717,
    "preview": "\"use strict\";(globalThis.webpackChunktinode_webapp=globalThis.webpackChunktinode_webapp||[]).push([[178],{8178:e=>{e.exp"
  },
  {
    "path": "umd/186.prod.js",
    "chars": 8792,
    "preview": "\"use strict\";(self.webpackChunktinode_webapp=self.webpackChunktinode_webapp||[]).push([[186],{1186:function(e){e.exports"
  },
  {
    "path": "umd/187.prod.js",
    "chars": 9176,
    "preview": "\"use strict\";(globalThis.webpackChunktinode_webapp=globalThis.webpackChunktinode_webapp||[]).push([[187],{1187:e=>{e.exp"
  },
  {
    "path": "umd/197.prod.js",
    "chars": 12152,
    "preview": "\"use strict\";(self.webpackChunktinode_webapp=self.webpackChunktinode_webapp||[]).push([[197],{7197:function(e){e.exports"
  },
  {
    "path": "umd/203.prod.js",
    "chars": 166543,
    "preview": "\"use strict\";(globalThis.webpackChunktinode_webapp=globalThis.webpackChunktinode_webapp||[]).push([[203],{7520:(t,d,e)=>"
  },
  {
    "path": "umd/226.prod.js",
    "chars": 7237,
    "preview": "\"use strict\";(globalThis.webpackChunktinode_webapp=globalThis.webpackChunktinode_webapp||[]).push([[226],{5226:e=>{e.exp"
  },
  {
    "path": "umd/246.prod.js",
    "chars": 108678,
    "preview": "(globalThis.webpackChunktinode_webapp=globalThis.webpackChunktinode_webapp||[]).push([[246],{9742:(e,t)=>{\"use strict\";t"
  },
  {
    "path": "umd/252.prod.js",
    "chars": 7279,
    "preview": "\"use strict\";(globalThis.webpackChunktinode_webapp=globalThis.webpackChunktinode_webapp||[]).push([[252],{252:(e,t,i)=>{"
  },
  {
    "path": "umd/264.prod.js",
    "chars": 9369,
    "preview": "\"use strict\";(globalThis.webpackChunktinode_webapp=globalThis.webpackChunktinode_webapp||[]).push([[264],{1264:e=>{e.exp"
  },
  {
    "path": "umd/271.prod.js",
    "chars": 19047,
    "preview": "\"use strict\";(self.webpackChunktinode_webapp=self.webpackChunktinode_webapp||[]).push([[271],{111:function(e){e.exports="
  },
  {
    "path": "umd/290.prod.js",
    "chars": 7830,
    "preview": "\"use strict\";(globalThis.webpackChunktinode_webapp=globalThis.webpackChunktinode_webapp||[]).push([[290],{1290:(d,e,a)=>"
  },
  {
    "path": "umd/297.prod.js",
    "chars": 11256,
    "preview": "\"use strict\";(self.webpackChunktinode_webapp=self.webpackChunktinode_webapp||[]).push([[297],{6297:function(n){n.exports"
  },
  {
    "path": "umd/311.prod.js",
    "chars": 14682,
    "preview": "\"use strict\";(globalThis.webpackChunktinode_webapp=globalThis.webpackChunktinode_webapp||[]).push([[311],{1311:(e,d,a)=>"
  },
  {
    "path": "umd/316.prod.js",
    "chars": 7802,
    "preview": "\"use strict\";(self.webpackChunktinode_webapp=self.webpackChunktinode_webapp||[]).push([[316],{111:function(d){d.exports="
  },
  {
    "path": "umd/327.prod.js",
    "chars": 14569,
    "preview": "\"use strict\";(globalThis.webpackChunktinode_webapp=globalThis.webpackChunktinode_webapp||[]).push([[327],{327:(e,a,d)=>{"
  },
  {
    "path": "umd/330.prod.js",
    "chars": 36549,
    "preview": "\"use strict\";(self.webpackChunktinode_webapp=self.webpackChunktinode_webapp||[]).push([[330],{4701:function(t,e){e.A={AC"
  },
  {
    "path": "umd/336.prod.js",
    "chars": 10385,
    "preview": "\"use strict\";(globalThis.webpackChunktinode_webapp=globalThis.webpackChunktinode_webapp||[]).push([[336],{3336:e=>{e.exp"
  },
  {
    "path": "umd/352.prod.js",
    "chars": 8898,
    "preview": "\"use strict\";(self.webpackChunktinode_webapp=self.webpackChunktinode_webapp||[]).push([[352],{2352:function(e,t,a){a.r(t"
  },
  {
    "path": "umd/365.prod.js",
    "chars": 18412,
    "preview": "\"use strict\";(globalThis.webpackChunktinode_webapp=globalThis.webpackChunktinode_webapp||[]).push([[365],{1365:(e,a,t)=>"
  },
  {
    "path": "umd/371.prod.js",
    "chars": 3433,
    "preview": "\"use strict\";(self.webpackChunktinode_webapp=self.webpackChunktinode_webapp||[]).push([[371],{6371:function(e,t,n){n.r(t"
  },
  {
    "path": "umd/372.prod.js",
    "chars": 14685,
    "preview": "\"use strict\";(globalThis.webpackChunktinode_webapp=globalThis.webpackChunktinode_webapp||[]).push([[372],{7752:(e,d,a)=>"
  },
  {
    "path": "umd/399.prod.js",
    "chars": 11016,
    "preview": "\"use strict\";(self.webpackChunktinode_webapp=self.webpackChunktinode_webapp||[]).push([[399],{3399:function(e){e.exports"
  },
  {
    "path": "umd/429.prod.js",
    "chars": 75653,
    "preview": "\"use strict\";(self.webpackChunktinode_webapp=self.webpackChunktinode_webapp||[]).push([[429],{1725:function(e,t,s){var i"
  },
  {
    "path": "umd/440.prod.js",
    "chars": 7279,
    "preview": "\"use strict\";(globalThis.webpackChunktinode_webapp=globalThis.webpackChunktinode_webapp||[]).push([[440],{440:(e,t,i)=>{"
  },
  {
    "path": "umd/472.prod.js",
    "chars": 2227,
    "preview": "\"use strict\";(self.webpackChunktinode_webapp=self.webpackChunktinode_webapp||[]).push([[472],{4472:function(e,t,n){n.r(t"
  },
  {
    "path": "umd/500.prod.js",
    "chars": 12281,
    "preview": "\"use strict\";(self.webpackChunktinode_webapp=self.webpackChunktinode_webapp||[]).push([[500],{2500:function(e){e.exports"
  },
  {
    "path": "umd/501.prod.js",
    "chars": 167501,
    "preview": "\"use strict\";(globalThis.webpackChunktinode_webapp=globalThis.webpackChunktinode_webapp||[]).push([[501],{8169:(t,d,e)=>"
  },
  {
    "path": "umd/514.prod.js",
    "chars": 9447,
    "preview": "\"use strict\";(globalThis.webpackChunktinode_webapp=globalThis.webpackChunktinode_webapp||[]).push([[514],{4514:e=>{e.exp"
  },
  {
    "path": "umd/536.prod.js",
    "chars": 10782,
    "preview": "\"use strict\";(self.webpackChunktinode_webapp=self.webpackChunktinode_webapp||[]).push([[536],{2536:function(e){e.exports"
  },
  {
    "path": "umd/537.prod.js",
    "chars": 108667,
    "preview": "(self.webpackChunktinode_webapp=self.webpackChunktinode_webapp||[]).push([[537],{251:function(e,t){t.read=function(e,t,n"
  },
  {
    "path": "umd/552.prod.js",
    "chars": 11660,
    "preview": "\"use strict\";(self.webpackChunktinode_webapp=self.webpackChunktinode_webapp||[]).push([[552],{4552:function(e){e.exports"
  },
  {
    "path": "umd/553.prod.js",
    "chars": 11593,
    "preview": "\"use strict\";(self.webpackChunktinode_webapp=self.webpackChunktinode_webapp||[]).push([[553],{5553:function(e){e.exports"
  },
  {
    "path": "umd/564.prod.js",
    "chars": 7161,
    "preview": "\"use strict\";(globalThis.webpackChunktinode_webapp=globalThis.webpackChunktinode_webapp||[]).push([[564],{4564:e=>{e.exp"
  },
  {
    "path": "umd/570.prod.js",
    "chars": 8384,
    "preview": "\"use strict\";(self.webpackChunktinode_webapp=self.webpackChunktinode_webapp||[]).push([[570],{570:function(e){e.exports="
  },
  {
    "path": "umd/632.prod.js",
    "chars": 10418,
    "preview": "\"use strict\";(globalThis.webpackChunktinode_webapp=globalThis.webpackChunktinode_webapp||[]).push([[632],{1632:e=>{e.exp"
  },
  {
    "path": "umd/634.prod.js",
    "chars": 9717,
    "preview": "\"use strict\";(globalThis.webpackChunktinode_webapp=globalThis.webpackChunktinode_webapp||[]).push([[634],{3634:e=>{e.exp"
  },
  {
    "path": "umd/64.prod.js",
    "chars": 12186,
    "preview": "\"use strict\";(self.webpackChunktinode_webapp=self.webpackChunktinode_webapp||[]).push([[64],{6064:function(e){e.exports="
  },
  {
    "path": "umd/648.prod.js",
    "chars": 7108,
    "preview": "\"use strict\";(globalThis.webpackChunktinode_webapp=globalThis.webpackChunktinode_webapp||[]).push([[648],{3648:e=>{e.exp"
  },
  {
    "path": "umd/688.prod.js",
    "chars": 166892,
    "preview": "\"use strict\";(globalThis.webpackChunktinode_webapp=globalThis.webpackChunktinode_webapp||[]).push([[688],{7300:(t,d,e)=>"
  },
  {
    "path": "umd/700.prod.js",
    "chars": 7184,
    "preview": "\"use strict\";(globalThis.webpackChunktinode_webapp=globalThis.webpackChunktinode_webapp||[]).push([[700],{5700:e=>{e.exp"
  },
  {
    "path": "umd/734.prod.js",
    "chars": 9744,
    "preview": "\"use strict\";(globalThis.webpackChunktinode_webapp=globalThis.webpackChunktinode_webapp||[]).push([[734],{3734:e=>{e.exp"
  },
  {
    "path": "umd/744.prod.js",
    "chars": 8439,
    "preview": "\"use strict\";(self.webpackChunktinode_webapp=self.webpackChunktinode_webapp||[]).push([[744],{5744:function(e){e.exports"
  },
  {
    "path": "umd/747.prod.js",
    "chars": 32016,
    "preview": "\"use strict\";(self.webpackChunktinode_webapp=self.webpackChunktinode_webapp||[]).push([[747],{6235:function(e,t,s){var a"
  },
  {
    "path": "umd/752.prod.js",
    "chars": 18414,
    "preview": "\"use strict\";(globalThis.webpackChunktinode_webapp=globalThis.webpackChunktinode_webapp||[]).push([[752],{2752:(e,a,t)=>"
  },
  {
    "path": "umd/780.prod.js",
    "chars": 11730,
    "preview": "\"use strict\";(self.webpackChunktinode_webapp=self.webpackChunktinode_webapp||[]).push([[780],{8399:function(e){e.exports"
  },
  {
    "path": "umd/817.prod.js",
    "chars": 9998,
    "preview": "\"use strict\";(globalThis.webpackChunktinode_webapp=globalThis.webpackChunktinode_webapp||[]).push([[817],{4817:e=>{e.exp"
  },
  {
    "path": "umd/827.prod.js",
    "chars": 4042,
    "preview": "\"use strict\";(self.webpackChunktinode_webapp=self.webpackChunktinode_webapp||[]).push([[827],{3827:function(e,t,a){a.r(t"
  },
  {
    "path": "umd/836.prod.js",
    "chars": 15834,
    "preview": "\"use strict\";(self.webpackChunktinode_webapp=self.webpackChunktinode_webapp||[]).push([[836],{6836:function(e,t,a){a.r(t"
  },
  {
    "path": "umd/844.prod.js",
    "chars": 9903,
    "preview": "\"use strict\";(globalThis.webpackChunktinode_webapp=globalThis.webpackChunktinode_webapp||[]).push([[844],{5844:e=>{e.exp"
  },
  {
    "path": "umd/864.prod.js",
    "chars": 9176,
    "preview": "\"use strict\";(globalThis.webpackChunktinode_webapp=globalThis.webpackChunktinode_webapp||[]).push([[864],{8864:e=>{e.exp"
  },
  {
    "path": "umd/868.prod.js",
    "chars": 14573,
    "preview": "\"use strict\";(globalThis.webpackChunktinode_webapp=globalThis.webpackChunktinode_webapp||[]).push([[868],{2868:(e,a,d)=>"
  }
]

// ... and 56 more files (download for full content)

About this extraction

This page contains the full source code of the tinode/webapp GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 256 files (6.2 MB), approximately 1.6M tokens, and a symbol index with 5326 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!