Compare commits

...

1252 Commits

Author SHA1 Message Date
a461444bed make version (instead of make release) 2023-10-08 13:53:45 +00:00
1307f87912 Simplify chapril release process 2023-10-07 08:15:40 +00:00
23cf858a02 Add some bash safeguards in README.charpil.md 2023-10-07 08:13:09 +00:00
b49146b36f [Branding] Customize homepage's text and links + CSS adjustments. 2023-10-07 08:13:09 +00:00
8d67dce865 [Branding] Replace Converse's logo with Chapril's logo. 2023-10-07 08:13:07 +00:00
543807aa50 Create a README for Chapril's build. 2023-10-07 08:12:53 +00:00
JC Brand
82a8c3f9fc Release 10.1.6 2023-08-31 21:30:48 +02:00
JC Brand
3e680e88d8 Fix import path 2023-08-31 21:20:40 +02:00
JC Brand
005f5374f0 Fixes #3246 2023-08-31 21:20:40 +02:00
JC Brand
79bb8e76ce Fix GIF rendering artifacts related to patching 2023-08-31 21:20:40 +02:00
JC Brand
61192f91d9 Fix GIF rendering issue
Remove the GIF parsing code from this repo and instead add a dependency on gifuct-js.
2023-08-31 21:20:40 +02:00
JC Brand
e31d4c7bac Release 10.1.5
Refine the `dist` step by creating a proper temporary file.

I spent a lot of time trying to pinpoint the underlying cause, why
translation chunk files are empty when generating a bundle with newer JS
features (i.e. not pinning preset-env to IE11) but couldn't find it.
2023-06-30 06:38:40 +02:00
JC Brand
c30569dfd3 Release 10.1.5
Found another bug while trying to make the release.

Running `npm run nodeps` last breaks dynamic importing of the DayJS
translations. I'm not sure why, I think maybe because of broken `.map`
files.

The fix for now is to move the js-po files out of the way, and then copy
them back in after running `npm run build`.

Hopefully all of this won't be necessary with gettext 0.22 which should
support template literals
2023-06-29 23:41:15 +02:00
JC Brand
5e02b9bd5d Release 10.1.5 (this time hopefully for real)
As I was making the release, I found a bug in the Makefile that still
prevented the locale JSON files from being properly generated.
2023-06-29 23:09:49 +02:00
JC Brand
9114db8764 Release 10.1.5 2023-06-29 22:29:11 +02:00
JC Brand
bc7621c25d Updates #3207 - Generate po files in the release checkout
Refactor the Makefile somewhat.

- Rename `make release` to `make version`
- Add `make release-checkout` which checks out the release branch
2023-06-29 22:16:19 +02:00
ssantos
ae518aa2c3 Translated using Weblate (Portuguese)
Currently translated at 99.8% (539 of 540 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/pt/
2023-06-29 21:55:15 +02:00
josé m
e4a4b2819c Translated using Weblate (Galician)
Currently translated at 100.0% (540 of 540 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/gl/
2023-06-29 21:55:15 +02:00
JC Brand
5310021b67 Modernize the i18n code.
- Remove old deprecated API methods `systemLanguage`, `browserLanguage`
  and `userLanguage`.
- Add types via JSDoc
2023-06-29 09:43:53 +02:00
SilverYoCha
e18fdd56b1 Fix #3209.
Fixing some technical errors when avoiding importing the `converse` global with bootstrap modal API.
2023-06-27 11:07:35 +02:00
JC Brand
94963662e7 Fix ordering or args 2023-06-25 11:22:16 +02:00
JC Brand
4f14d50f5d Check out depth of 1 when deploying 2023-06-25 11:15:46 +02:00
JC Brand
699ab71f21 Larger sponsor image 2023-06-25 11:13:24 +02:00
JC Brand
daeb641530 Postrelease 2023-06-25 11:09:50 +02:00
JC Brand
6e71555ee4 Release 10.1.4 2023-06-25 11:03:06 +02:00
JC Brand
27d61411ab Update release instructions 2023-06-25 10:58:58 +02:00
JC Brand
3328e1c94c Add libsignal as a 3rd party dependency
Ultimately I'd like to use libomemo.js, but it's not yet ready
https://github.com/conversejs/libomemo.js
2023-06-25 10:58:58 +02:00
Eric
c63c787a6d Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (540 of 540 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/zh_Hans/
2023-06-25 10:58:48 +02:00
gallegonovato
0efeead71a Translated using Weblate (Spanish)
Currently translated at 100.0% (540 of 540 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/es/
2023-06-25 10:58:48 +02:00
JC Brand
5822fade32 Add make recipe to create tar files 2023-06-23 13:34:51 +02:00
JC Brand
621612d126 Postrelease 2023-06-23 10:39:32 +02:00
JC Brand
536350155d Release 10.1.3 2023-06-23 10:17:53 +02:00
Emmanuel Gil Peyrot
841a57fd66 Translated using Weblate (French)
Currently translated at 98.3% (533 of 542 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/fr/
2023-06-23 10:09:14 +02:00
Breno Peres
175595098a Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (542 of 542 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/pt_BR/
2023-06-23 10:09:14 +02:00
Breno Peres
03655b45b2 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (542 of 542 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/pt_BR/
2023-06-23 10:09:14 +02:00
JC Brand
fa9ae16ead Run npm update 2023-06-23 10:01:34 +02:00
JC Brand
cb1f929045 Fixes #3123: Contacts do not show up online until chat is opened with them.
The issue was that nothing was listening to the new `presenceChanged` event.
2023-06-09 20:37:27 +02:00
JC Brand
9ba339a6d9 Add colon 2023-06-09 17:12:49 +02:00
JC Brand
bc452596a7 Add workflow_dispatch
So that worfklows can be triggered.
https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_dispatch
2023-06-09 17:10:29 +02:00
JC Brand
2b732cdb94 Bump filesize to latest version and fix issues. 2023-06-09 14:55:09 +02:00
JC Brand
1e4937bf41 Run npm update and fix resulting dynamic import error.
For some reason the newer webpack versions can't handle the destructured
assignment from a dynamic import of a JSON file.
2023-06-09 12:34:58 +02:00
JC Brand
8b28ffecfe Don't run type check when making dist files 2023-06-09 11:40:04 +02:00
JC Brand
80bf81db6f Use Node 18.x in CI tests 2023-06-09 11:25:23 +02:00
JC Brand
7fdbcd0e64 Make sure node_modules are installed 2023-06-09 11:23:56 +02:00
JC Brand
975a2c2305 Remove Lerna and bump Node version.
Lerna doesn't seem to be needed anymore, NPM workspaces functionality suffices.
2023-06-09 11:19:23 +02:00
dependabot[bot]
abad4d054b Bump postcss-loader from 7.0.2 to 7.3.2
Bumps [postcss-loader](https://github.com/webpack-contrib/postcss-loader) from 7.0.2 to 7.3.2.
- [Release notes](https://github.com/webpack-contrib/postcss-loader/releases)
- [Changelog](https://github.com/webpack-contrib/postcss-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/postcss-loader/compare/v7.0.2...v7.3.2)

---
updated-dependencies:
- dependency-name: postcss-loader
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-09 10:58:29 +02:00
dependabot[bot]
b5b6d1f8b2 Bump webpack-dev-server from 4.11.1 to 4.15.0
Bumps [webpack-dev-server](https://github.com/webpack/webpack-dev-server) from 4.11.1 to 4.15.0.
- [Release notes](https://github.com/webpack/webpack-dev-server/releases)
- [Changelog](https://github.com/webpack/webpack-dev-server/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-dev-server/compare/v4.11.1...v4.15.0)

---
updated-dependencies:
- dependency-name: webpack-dev-server
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-09 10:25:46 +02:00
dependabot[bot]
64aef7f70d Bump @babel/preset-env from 7.20.2 to 7.22.5
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.20.2 to 7.22.5.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.22.5/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-09 10:24:59 +02:00
dependabot[bot]
4f0f210e21
Bump @babel/cli from 7.20.7 to 7.22.5 (#3189)
Bumps [@babel/cli](https://github.com/babel/babel/tree/HEAD/packages/babel-cli) from 7.20.7 to 7.22.5.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.22.5/packages/babel-cli)

---
updated-dependencies:
- dependency-name: "@babel/cli"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-09 10:24:42 +02:00
dependabot[bot]
c4299e92be
Bump karma-jasmine-html-reporter from 2.0.0 to 2.1.0 (#3180)
Bumps [karma-jasmine-html-reporter](https://github.com/dfederm/karma-jasmine-html-reporter) from 2.0.0 to 2.1.0.
- [Release notes](https://github.com/dfederm/karma-jasmine-html-reporter/releases)
- [Commits](https://github.com/dfederm/karma-jasmine-html-reporter/commits)

---
updated-dependencies:
- dependency-name: karma-jasmine-html-reporter
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-08 12:50:13 +02:00
dependabot[bot]
0cc03e7e7a
Bump @typescript-eslint/eslint-plugin from 5.48.0 to 5.59.9 (#3181)
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 5.48.0 to 5.59.9.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.59.9/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-08 12:49:31 +02:00
dependabot[bot]
f9f246282b
Bump mini-css-extract-plugin from 2.7.2 to 2.7.6 (#3184)
Bumps [mini-css-extract-plugin](https://github.com/webpack-contrib/mini-css-extract-plugin) from 2.7.2 to 2.7.6.
- [Release notes](https://github.com/webpack-contrib/mini-css-extract-plugin/releases)
- [Changelog](https://github.com/webpack-contrib/mini-css-extract-plugin/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/mini-css-extract-plugin/compare/v2.7.2...v2.7.6)

---
updated-dependencies:
- dependency-name: mini-css-extract-plugin
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-08 12:48:48 +02:00
dependabot[bot]
3e4a8b23fe
Bump webpack-cli from 4.10.0 to 5.1.4 (#3185)
Bumps [webpack-cli](https://github.com/webpack/webpack-cli) from 4.10.0 to 5.1.4.
- [Release notes](https://github.com/webpack/webpack-cli/releases)
- [Changelog](https://github.com/webpack/webpack-cli/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-cli/compare/webpack-cli@4.10.0...webpack-cli@5.1.4)

---
updated-dependencies:
- dependency-name: webpack-cli
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-08 12:47:57 +02:00
dependabot[bot]
cdda140137
Bump webpack from 5.75.0 to 5.76.0 (#3173)
Bumps [webpack](https://github.com/webpack/webpack) from 5.75.0 to 5.76.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.75.0...v5.76.0)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-07 14:40:29 +02:00
dependabot[bot]
0a15b003dc
Bump sass from 1.58.1 to 1.62.1 (#3171)
Bumps [sass](https://github.com/sass/dart-sass) from 1.58.1 to 1.62.1.
- [Release notes](https://github.com/sass/dart-sass/releases)
- [Changelog](https://github.com/sass/dart-sass/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sass/dart-sass/compare/1.58.1...1.62.1)

---
updated-dependencies:
- dependency-name: sass
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-07 12:48:36 +02:00
dependabot[bot]
23539ecf47
Bump socket.io-parser from 4.2.2 to 4.2.4 (#3175)
Bumps [socket.io-parser](https://github.com/socketio/socket.io-parser) from 4.2.2 to 4.2.4.
- [Release notes](https://github.com/socketio/socket.io-parser/releases)
- [Changelog](https://github.com/socketio/socket.io-parser/blob/main/CHANGELOG.md)
- [Commits](https://github.com/socketio/socket.io-parser/compare/4.2.2...4.2.4)

---
updated-dependencies:
- dependency-name: socket.io-parser
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-07 12:47:52 +02:00
dependabot[bot]
efa448956e
Bump dayjs from 1.11.6 to 1.11.8 (#3172)
Bumps [dayjs](https://github.com/iamkun/dayjs) from 1.11.6 to 1.11.8.
- [Release notes](https://github.com/iamkun/dayjs/releases)
- [Changelog](https://github.com/iamkun/dayjs/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/iamkun/dayjs/compare/v1.11.6...v1.11.8)

---
updated-dependencies:
- dependency-name: dayjs
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-07 12:47:13 +02:00
dependabot[bot]
743f336dc5
Bump jsdoc from 4.0.0 to 4.0.2 (#3146)
Bumps [jsdoc](https://github.com/jsdoc/jsdoc) from 4.0.0 to 4.0.2.
- [Release notes](https://github.com/jsdoc/jsdoc/releases)
- [Changelog](https://github.com/jsdoc/jsdoc/blob/4.0.2/CHANGES.md)
- [Commits](https://github.com/jsdoc/jsdoc/compare/4.0.0...4.0.2)

---
updated-dependencies:
- dependency-name: jsdoc
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-07 12:46:35 +02:00
dependabot[bot]
8a0386fdcc
Bump @babel/core from 7.20.12 to 7.22.1 (#3170)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.20.12 to 7.22.1.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.22.1/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-07 11:41:21 +02:00
JC Brand
b647f5463f Check out new repo when making a release
Ignore media dir
2023-06-06 10:31:53 +02:00
Breno Reis
46f2e40f91
Small pt_BR corrections (#3168)
* 'a bastante tempo' -> 'há bastante tempo'

* Fix a wrong comma usage

* Update CHANGES.md
2023-06-06 09:58:45 +02:00
Daniele Bortoluzzi
8b1b4b6446 Translated using Weblate (Italian)
Currently translated at 100.0% (542 of 542 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/it/
2023-06-06 09:48:58 +02:00
Raphaël Maginot
9407d00c67 Translated using Weblate (French)
Currently translated at 97.4% (528 of 542 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/fr/
2023-06-06 09:48:58 +02:00
Sergi Font
f0d584aed6 Translated using Weblate (Catalan)
Currently translated at 81.1% (440 of 542 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/ca/
2023-06-06 09:48:58 +02:00
Meno25
2768c2a3ec Translated using Weblate (Arabic)
Currently translated at 69.3% (376 of 542 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/ar/
2023-06-06 09:48:58 +02:00
Mr. EddX
8fb1716681 Translated using Weblate (Bulgarian)
Currently translated at 100.0% (542 of 542 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/bg/
2023-06-06 09:48:58 +02:00
Mr. EddX
507cfa9ef2 Translated using Weblate (Bulgarian)
Currently translated at 33.7% (183 of 542 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/bg/
2023-06-06 09:48:58 +02:00
Meno25
5ef7807a68 Translated using Weblate (Arabic)
Currently translated at 69.3% (376 of 542 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/ar/
2023-06-06 09:48:58 +02:00
Meno25
952d3cf440 Translated using Weblate (Arabic)
Currently translated at 68.6% (372 of 542 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/ar/
2023-06-06 09:48:58 +02:00
Kim Alvefur
c9a95faa35 Translated using Weblate (Swedish)
Currently translated at 97.4% (528 of 542 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/sv/
2023-06-06 09:48:58 +02:00
gnu-ewm
02185cee5f Translated using Weblate (Polish)
Currently translated at 94.6% (513 of 542 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/pl/
2023-06-06 09:48:58 +02:00
K.Y
40290f27e7 Translated using Weblate (Uyghur)
Currently translated at 97.9% (531 of 542 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/ug/
2023-06-06 09:48:58 +02:00
Sam Mendes
bbfcb74eaa Translated using Weblate (Persian)
Currently translated at 22.5% (122 of 542 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/fa/
2023-06-06 09:48:58 +02:00
Zoltán Tóth
a2e618a8f6 Translated using Weblate (Hungarian)
Currently translated at 93.5% (507 of 542 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/hu/
2023-06-06 09:48:58 +02:00
Ze-oZ
ebbb39a9aa Translated using Weblate (Greek)
Currently translated at 58.4% (317 of 542 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/el/
2023-06-06 09:48:58 +02:00
Allan Nordhøy
2d66a974d0 Translated using Weblate (Norwegian Bokmål)
Currently translated at 66.2% (359 of 542 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/nb_NO/
2023-06-06 09:48:58 +02:00
nautilusx
fa12dae7bc Translated using Weblate (German)
Currently translated at 100.0% (542 of 542 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/de/
2023-06-06 09:48:58 +02:00
Eric
df25e16438 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (542 of 542 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/zh_Hans/
2023-06-06 09:48:58 +02:00
Oğuz Ersen
c39d61f62c Translated using Weblate (Turkish)
Currently translated at 100.0% (542 of 542 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/tr/
2023-06-06 09:48:58 +02:00
josé m
01ce344d82 Translated using Weblate (Galician)
Currently translated at 100.0% (542 of 542 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/gl/
2023-06-06 09:48:58 +02:00
gallegonovato
bb428fa1d7 Translated using Weblate (Spanish)
Currently translated at 100.0% (542 of 542 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/es/
2023-06-06 09:48:58 +02:00
JC Brand
5a710e4601 Add new sponsor BairesDev 2023-06-05 16:53:49 +02:00
JC Brand
f91f4cb7ab Allow arguments to be passed when running tests 2023-06-05 09:39:37 +02:00
JC Brand
f2ac748e06 Add test and lint NPM scripts 2023-06-02 07:31:47 +02:00
JC Brand
27a47c6ee8 fixes #3165
Use configured nickname in profile view in the control box.
Remove doc for the unimplemented `fullname` setting.
2023-06-02 07:24:37 +02:00
JC Brand
0a338feb40 headless.js has been renamed to index.js 2023-03-15 17:53:33 +01:00
JC Brand
d74daccfbb Fix logo transparency and add extra platforms in doap file 2023-03-03 17:28:26 +01:00
JC Brand
5c3acc8a4d Rename package module files to index.js
Makes it easier to import, you don't have to specify the file name, just
the package name.
2023-03-03 17:28:26 +01:00
JC Brand
48e7987f38 Start work on removing constants from _converse object 2023-03-03 17:28:26 +01:00
JC Brand
4d2a8e9f8d Create new config setting stanza_timeout
And move STANZA_TIMEOUT off `_converse` and into constants.js
2023-03-03 17:28:26 +01:00
JC Brand
3d0e9a7374 Move CONNECTION_STATUS to constant.js 2023-03-03 17:28:26 +01:00
JC Brand
fb054c40be Experimenting with avoiding importing the converse global 2023-03-03 17:28:26 +01:00
drlight17
c3c666e568
dragresize over iframe fix function concept (#3157)
Fixes stuttering of conversejs overlayed dragresize UI elements over the iframes on the parent page.
2023-03-03 11:52:24 +01:00
JC Brand
6b365458f5 Get rid of lodash's invoke method 2023-02-26 19:32:55 +01:00
JC Brand
885a3d92b5 Move private API to own file 2023-02-26 18:10:01 +01:00
JC Brand
6df80507f3 Move ConnectionFeedback model to its own file 2023-02-26 18:10:01 +01:00
JC Brand
16754c15aa Register Strophe namespaces in constants.js 2023-02-26 18:10:01 +01:00
JC Brand
70a10efd49 Move public API into its own file 2023-02-26 18:10:01 +01:00
JC Brand
9a63629b40 Get rid of lodash's isFunction 2023-02-26 18:10:01 +01:00
JC Brand
dcfc0d50f4 Refactor shared API functions out into src/headless/shared/api 2023-02-26 18:10:01 +01:00
JC Brand
fde55bea2c Include XEP-0172 nick in all outgoing presence subscribe stanzas 2023-02-26 09:53:25 +01:00
JC Brand
3530ccc35d Add initial TypeScript support and declaration files 2023-02-23 09:38:11 +01:00
JC Brand
05c5cd1046 Remove call to api.confirm in @converse/headless 2023-02-22 15:21:56 +01:00
JC Brand
c38c706079 Fix logo not showing in background 2023-02-22 12:25:21 +01:00
JC Brand
e1e93c2ec9 Properly set checkbox state in bookmark form 2023-02-22 12:25:21 +01:00
JC Brand
16b442ac19 Occupant modal: Only show role/affiliation forms for moderators 2023-02-22 09:32:20 +01:00
JC Brand
0122bd7bab Import emoji utils.
Fixes `TypeError: core_default.isOnlyEmojis is not a function`
when using only `@converse/headless`.
2023-02-22 09:10:22 +01:00
JC Brand
56259fd22e Add the role form to the occupant modal 2023-02-21 23:14:16 +01:00
JC Brand
85181053e6 Make the role form a custom element
So that it can be used in the occupant modal as well.
2023-02-21 23:14:16 +01:00
JC Brand
26062df4e5 Fix logo path 2023-02-21 23:14:16 +01:00
JC Brand
2fb9fec8f8 Use addEventListener in the constructor
In Lit elements, the `initialize` function can get called multiple
times, thereby causing a memory leak if `addEventListener` is called
there and not removed.

The `ElementView` only calls it once, but I'm making the change so that
it's not forgotten when we eventually move to using Lit elements for
modals.
2023-02-21 23:14:16 +01:00
JC Brand
d4cb67dc5f Add affiliation form to the occupant modal 2023-02-21 23:14:16 +01:00
JC Brand
ad7b4ae343 Add affiliation form to the occupant modal 2023-02-21 20:18:59 +01:00
JC Brand
57f489f61b Turn the MUC affiliation form into a component
So that it can be used elsewhere, for example in the occupant modal.
2023-02-21 20:18:16 +01:00
JC Brand
6ce8879e9c CSS: fix MUC textarea color when correcting a message 2023-02-21 17:41:39 +01:00
JC Brand
1ee4cce2fd Modtools: fix wrench icon not visible in dracula theme
Also fix spacing of buttons
2023-02-21 09:30:29 +01:00
JC Brand
b69e5b5482 Create occupants based on messages
That way the occupant modal can still be shown in MUCs even if the user
is no longer online.
2023-02-20 22:02:13 +01:00
JC Brand
3f6ad0d950 CSS build fixes
- Bump postcss.
- Remove postcss-clean. It's incompatible with newer versions and
  apparently unnecesary.
- Finally got CSS source maps to work again
2023-02-20 12:43:20 +01:00
JC Brand
9899351597 Add a deploy Makefile recipe 2023-02-17 12:19:08 +01:00
JC Brand
0b3bcbfe40 Release 10.1.2 2023-02-17 11:56:30 +01:00
JC Brand
5e3139f563 Fixes #1490: Busy-loop when fetching registration form fails 2023-02-17 11:44:22 +01:00
JC Brand
7b8b32638c Fixes #3137
- Modernize the `RegisterPanel` component and turn it into a Lit element.
- Improve CSS and move into plugin.
- Fix button click handler not being registered.
- Fix switching between login/register form after logging out (Fixes #1556)
2023-02-16 23:45:59 +01:00
JC Brand
8035084e8e Remove unused dir 'converse-logs' 2023-02-16 14:48:02 +01:00
JC Brand
19466ddf62 Remove codefirst as sponsor 2023-02-16 14:47:23 +01:00
JC Brand
bb7ed5315f XEP-0437 MUC RAI fixes
Avoid unnecessarily connecting to rooms that should instead receive room
activity indicators (RAI).

- Don't join a newly created room that qualifies for RAI.
- Upon switching back to the tab, don't reconnect to a room that qualifies for RAI.
- Don't ping a room that we didn't actually enter.
2023-02-16 14:25:24 +01:00
JC Brand
6719aeba45 Release 10.1.1 2023-02-15 15:14:13 +01:00
Igor
45844447bf Translated using Weblate (Russian)
Currently translated at 100.0% (534 of 534 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/ru/
2023-02-15 15:06:56 +01:00
koukei
82314eb1df Translated using Weblate (Indonesian)
Currently translated at 76.4% (408 of 534 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/id/
2023-02-15 15:06:56 +01:00
nautilusx
d9c86ed575 Translated using Weblate (German)
Currently translated at 99.8% (533 of 534 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/de/
2023-02-15 15:06:56 +01:00
Eric
89d231a5dd Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (534 of 534 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/zh_Hans/
2023-02-15 15:06:56 +01:00
Oğuz Ersen
72406b4aac Translated using Weblate (Turkish)
Currently translated at 100.0% (534 of 534 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/tr/
2023-02-15 15:06:56 +01:00
gallegonovato
e08b58c3d3 Translated using Weblate (Galician)
Currently translated at 100.0% (534 of 534 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/gl/
2023-02-15 15:06:56 +01:00
gallegonovato
387c992381 Translated using Weblate (Spanish)
Currently translated at 100.0% (534 of 534 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/es/
2023-02-15 15:06:56 +01:00
JC Brand
4e98383e65 Ran npm update 2023-02-15 15:00:38 +01:00
JC Brand
dae84028c2 Fixes #1851: Sort open groupchats alphabetically 2023-02-15 14:43:56 +01:00
JC Brand
5e5bdc78ec Bump @converse/skeletor to 0.0.8 for @converse/headless 2023-02-15 14:43:39 +01:00
JC Brand
15c10376b0 Rename all templates to camelCase
To conform with naming conventions regarding functions, which the
templates are.
2023-02-15 14:29:07 +01:00
JC Brand
ccc165facc Update roomslist and templates to bring in line with conventions 2023-02-15 14:29:07 +01:00
JC Brand
aa299af3ec Update files in package.json to include Sass files in ./src 2023-02-14 14:39:36 +01:00
JC Brand
b16e3efbd4 Update to @conversejs/skeletor version 0.0.8 2023-02-14 13:25:40 +01:00
JC Brand
5db3e8ca51 Move adhoc plugin into own directory with separate files 2023-02-14 11:51:35 +01:00
JC Brand
0fcdb2a594 Add-hoc form fixes
- Provide actions as received in the Ad-Hoc form
- Add support for multi-stage ad-hoc forms
- Add new tests for multi-stage forms

Fixes #2240
2023-02-14 11:51:35 +01:00
JC Brand
5029d93523 XML stanza parsing fixes
- Add a `Stanza` class which can be used by Strophe because it has a
  `tree()` function. This is what gets returned by the `stx` tagged
  template.

- Throw an error when no valid namespace is on the stanza.
    Strophe.Builder used to automatically add the `jabber:client` namespace,
    but that doesn't happen with `toStanza`, so we need to fail if it's not
    specified by the user.

- Use the Strophe XML Parser
    This opens the door to NodeJS support
2023-02-14 11:50:38 +01:00
JC Brand
bab11b682b Fix failing test 2023-02-13 20:37:11 +01:00
JC Brand
9343488864 Update translations 2023-02-08 12:06:46 +01:00
Emmanuel Gil Peyrot
782c8c97fa Translated using Weblate (French)
Currently translated at 99.2% (531 of 535 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/fr/
2023-02-08 11:08:15 +01:00
JC Brand
d2f7756313 Translated using Weblate (Afrikaans)
Currently translated at 98.5% (527 of 535 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/af/
2023-02-08 11:08:15 +01:00
Quentin PAGÈS
07371b0852 Translated using Weblate (Occitan)
Currently translated at 75.7% (405 of 535 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/oc/
2023-02-08 11:08:15 +01:00
nautilusx
25aa0303c6 Translated using Weblate (German)
Currently translated at 100.0% (535 of 535 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/de/
2023-02-08 11:08:15 +01:00
52871299hzy
6186f05a3e Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (535 of 535 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/zh_Hans/
2023-02-08 11:08:15 +01:00
jiangshanghan
dd4f1e6b85 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (535 of 535 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/zh_Hans/
2023-02-08 11:08:15 +01:00
kapad
366390935f Translated using Weblate (Greek)
Currently translated at 58.6% (314 of 535 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/el/
2023-02-08 11:08:15 +01:00
josé m
7eb07fa02f Translated using Weblate (Galician)
Currently translated at 100.0% (535 of 535 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/gl/
2023-02-08 11:08:15 +01:00
K.Y
fbe2e41de7 Translated using Weblate (Uyghur)
Currently translated at 100.0% (535 of 535 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/ug/
2023-02-08 11:08:15 +01:00
licat
cfc2d93b9b Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (535 of 535 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/zh_Hans/
2023-02-08 11:08:15 +01:00
Eric
12170461cd Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (535 of 535 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/zh_Hans/
2023-02-08 11:08:15 +01:00
gallegonovato
ab079036da Translated using Weblate (Spanish)
Currently translated at 100.0% (535 of 535 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/es/
2023-02-08 11:08:15 +01:00
nautilusx
8001cf3809 Translated using Weblate (German)
Currently translated at 100.0% (535 of 535 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/de/
2023-02-08 11:08:15 +01:00
josé m
d93a47d246 Translated using Weblate (Galician)
Currently translated at 100.0% (535 of 535 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/gl/
2023-02-08 11:08:15 +01:00
Jaime Marquínez Ferrándiz
76fb90319b Translated using Weblate (Spanish)
Currently translated at 98.5% (527 of 535 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/es/
2023-02-08 11:08:15 +01:00
nautilusx
9ca1114670 Translated using Weblate (German)
Currently translated at 99.6% (533 of 535 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/de/
2023-02-08 11:08:15 +01:00
Oğuz Ersen
251784c21c Translated using Weblate (Turkish)
Currently translated at 100.0% (535 of 535 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/tr/
2023-02-08 11:08:15 +01:00
JC Brand
8c3ce2892b Updates #3128: Fix test and add changelog entry 2023-01-28 22:50:48 +01:00
JC Brand
6c44fb2a2f Fixes #3128 2023-01-28 22:37:52 +01:00
JC Brand
465aa38222 Refactor bookmark modal
- Use `getDisplayName` to have proper fallback for the MUC name
- Don't use the term "Unbookmark". There might be other reasons for
opening the bookmark modal besides removing a bookmark.
2023-01-28 22:37:52 +01:00
JC Brand
6fc83db9df Run npm update 2023-01-17 12:41:48 +01:00
JC Brand
a486fe25b8 Configure Webpack to make @converse/headless a library
Also, remove unused alias.
2023-01-17 12:33:08 +01:00
Licaon_Kter
87c172acd0 Update info on saved scram 2023-01-10 19:16:30 +01:00
Licaon_Kter
968ec8182c Fix typo 2023-01-10 19:15:39 +01:00
JC Brand
451ed18261 Postrelease and fix issue with Uyghur translations not loading 2023-01-07 21:50:13 +01:00
JC Brand
078936fb8a Release 10.1.0 2023-01-07 21:14:22 +01:00
JC Brand
0227b2e06c Run npm update 2023-01-07 21:07:32 +01:00
Marco Marchiò
44c22bb984 Translated using Weblate (Italian)
Currently translated at 99.6% (520 of 522 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/it/
2023-01-07 21:02:31 +01:00
Emmanuel Gil Peyrot
da12005420 Translated using Weblate (French)
Currently translated at 99.6% (520 of 522 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/fr/
2023-01-07 21:02:31 +01:00
JC Brand
de65409e79 Add Uyghur 2023-01-02 09:45:04 +01:00
Trần H. Trung
9ab99a0859 Translated using Weblate (Vietnamese)
Currently translated at 35.8% (187 of 522 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/vi/
2023-01-01 17:01:16 +01:00
ssantos
77fdbb5aa2 Translated using Weblate (Portuguese)
Currently translated at 98.4% (514 of 522 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/pt/
2023-01-01 17:01:16 +01:00
gallegonovato
a8f4bc4617 Translated using Weblate (Galician)
Currently translated at 100.0% (522 of 522 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/gl/
2023-01-01 17:01:16 +01:00
K.Y
18cd864e09 Translated using Weblate (Uyghur)
Currently translated at 100.0% (515 of 515 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/ug/
2023-01-01 17:01:16 +01:00
Gediminas Murauskas
192861f9c9 Translated using Weblate (Lithuanian)
Currently translated at 100.0% (522 of 522 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/lt/
2023-01-01 17:01:16 +01:00
nautilusx
4a43b46432 Translated using Weblate (German)
Currently translated at 100.0% (522 of 522 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/de/
2023-01-01 17:01:16 +01:00
Eric
95bf14385b Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (522 of 522 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/zh_Hans/
2023-01-01 17:01:16 +01:00
Oğuz Ersen
0fe2df24ad Translated using Weblate (Turkish)
Currently translated at 100.0% (522 of 522 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/tr/
2023-01-01 17:01:16 +01:00
gallegonovato
5a368a9c0f Translated using Weblate (Galician)
Currently translated at 100.0% (522 of 522 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/gl/
2023-01-01 17:01:16 +01:00
gallegonovato
73b9cbea13 Translated using Weblate (Spanish)
Currently translated at 100.0% (522 of 522 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/es/
2023-01-01 17:01:16 +01:00
JC Brand
2dee891c63 Translated using Weblate (Afrikaans)
Currently translated at 100.0% (522 of 522 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/af/
2023-01-01 17:01:16 +01:00
K.Y
97b87bcdc1 Translated using Weblate (Uyghur)
Currently translated at 1.5% (8 of 520 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/ug/
2023-01-01 17:01:16 +01:00
K.Y
c10f18ad1c Added translation using Weblate (Uyghur) 2023-01-01 17:01:16 +01:00
yater
4d687b022a removing the entry for a removed sponsor image
image (logo of "c") is removed.
c6bc5e1438
2022-12-29 10:35:29 +01:00
JC Brand
53d562481e Add @converse/headless as a NPM workspace 2022-12-28 22:13:31 +01:00
JC Brand
7539fc1a6f Move functions out of src/headless/core.js into utils 2022-12-28 21:36:40 +01:00
JC Brand
f740332e95 Fixes based on Github's code scanning results 2022-12-28 21:14:15 +01:00
JC Brand
4abc9c45d3 Exclude tests from code scanning 2022-12-28 11:49:37 +01:00
LGTM Migrator
756942d2bd Add CodeQL workflow for GitHub code scanning 2022-12-28 11:49:37 +01:00
JC Brand
fdcab413f5 Use crypto.randomUUID() if available 2022-12-28 11:49:37 +01:00
JC Brand
3c6dd5d0ae Run npm update in src/headless 2022-12-28 10:18:14 +01:00
JC Brand
3004d7bff5 Fix docs example on how to use the shared worker 2022-12-28 10:12:52 +01:00
JC Brand
6494b34da3 Don't automatically log in again if the user manually logged out
Fixes #2759
2022-12-28 09:57:32 +01:00
JC Brand
447fe8ba08 Refactor the code related to storing SCRAM keys
- No need to create a new storage mechanism, just use `persistent`.
- Store SCRAM keys per JID
- Upon succesfull login, store the current session JID, so that we know who to fetch SCRAM keys for
- Only store SCRAM keys when the device is trusted

Fixes #3001
2022-12-28 09:56:41 +01:00
based-a-tron
8ab0b718de Added option to save SCRAM keys 2022-12-27 22:39:12 +01:00
JC Brand
97e5bb9b11 Run npm update 2022-12-27 21:12:40 +01:00
JC Brand
5f38a914b1 Update and clean up password-reset feature
- No need for it to be in a separate plugin
- Make all UI strings translateable
- Remove the "Are you sure?" prompt
- Add tests

Fixes #326
2022-12-27 21:07:23 +01:00
based-a-tron
fa132567da Reworked profile modal; Added rudimentary password reset plugin 2022-12-27 12:46:29 +01:00
JC Brand
5ea00b8008 Tweak modal tab style 2022-12-27 12:46:29 +01:00
JC Brand
a76393f216 Also handle 'normal' messages from roster contacts 2022-12-26 19:17:40 +01:00
JC Brand
739d79e90c Fixes #2816 2022-12-20 18:05:35 +01:00
JC Brand
e63ba2075f Use repeat directive to render roster and MUC occupant items
If we don't use `repeat`, a DOM node may be reused with different state
(e.g. the `model` it receives originally changes upon next render).

https://lit.dev/docs/templates/lists/#when-to-use-map-or-repeat

Fixes #2816
2022-12-13 10:04:13 +01:00
JC Brand
8ca265d8d5 CSS: Fix color for info alerts 2022-12-02 23:55:07 +01:00
JC Brand
78a7841afb Don't duplicate disco items across two collections
We now no longer have an `.items` collection on a disco entity.
Instead, add a new API method `api.disco.entities.items` should be used.

This should solve the issue of the entities disappearing when reloading
the page.

Updates #2925
2022-12-02 22:50:06 +01:00
JC Brand
4733e7f65f Run npm update 2022-11-25 10:34:59 +01:00
JC Brand
8c84e276ff Run npm update 2022-11-08 20:35:17 +01:00
JC Brand
a251608fc5 Fix race condition where waitUntilFeaturesDiscovered was resolved too early
When calling `api.supports(feature, entity_jid)`, it checks whether the entity
supports the feature or whether any of the sub-items on the entity
supports that feature.

However, on `DiscoEntity`, the `waitUntilFeaturesDiscovered` promise
didn't wait for the items on the entity to be fetched, and was therefore
resolved too quickly.

This caused the file upload button to not render.

Updates #2925
2022-11-08 20:03:37 +01:00
dependabot[bot]
3af6168270 Bump lerna from 5.5.1 to 6.0.1
Bumps [lerna](https://github.com/lerna/lerna/tree/HEAD/core/lerna) from 5.5.1 to 6.0.1.
- [Release notes](https://github.com/lerna/lerna/releases)
- [Changelog](https://github.com/lerna/lerna/blob/main/core/lerna/CHANGELOG.md)
- [Commits](https://github.com/lerna/lerna/commits/v6.0.1/core/lerna)

---
updated-dependencies:
- dependency-name: lerna
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-04 21:25:22 +01:00
dependabot[bot]
34c17a7662 Bump sass-loader from 12.6.0 to 13.1.0
Bumps [sass-loader](https://github.com/webpack-contrib/sass-loader) from 12.6.0 to 13.1.0.
- [Release notes](https://github.com/webpack-contrib/sass-loader/releases)
- [Changelog](https://github.com/webpack-contrib/sass-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/sass-loader/compare/v12.6.0...v13.1.0)

---
updated-dependencies:
- dependency-name: sass-loader
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-04 21:23:20 +01:00
dependabot[bot]
87aba699f1 Bump babel-loader from 8.2.5 to 9.1.0
Bumps [babel-loader](https://github.com/babel/babel-loader) from 8.2.5 to 9.1.0.
- [Release notes](https://github.com/babel/babel-loader/releases)
- [Changelog](https://github.com/babel/babel-loader/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel-loader/compare/v8.2.5...v9.1.0)

---
updated-dependencies:
- dependency-name: babel-loader
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-04 21:20:31 +01:00
dependabot[bot]
defe5cdcb0 Bump karma-jasmine-html-reporter from 1.7.0 to 2.0.0
Bumps [karma-jasmine-html-reporter](https://github.com/dfederm/karma-jasmine-html-reporter) from 1.7.0 to 2.0.0.
- [Release notes](https://github.com/dfederm/karma-jasmine-html-reporter/releases)
- [Commits](https://github.com/dfederm/karma-jasmine-html-reporter/compare/v1.7.0...v2.0.0)

---
updated-dependencies:
- dependency-name: karma-jasmine-html-reporter
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-04 21:17:13 +01:00
JC Brand
038a38cae0 Run npm update 2022-11-04 16:47:01 +01:00
dependabot[bot]
8aaf792c6c Bump jsdoc from 3.6.11 to 4.0.0
Bumps [jsdoc](https://github.com/jsdoc/jsdoc) from 3.6.11 to 4.0.0.
- [Release notes](https://github.com/jsdoc/jsdoc/releases)
- [Changelog](https://github.com/jsdoc/jsdoc/blob/main/CHANGES.md)
- [Commits](https://github.com/jsdoc/jsdoc/compare/3.6.11...4.0.0)

---
updated-dependencies:
- dependency-name: jsdoc
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-04 13:22:19 +01:00
JC Brand
659a69e7b7 Make sure a moderator can also add contacts...
since they can see real JIDs, even if the room is semi-anonymous.

Also made changes regarding programming style and conventions:

- Pass in `this` to the template
    Recently I've started simplifying the `render` method by just
    passing `this` into the template and letting the template calculate
    what it needs from that.
- Don't use `bind()`
    It's slow and arrow functions can be used instead.
- Don't use an i18n string inside a tagged template literal
    Due to limitations with `xgettext` which cannot parse properly
    inside tagged template literals
- Use snake-case for variables
2022-11-03 10:14:12 +01:00
JC Brand
ec70d4bc56 Classic theme: re-use CSS variable names 2022-11-03 09:53:06 +01:00
Simon Lipp
b0b8a3f89d muc: add a add to contacts button 2022-11-03 09:46:06 +01:00
Simon Lipp
72be204f77 Show nickname in status if fullname is not provided 2022-11-01 14:39:10 +01:00
JC Brand
d5deed0871 Release 10.0.0 2022-10-30 17:03:41 +01:00
JC Brand
040d5bae9d Rename CSS vars to try and get some more consistency 2022-10-30 16:51:15 +01:00
JC Brand
b2ad6e844c Fix chat head buttons not showing
We need to use `converse-icon` now that the fontawesome fonts aren't
included
2022-10-30 16:51:15 +01:00
JC Brand
b4fb710d61 Fix import path 2022-10-30 11:53:15 +01:00
dependabot[bot]
a5be19ad50 Bump dayjs from 1.11.3 to 1.11.6
Bumps [dayjs](https://github.com/iamkun/dayjs) from 1.11.3 to 1.11.6.
- [Release notes](https://github.com/iamkun/dayjs/releases)
- [Changelog](https://github.com/iamkun/dayjs/blob/v1.11.6/CHANGELOG.md)
- [Commits](https://github.com/iamkun/dayjs/compare/v1.11.3...v1.11.6)

---
updated-dependencies:
- dependency-name: dayjs
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-30 10:51:26 +01:00
Allan Nordhøy
6250be89ed Translated using Weblate (Norwegian Bokmål)
Currently translated at 70.3% (365 of 519 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/nb_NO/
2022-10-30 10:50:10 +01:00
Gediminas Murauskas
e355814da7 Translated using Weblate (Lithuanian)
Currently translated at 100.0% (519 of 519 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/lt/
2022-10-30 10:50:10 +01:00
SilvanaFP
1ecffd61af Translated using Weblate (Catalan)
Currently translated at 85.5% (444 of 519 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/ca/
2022-10-30 10:50:10 +01:00
gallegonovato
d887ea4b7b Translated using Weblate (Spanish)
Currently translated at 100.0% (519 of 519 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/es/
2022-10-30 10:50:10 +01:00
Geert van der Meer
b2943351a1 Translated using Weblate (Dutch (Belgium))
Currently translated at 99.2% (515 of 519 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/nl_BE/
2022-10-30 10:50:10 +01:00
Fotios Kolytoumpas
0b514fbc3e Translated using Weblate (Greek)
Currently translated at 38.5% (200 of 519 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/el/
2022-10-30 10:50:10 +01:00
Translator
0d743d428f Translated using Weblate (French)
Currently translated at 100.0% (520 of 520 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/fr/
2022-10-30 10:50:10 +01:00
Geert van der Meer
0b809049e2 Translated using Weblate (Dutch (Belgium))
Currently translated at 90.9% (472 of 519 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/nl_BE/
2022-10-30 10:50:10 +01:00
Artem
8b64482fd4 Translated using Weblate (Ukrainian)
Currently translated at 34.8% (181 of 519 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/uk/
2022-10-30 10:50:10 +01:00
Vincent L
996e47b275 Translated using Weblate (Occitan)
Currently translated at 78.9% (410 of 519 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/oc/
2022-10-30 10:50:10 +01:00
Jaime Marquínez Ferrándiz
c3ff3370bd Translated using Weblate (Spanish)
Currently translated at 94.4% (490 of 519 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/es/
2022-10-30 10:50:10 +01:00
МАН69К
83726f0821 Translated using Weblate (Russian)
Currently translated at 97.8% (508 of 519 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/ru/
2022-10-30 10:50:10 +01:00
WofWca
1ef2c3b3d4 Translated using Weblate (Ukrainian)
Currently translated at 34.8% (181 of 519 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/uk/
2022-10-30 10:50:10 +01:00
random r
0af4b185ac Translated using Weblate (Italian)
Currently translated at 100.0% (519 of 519 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/it/
2022-10-30 10:50:10 +01:00
CreeperXP
a3a90a9be8 Translated using Weblate (Russian)
Currently translated at 97.6% (507 of 519 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/ru/
2022-10-30 10:50:10 +01:00
vitoUwu
7861af7bf9 Translated using Weblate (Portuguese)
Currently translated at 99.6% (517 of 519 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/pt/
2022-10-30 10:50:10 +01:00
dependabot[bot]
e90cf6453e Bump po-loader from 0.6.1 to 0.7.0
Bumps [po-loader](https://github.com/perchlabs/po-loader) from 0.6.1 to 0.7.0.
- [Release notes](https://github.com/perchlabs/po-loader/releases)
- [Commits](https://github.com/perchlabs/po-loader/commits)

---
updated-dependencies:
- dependency-name: po-loader
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-30 10:38:22 +01:00
JC Brand
dbd36a0d75 Ran npm update and manually update to Strophe 1.6.0 2022-10-30 10:10:27 +01:00
JC Brand
c6bc5e1438 Remove sponsor 2022-10-29 07:37:19 +02:00
JC Brand
cc6a20b3e6 Fix MUC icon colors in controlbox
The default icon color is used elsewhere and is sufficient.

The `var(--inverse-link-color)` used previously did not have enough
contrast in the default theme.
2022-10-26 20:57:41 +02:00
JC Brand
40024f4599 Fixes #3028 Encrypted media not properly decrypting
Turns out that older versions Quicksy/Conversations use an IV of 16 bytes although the spec states 12
2022-10-26 09:10:45 +02:00
JC Brand
18d8b69f00 Bugfix. Use https for encrypted media unless hosted via localhost 2022-10-25 14:33:49 +02:00
Keith Maika
62cd0afa37 Save delay for future push.
GCE comes before the frame data.  Save the delay to use in a future call to pushFrame.

Final frame needs to be pushed when EOF is encountered.  Intermediate frames are pushed when a new GCE is encountered.
2022-10-24 12:11:58 +02:00
JC Brand
eb9fd74c77 Provide error message instead of aesm URL
when encrypted media cannot be decrypted because it can't be downloaded.
2022-10-23 11:56:59 +02:00
JC Brand
6c9f0400c8 Fix certain Gifs not loading
https://burtrum.org/up/2529a1fc-29cc-47bf-a7a9-7bc081382c54/winkgrin.gif
2022-10-22 18:30:13 +02:00
Dele Olajide
210d4cb87d Fix #3053
Apply fix for issue #3053 - Using Concord Theme, bookmarks list is difficult to read
2022-10-21 14:48:42 +02:00
Keith Maika
7b6301d7f3 Clear before starting parsing. 2022-10-20 10:20:17 +02:00
JC Brand
63cc8411a5 Run npm update 2022-10-19 10:02:03 +02:00
JC Brand
21c41f9265 Fixes #2939
Data forms with a field named "username" are not displayed #2939
Also adds a test case for ad-hoc commands
Update to Lit 2.4.0
2022-10-19 09:51:20 +02:00
JC Brand
83351fb98f Add test case for adhoc commands 2022-10-18 10:10:13 +02:00
JC Brand
4531dd4363 Move Add-Hoc commands UI code into its own plugin 2022-10-18 09:33:28 +02:00
JC Brand
31b10aa0b0 CSS: add right margin 2022-10-03 14:01:12 +02:00
JC Brand
ef16a52ced Make toggling of rooms list reactive and remove imperative code 2022-10-02 16:04:49 +02:00
JC Brand
1a8ae3dcbe Make roster contacts toggleable 2022-10-02 15:52:01 +02:00
JC Brand
34a4a70ae2 Move bookmarks into a modal 2022-10-01 10:52:08 +02:00
JC Brand
f791169f47 Fixes #3030
* The `confirm` modal didn't show the `title`
* Refactor the new modal code to not automatically show a close button in the footer.
2022-09-30 09:29:49 +02:00
JC Brand
782de0165f Add hover effect to tabs in modal 2022-09-29 14:26:54 +02:00
JC Brand
e555469e3f Move clearSession function to utils 2022-09-29 14:26:54 +02:00
JC Brand
b4eb6c0994 Always enable carbons upon connection or reconnection
Previously we tried to remember whether carbons were enabled before by
saving a flag in the session storage, but apparently this resulted in
false positives and carbons then not being enabled.

With carbons not enabled, clients don't get sent messages.

I don't like the idea of enabling carbons every time the page reloads,
but the alternative is lost messages which is way worse.

I think the issue is that it's not possible to guarantee that the
session is always properly cleared. For example if Converse crashes, and
then the page is reloaded, the session will wrongly indicate that
carbons have been enabled, even though they won't be.
2022-09-29 14:26:54 +02:00
JC Brand
74cda3f4b4 Remove FA font files 2022-09-29 14:09:21 +02:00
JC Brand
aebd98cf0a Stop using font-awesome fonts to render icons
This commit just does the last 1% of work necessary to get rid of font-awesome fonts.

fixes #1004
fixes #2639
2022-09-28 15:11:46 +02:00
JC Brand
983d5ea09c CSS: more tweaks to cut off vertical zalgo text 2022-09-28 12:53:35 +02:00
JC Brand
3720092c09 CSS fix: prevent zalgo text from going out of vertical bounds
(previous commit didn't work properly it seems)
2022-09-28 11:15:39 +02:00
JC Brand
36cb7a644e CSS fix: prevent zalgo text from going out of vertical bounds 2022-09-28 11:01:36 +02:00
JC Brand
6293efd8ee Avoid double wrapping with anchor tag and tweak unfurl CSS
to make it smaller on large screens.
2022-09-27 14:31:19 +02:00
JC Brand
5760379e0a Only send out ping if we're actually authenticated
Fixes #2562
2022-09-20 15:01:55 +02:00
JC Brand
a4ee3085b7 MUC: Don't ping when we're not connected
Instead, wait for the `reconnection` event and then ping.
2022-09-20 15:01:51 +02:00
JC Brand
bd60861c1e Don't import plugins' index.js file from other plugins
Importing a plugin's `index.js` file from other plugins means that it's no
longer possible to remove that plugin by removing it from `src/converse.js`.

Instead, all plugins need to be imported in proper order from
`src/headless/headless.js` and `src/converse.js`.

Updates #3026
2022-09-20 14:48:20 +02:00
JC Brand
fbe86e5af8 Create an ElementView base modal and use it for all modals
Modals are now all web components and are opened by component name.
2022-09-16 10:33:47 +02:00
JC Brand
927add0707 Wrap requestUpdate in an arrow function
Otherwise parameters from the event handler might be passed in to it,
causing potential weirdness.
2022-09-16 10:26:21 +02:00
JC Brand
8378ce739b Remove unfurls for hyperlinks removed in a message correction 2022-09-12 10:05:54 +02:00
JC Brand
f9e6c3ff95 Fix groups auto-complete for add-contact modal 2022-09-12 09:28:37 +02:00
JC Brand
98ae55790d Add a list property to the converse-autocomplete component
This can be used instead of the `getAutoCompleteList` function and
avoids unnecessary computation.
2022-09-10 15:20:05 +02:00
JC Brand
bb0ad432b2 Move add-contact modal to the rosterview plugin 2022-09-10 14:46:32 +02:00
JC Brand
55e3417df3 Move user settings modal to profile plugin 2022-09-10 14:37:01 +02:00
Keith Maika
92f71bafb2 Fix muc icons not working due to incorrect target element. 2022-09-08 11:21:53 +02:00
JC Brand
f1734dbb40 Bugfix. Trim whitespace after JID 2022-09-06 13:45:30 +02:00
JC Brand
0489e0f902 Remove unused function 2022-09-01 17:28:29 +02:00
JC Brand
0aa66fee99 CSS Fixes.
- Remove max height for MUC heading, otherwise subject text can get cut off
- Fix offset in mobile due to the background image
2022-08-27 16:40:13 +02:00
JC Brand
ed1099490c Fix bug where auto-complete list would jump to top 2022-08-26 23:19:08 +02:00
JC Brand
a74bbd093f Improve rendering of add-muc autocomplete suggestions 2022-08-26 22:58:46 +02:00
JC Brand
8ae4b6abd4 MUC: Set occupant ID from reflected message 2022-08-21 17:33:35 +02:00
JC Brand
ca3c8fc10b Fixes #3007
Bugfix: Links in message become text when the message is edited
2022-08-20 11:12:59 +02:00
JC Brand
e8b9681a15 MAM: Always query for newest MAM messages after cached ones have been fetched
The `_converse.connection.restored` check ensured that 1:1 chats
manually opened after tab reload would never get their MAM messages
fetched 🤦
2022-08-17 13:53:31 +02:00
JC Brand
51516e38f6 Remove duplicate trigger of afterMessagesFetched 2022-08-17 13:38:57 +02:00
JC Brand
de72d6bae3 MUC: Move constants to separate file 2022-08-17 12:53:41 +02:00
JC Brand
0d9561e666 MUC: When closing, only send read marker if we were entered
When using RAI, it's possible to close a MUC without it being entered.
2022-08-17 12:49:44 +02:00
JC Brand
97be0bd8ac Styling: Use zero-width space and maintain position of newline char
Fixes #2879
2022-08-15 15:56:15 +02:00
Debanjana Sarkar
7f99b24e28 Fix for #2870 2022-08-15 15:54:29 +02:00
Keith Maika
17e5804be7 Select the immediate body, not the one in fallback. 2022-08-13 10:00:40 +02:00
JC Brand
fd9e41a917 Fix failing test.
The fix from @joudinet was to call `this.items.create` on `DiscoEntity`,
however we still need to pass in the same `entity` model as before so that both
collections (`this.items` and `_converse.disco_entities`) have a
referene to the same model.

That way, when attributes like `.identities` are added on the entity,
it's available from both `this.items` and `_converse.disco_entities`.
2022-08-12 10:27:09 +02:00
Johan Oudinet
760f4f7dd1 Fix missing disco-items in session storage
This should fix #2925.
2022-08-12 10:07:12 +02:00
JC Brand
5231262bda Take from_real_jid into account when determining sender
of MUC messages.

This is safer than simply checking nicknames when the XEP-0421 occupant-id is not
available.
2022-08-12 09:43:49 +02:00
JC Brand
34927b5b77 Use occupant_id to get own occupant O(1) if available 2022-08-12 09:21:01 +02:00
JC Brand
7028286855 Restrict editing of MUC messages...
to ones with the same XEP-0421 occupant ID
2022-08-11 22:44:11 +02:00
JC Brand
342c75775b Save the user's XEP-0421 occupant ID on the ChatRoom 2022-08-11 15:47:09 +02:00
JC Brand
f1cc8c85f4 Rename the stanza TTL to stx to avoid name clashes 2022-08-11 15:30:51 +02:00
JC Brand
c5588e3c49 MUC: Features are fetched in join
due to the `await this.refreshDiscoInfo()` call in `join`.

So should be safe to remove the check whether features were fetched.
2022-08-11 15:12:55 +02:00
JC Brand
3d19def3e7 Wait for emojis to be initialized before sending a message 2022-08-11 14:31:28 +02:00
JC Brand
53521c2236 Import utilty function directly and use optional chaining 2022-08-11 10:42:00 +02:00
JC Brand
22170450b4 Stop using zipObject from lodash 2022-08-11 10:30:07 +02:00
JC Brand
f014db8b7a Update nick attr on ChatRoom when user nick changes 2022-08-11 10:23:16 +02:00
JC Brand
fe9345b7fc MUC: only allow corrections with a matching sender occupant-id
Also, don't render messages from a sender with a different `occupant-id`
as a followup message.
2022-08-10 14:53:18 +02:00
JC Brand
d2bdce51e8 Add a tagged template literal function stanza
For creating XML stanzas from template literals.
2022-08-10 14:50:12 +02:00
JC Brand
cac92c3ebc Bump copy-webpack-plugin to 11.0.0 2022-08-09 13:33:12 +02:00
JC Brand
603f8349e8 Bump eslint and use @babel/eslint-parser
Also had to add a `babel.config.js` for it to work
2022-08-09 11:56:00 +02:00
JC Brand
5f6e70289b Run npm update to update headless deps 2022-08-09 11:06:44 +02:00
JC Brand
c716551fc8 Update postcss-loader to version 7.0.1 2022-08-09 11:00:38 +02:00
JC Brand
78634cdec3 Update deps with npm update and then run make dev 2022-08-09 10:48:36 +02:00
JC Brand
45e989f048 Move converse-oauth to the community-plugins repo 2022-08-09 10:42:33 +02:00
JC Brand
0cfe2a18af Apply eslint to all JS files in src/ 2022-07-26 21:39:50 +02:00
JC Brand
71d1383604 Move code that sets active flag on session to initSession
It doesn't belong in the `converse-status` plugin and the event handler
doesn't get registered when all CSI-related timeouts are set to 0.
2022-07-25 11:59:25 +02:00
JC Brand
0df1c1880e Bump dayjs in package-lock.json 2022-07-20 09:03:03 +02:00
dependabot[bot]
06a2aac022 Bump dayjs from 1.11.1 to 1.11.3
Bumps [dayjs](https://github.com/iamkun/dayjs) from 1.11.1 to 1.11.3.
- [Release notes](https://github.com/iamkun/dayjs/releases)
- [Changelog](https://github.com/iamkun/dayjs/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/iamkun/dayjs/compare/v1.11.1...v1.11.3)

---
updated-dependencies:
- dependency-name: dayjs
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-19 15:35:30 +02:00
JC Brand
d8ea42a845 Add XEP-372 URI as data attribute to mention element 2022-07-19 11:59:55 +02:00
JC Brand
085de8405f Bump Lerna to 5.1.8 2022-07-19 10:47:23 +02:00
JC Brand
990aefc6cb docs: Discourage usage of overrides and add hook to example plugin 2022-07-19 10:35:45 +02:00
JC Brand
eb29d962f5 Bugfix. Don't try to look up occupant via MUC JID
Also set function as class method
2022-07-18 16:19:02 +02:00
JC Brand
605c02901a Fix yet more tests 2022-07-14 21:17:32 +02:00
JC Brand
368bcf258f Fix failing tests 2022-07-14 20:40:58 +02:00
JC Brand
07efd601da Use the native crypto library for SHA-1
instead of the one from Strophe
2022-07-14 20:34:15 +02:00
JC Brand
4aab83c4af Remove unused method 2022-07-14 08:47:39 +02:00
JC Brand
f05a41f6a5 Ran npm update 2022-07-12 09:14:25 +02:00
JC Brand
4d9c0d3f9a Also check for body 2022-07-12 09:05:28 +02:00
Licaon_Kter
35bdcf58cd Another typo 2022-07-12 07:45:02 +02:00
Licaon_Kter
3ca478da32 Contributing typos 2022-07-09 23:14:14 +02:00
JC Brand
5d3da20bd9 Remove/update old comments 2022-07-03 13:36:15 +02:00
JC Brand
a95c070c2b Set autoprefixer version to fix compilation error 2022-06-22 14:05:03 +02:00
JC Brand
c14c2b3b59 Carbons: check for server support before enabling 2022-06-20 22:44:23 +02:00
JC Brand
b7e793df02 Bump 3rd party dependencies 2022-06-20 21:05:27 +02:00
Johan Oudinet
c245599e65 docs: enable_smacks is set to true by default since v6.0.0
Fix #2936.
2022-06-20 20:57:45 +02:00
Johan Oudinet
7e86c561c7 CHANGES.md: fix typo in 6.0.0 changes 2022-06-20 20:57:45 +02:00
JC Brand
25891ef0ee findOccupant: Don't fall back to nick/jid search...
if the occupant can't be found via XEP-0421 occupant id.

We cannot safely assume that an occupant found via nick/jid but without
the same occupant id is the same occupant.
2022-06-20 14:33:44 +02:00
JC Brand
ba7c6d7a50 Let HeadlinesHeading use CustomElement 2022-06-19 13:03:06 +02:00
JC Brand
7e2dd55c16 Use api.elements.define 2022-06-19 12:12:09 +02:00
JC Brand
b8579ccc90 Explicitly add po2json as dependency and fix package-lock version 2022-06-16 15:33:43 +02:00
JC Brand
73a7b209ce Add meta tag which prompts IE users to upgrade
https://docs.microsoft.com/en-us/openspecs/ie_standards/ms-iedoco/380e2488-f5eb-4457-a07a-0cb1b6e4b4b5
2022-06-15 17:48:11 +02:00
JC Brand
8dc8b1d564 Insert only the MUC JID when clicking an auto-complete suggestion 2022-06-12 10:25:41 +02:00
JC Brand
d2b4f2e0f6 MUC search: no need to first fetch the form 2022-06-12 09:59:50 +02:00
JC Brand
320f11f795 Use XMPP to search for MUCs via search.jabber.network
Also refactor AutoComplete somewhat to not compute `this._list` too
eagerly and to also pass the query string to `this._list`.
2022-06-11 23:43:43 +02:00
JC Brand
4237e5b3ae Style the add-muc modal autocomplete
- Let it drop down to the bottom
- Add a border
- Let it scroll
2022-06-11 23:42:47 +02:00
JC Brand
8671afc4b1 Document converse-autocomplete and always add closing tag
Weird parsing issues happen when a closing tag is not present.
2022-06-11 23:42:47 +02:00
JC Brand
6d39fae71a Remove Buildout and just use pip to genrate the Sphinx docs 2022-06-11 23:42:47 +02:00
JC Brand
0316f073e0 Replace font icons with svg icons 2022-06-11 23:42:47 +02:00
JC Brand
1744dbc420 Move roomslist tests to the right plugin 2022-06-11 23:42:47 +02:00
JC Brand
eb8ebea920 Move bookmarks list tests into separate file 2022-06-11 23:42:47 +02:00
badlop
6c13cfaf30 Add ejabberd and add XMPP servers homepages 2022-06-11 23:40:46 +02:00
Guus der Kinderen
a228cf244c Add references to libsignal setup to features page 2022-06-08 11:33:56 +02:00
Guus der Kinderen
3b124cfdce Fix 'Edit me on GitHub' links 2022-06-08 11:33:56 +02:00
JC Brand
4c8bc187b2 Allow autofocus to be set on an autocomplete input 2022-06-01 22:04:43 +02:00
Sanskar Bajpai
1ad6de2dd6 AutoComplete: added converse-autocomplete suggestion to group chat query
this commit introduces autocomplete feature to the muc-list group chat dialog,
previously there was only an input field which displayed hardcoded servers.
2022-05-24 17:31:24 +02:00
Sanskar Bajpai
795a9a7e3e add-modal-test: replaced a mistyped jid 2022-05-24 17:04:38 +02:00
Daniel Brötzmann
87ecf061f1 DOAP: Add logo and os/platform 2022-05-24 09:49:16 +02:00
JC Brand
858a6051ac Refactoring of the headlines plugins
- Move template to relevant plugin
- Turn ElementView into CustomElement
- Use the terminology "Headlines Feed" instead of "Headlines Box"
- Break the `converse-headlines` plugin up into multiple files
- Fix CSS styling for headlines feeds for the Dracula theme
2022-05-13 16:49:45 +02:00
eapo
52693bfc0b Translated using Weblate (Hungarian)
Currently translated at 95.1% (494 of 519 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/hu/
2022-05-13 10:50:39 +02:00
HAMANO Tsukasa
79063b9993 Translated using Weblate (Japanese)
Currently translated at 100.0% (519 of 519 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/ja/
2022-05-13 10:50:39 +02:00
HAMANO Tsukasa
22840f8a50 Translated using Weblate (Japanese)
Currently translated at 100.0% (519 of 519 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/ja/
2022-05-13 10:50:39 +02:00
HAMANO Tsukasa
92f74b888b Translated using Weblate (Japanese)
Currently translated at 100.0% (519 of 519 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/ja/
2022-05-13 10:50:39 +02:00
Emmanuel Gil Peyrot
ac241e5ed1 Translated using Weblate (French)
Currently translated at 99.8% (519 of 520 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/fr/
2022-05-13 10:50:39 +02:00
JC Brand
6573d080e4 Message carbons
- Remove the `converse-carbons` plugin and make carbons part of the `converse-chat` plugin.
- Remove the `message_carbons` configuration setting. Carbons are now always enabled.
2022-05-13 10:32:54 +02:00
JC Brand
12a0d0e3cc Show roster contacts with subscription set to none
Remove the `allow_chat_pending_contacts` config option.
2022-05-13 10:19:52 +02:00
JC Brand
2a7bfd13b5 Add ability to specify group when adding contact 2022-05-13 10:18:22 +02:00
JC Brand
ab7e879261 Don't automatically convert OpenStreetMap URLs into geo: URIs in sent messages
Updates #1850 and #2914
2022-05-13 10:14:31 +02:00
JC Brand
a57853156e Use our own confirm dialog consistently 2022-05-12 23:23:24 +02:00
JC Brand
a3c0f90476 Don't use browser's confirm dialog when logging out
Refs https://github.com/conversejs/converse-desktop/issues/18
2022-05-11 09:13:17 +02:00
JC Brand
b5bcc05947 Create generatePreKeys function 2022-05-08 23:37:47 +02:00
HAMANO Tsukasa
bd579d8613 remove unnecessary } 2022-05-08 22:46:57 +02:00
JC Brand
0c02fbe4cf Add entry point for devserver 2022-05-08 22:41:24 +02:00
JC Brand
0b172be3d0 Update development docs and add theming info 2022-05-07 23:03:04 +02:00
Eric
7e9861ba8f Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (417 of 417 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/zh_Hans/
2022-05-06 13:10:00 +02:00
Emmanuel Gil Peyrot
0c9fd691ac Translated using Weblate (French)
Currently translated at 100.0% (417 of 417 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/fr/
2022-05-06 13:09:39 +02:00
JC Brand
984386aa64 Bugfix. Add missing translations
Some translations were erroneously removed due to the nodeps build
contained string literals.
2022-05-06 13:02:03 +02:00
JC Brand
ae2bd63d8f Release 9.1.1 2022-05-05 21:33:31 +02:00
Иван Иванович
5e27e27845 Translated using Weblate (Russian)
Currently translated at 96.5% (501 of 519 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/ru/
2022-05-05 20:57:59 +02:00
Yoandry González Castro
ca9d68b99e Translated using Weblate (Spanish)
Currently translated at 90.5% (470 of 519 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/es/
2022-05-05 20:57:59 +02:00
JC Brand
99c5d7a760 Fix failing test 2022-05-05 07:57:33 +02:00
JC Brand
4b6626ee70 Improve and simplify the webpack builds
I've now also figured out why loading of chunks failed when running
using converse.js (but not when using converse.min.js or when running `make watch`).

When running `make dist`, first `converse.js` and `converse.min.js` were
built with `mode` set to `development` (via `webpack.dev.js`) and then
`converse.min.js` was again built with mode set to `production` (via
`webpack.prod.js`).

When running only one build or the other (either `webpack.dev.js` or
`webpack.prod.js`) then the loading of chunks didn't fail, so it had
something to do with running both builds back to back.

I've now removed the `.dev.js` webpack config files and instead build
the minimized and non-minimized from the same config file
`webpack.build.js`.

I did the same for the headless builds.
2022-05-05 07:28:44 +02:00
JC Brand
8ea9e8a5ad Update to po-loader 0.6.1 2022-05-04 21:54:51 +02:00
JC Brand
f929f8b7f9 Bugfix. Chunks not loading when using converse.js build
(Although they do load when using converse.min.js)

I wasn't able to figure out why exactly, but setting `mode` to
`production` for the `converse.js` build solved the issue.
2022-05-04 21:54:51 +02:00
JC Brand
ad8c250314 Fix loading of fonts
No need to use `file-loader` anymore, using the built-in resource loading.
2022-05-04 21:54:51 +02:00
JC Brand
02146bdf22 Fixes #2906
Bump po-loader to a commit that includes the latest po2json
2022-05-04 14:37:58 +02:00
Eric
dbc0028880 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (519 of 519 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/zh_Hans/
2022-05-02 09:48:25 +02:00
Oğuz Ersen
f27238b76f Translated using Weblate (Turkish)
Currently translated at 100.0% (519 of 519 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/tr/
2022-05-02 09:48:25 +02:00
Xosé M
5adc39ebac Translated using Weblate (Galician)
Currently translated at 100.0% (519 of 519 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/gl/
2022-05-02 09:48:25 +02:00
nautilusx
53ccc4948f Translated using Weblate (German)
Currently translated at 100.0% (519 of 519 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/de/
2022-05-02 09:48:25 +02:00
JC Brand
e48bd0dd4b Remove Issuehunt from funding, looks dead 2022-04-30 19:45:45 +02:00
JC Brand
cb6fc463aa
Add Issuehunt to funding 2022-04-30 18:53:44 +02:00
JC Brand
3b4ef074b9
Add changelog entry for #1130
Fixes #1130
2022-04-30 13:21:55 +02:00
JC Brand
a3b5c58023 Bump autoprefixer to 10.4.5 2022-04-29 00:13:20 +02:00
JC Brand
1f7fe4f48e Upgrade to Strophe 1.5.0 and upgrade various other dependencies
Had to add `src/strophe-shims.js` as a webpack alias to the shims.js
file in Strophe because the usage of `require` to load Node.js packags
in shims.js is causing problems with Webpack 5.

Set postcss-clean to 1.2.0 to fix the build error `node.getIterator() is
not a function`

Upgrade to latest Webpack
2022-04-28 23:53:31 +02:00
JC Brand
e03d7bc71c Mention Ejabberd's Converse module 2022-04-28 16:08:08 +02:00
JC Brand
828b6785b4 Bump babel-loader, karma-jasmine and webpack-dev-server 2022-04-26 21:39:52 +02:00
JC Brand
e06d335b7d Bump dependencies
Bump `http-server`, `@babel/core`, `clean-css-cli`, `karma-chrome-launcher` and `sass`
2022-04-26 21:25:59 +02:00
JC Brand
55d02cb37b Update headless package-lock.json 2022-04-26 21:09:16 +02:00
JC Brand
8e612e3cd9 Bump lit, karma, prettierx and localforage-webextensionstorage-driver 2022-04-26 21:05:14 +02:00
JC Brand
0af72d41da Fix button hover color 2022-04-26 20:45:37 +02:00
JC Brand
ebd9474ac1 Add more ways to get VCard for occupant modal 2022-04-26 20:41:04 +02:00
JC Brand
2172409fec Set from_real_jid on the message when its occupant is attached. 2022-04-26 20:38:20 +02:00
JC Brand
d22c063ae5 Make sure that the occupant_id is also the id for occupants
insofar we have an `occupant_id`.

We do this by subclassing `create` on the `ChatRoomOccupants` collection
and `save` on the `ChatRoomOccupant` model, to make sure that whenever
an occupant is created or saved, that the `id` matches the `occupant_id`
value if it's available.

This lets us look up the occupant via `occupant_id` via dictionary lookup,
instead of array traversal.

Another change is to save `from_real_jid` when adding an occupant to a message
2022-04-26 20:38:20 +02:00
JC Brand
b71a7ae2ac Turn ChatRoomOccupants and ChatRoomOccupant into classes 2022-04-26 20:33:54 +02:00
JC Brand
6c26c1397f Update dayjs to 1.11.1 2022-04-26 14:21:47 +02:00
JC Brand
a31f87f25b Add documentation on writing hooks 2022-04-26 12:44:31 +02:00
JC Brand
18ca225450 Update Sass and sass-loader 2022-04-25 16:24:06 +02:00
JC Brand
fe10f2203b Bump minimist, mini-css-extract-plugin and css-loader 2022-04-25 13:40:13 +02:00
JC Brand
3c2eda4a1d Better documentation for getHeadingButtons 2022-04-25 09:58:27 +02:00
JC Brand
0a07cad2cb Move connection api into separate file 2022-04-25 09:48:08 +02:00
JC Brand
f93b30f7b3 Show spinner in controlbox when reconnecting 2022-04-24 11:18:09 +02:00
JC Brand
35b2c247f3 Remove po2json as explicit dep. Fixes build issue 2022-04-23 12:57:41 +02:00
JC Brand
1915d70c41 Turn controlbox into a Lit element 2022-04-23 12:01:41 +02:00
JC Brand
059795c0f3 No need to log cache misses 2022-04-22 10:06:08 +02:00
JC Brand
0260e5f803 Fix infinite loop in service discovery
When there is a circular dependency between disco entities (via their
advertised `disco#items`), Converse went into an infinite loop because
even though there was a check whether an entity already existed, it
failed to add newly created entities to the global
`_converse.disco_entities` collection.
2022-04-22 09:39:47 +02:00
Allan Nordhøy
1b60697565 Translated using Weblate (Norwegian Bokmål)
Currently translated at 70.9% (362 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/nb_NO/
2022-04-20 13:47:22 +02:00
JC Brand
fb158e418b Show number of participants in sidebar 2022-04-20 09:59:57 +02:00
JC Brand
995cc51f99 Fix failing SMACKS test 2022-04-20 09:52:17 +02:00
JC Brand
760fa4ae63 Send out carbon IQ after stream resumption 2022-04-20 09:52:17 +02:00
JC Brand
d4382fda19 OMEMO bugfix. Don't auto-create device list without JID 2022-04-20 09:52:17 +02:00
JC Brand
4c394c072e Don't wait for vcards before initializing the roster 2022-04-20 09:52:17 +02:00
JC Brand
699326547a Show MUC avatar 2022-04-20 09:52:17 +02:00
JC Brand
2a9a01bc32 Fix flashing of bookmarks on page load 2022-04-19 22:52:33 +02:00
JC Brand
ce22508344 Turn bookmarks list into a Lit component 2022-04-19 21:08:52 +02:00
JC Brand
230b72139a Set jid as id attribute for vcards, presence and roster contacts
This allows models to be retrieved from a dict instead of via array
traversal.
2022-04-19 09:28:06 +02:00
JC Brand
0b168e8439 Use listenTo 2022-04-16 14:25:39 +02:00
JC Brand
e492885ac0 Set jid as the id attribute of the VCards collection
This reduces lookup time for vcards greatly, since we don't can access a
map of ids instead of using `findWhere` through an array of models.
2022-04-16 00:15:27 +02:00
SilverYoCha
7cb86638b5 Fixing display problems with chatbox view with mobile view mode 2022-04-15 06:48:25 +02:00
JC Brand
2d5b0753e2 Remove local contacts not returned from a full roster response 2022-04-14 11:29:28 +02:00
JC Brand
8e1c3e47df Improve how the muc_domain setting is populated via disco
Remove brittle code that uses `querySelector` to get the rooms list model.
This code was causing a TypeError due to a race condition.
2022-04-09 10:57:55 +02:00
JC Brand
99ae9a9850 Update webpack-copy-plugin 2022-04-09 09:13:05 +02:00
JC Brand
7b31f4d333 Remove allow_muc setting 2022-04-09 09:11:54 +02:00
JC Brand
8930201b99 Fixes #2746
Update to latest Strophe which adds a fallback handler for unhandled incoming "get" and "set" IQs.
2022-04-08 22:17:01 +02:00
JC Brand
ad11dce92f Call safeSave to avoid error when MUC is not yet persistable 2022-04-08 12:19:05 +02:00
JC Brand
0c049dd364 Resolve fetched promise when clearing messages
This fixes an issue where chats stay empty after reconnection when
`clear_messages_on_reconnection` is `true`.
2022-04-08 11:22:21 +02:00
JC Brand
ca0953e4bd Bump urijs, skeletor and localforage-getitems 2022-04-08 11:22:15 +02:00
JC Brand
a17e8bea1c Only warn when getting an error in safeDestroy 2022-04-08 10:58:06 +02:00
SilverYoCha
b331405658 Bugfix: selected emoji inserted into all open chat boxes
when in overlay view mode.
2022-04-08 08:21:19 +02:00
JC Brand
c3e3f89e52 Update CONTRIBUTING 2022-04-07 14:21:51 +02:00
JC Brand
f0297fe075 Add status and show elements to MUC join presence in status plugin
and not in the muc plugin.

This decouples the plugins more. Ideally we can remove the status plugin
entirely from a customized Converse build (but we're not there yet).
2022-04-07 11:08:00 +02:00
JC Brand
4d4e0ffc8d Bump minimist to 1.2.6 2022-04-06 23:30:48 +02:00
badlop
e202ac9964 Add "dracula" to the "theme" option documentation 2022-04-06 23:20:33 +02:00
ubermanu
5c5825fb75 Add missing headless dependencies 2022-04-06 23:16:09 +02:00
ubermanu
e0e1fd4f02 Update lock file with root node version (16.3) 2022-04-06 23:10:13 +02:00
ubermanu
5e4fa98577 Add subdir to repo information 2022-04-06 23:10:13 +02:00
ubermanu
7e18873bcd Target to converse default export 2022-04-06 23:10:13 +02:00
ubermanu
592d982210 Include all headless files except tests 2022-04-06 23:10:13 +02:00
JC Brand
9d4382c754 Move emoji functions to utils.js
Also, move various emoji utility methods out of @converse/headless, and
thereby remove the dependency on lit-html
2022-04-06 23:07:16 +02:00
JC Brand
b1a448f1e9 Update OMEMO documentation 2022-04-06 10:10:41 +02:00
JC Brand
af342456c5 Add enterkeyhint attribute to message form inputs 2022-04-06 09:55:56 +02:00
JC Brand
5d3895078b Use the loading HTML attr to lazily load images 2022-04-06 08:33:23 +02:00
JC Brand
0464381cac Bump node-forge 2022-04-05 11:33:57 +02:00
JC Brand
32a443408a Bugfix. GIF unfurl images not loading...
and causing `TypeError: this.shouldRenderMedia is not a function`
2022-04-04 16:31:32 +02:00
JC Brand
b429484501 Move csi_waiting_time setting to the converse-status plugin 2022-04-04 15:03:57 +02:00
JC Brand
2fa1d00fb4 Postrelease
- Pull first before installing node via nvm
2022-04-02 20:39:42 +02:00
JC Brand
c590c4f4bb Updated to latest Sphinx version 2022-04-02 20:32:34 +02:00
JC Brand
6b1845ff39 Release 9.1.0 2022-04-02 19:31:37 +02:00
JC Brand
fb704fdf87 Don't import from i18n in headless 2022-04-02 15:55:56 +02:00
Ricky Tigg
f6a985c24f Translated using Weblate (Finnish)
Currently translated at 83.5% (426 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/fi/
2022-04-01 15:51:52 +02:00
Edward
44cd910154 Translated using Weblate (Romanian)
Currently translated at 45.0% (230 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/ro/
2022-04-01 15:51:52 +02:00
Γκουλιούμης Θεόδωρος
f21fc90629 Translated using Weblate (Greek)
Currently translated at 0.3% (2 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/el/
2022-04-01 15:51:52 +02:00
Hasan
21fb57ecfd
Translated using Weblate (Turkish)
Currently translated at 100.0% (510 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/tr/
2022-03-31 09:33:27 +02:00
Xosé M
3bb645ce24
Translated using Weblate (Galician)
Currently translated at 100.0% (510 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/gl/
2022-03-31 09:33:27 +02:00
JC Brand
fd991846f4 Replace ElementView with CustomElement for RoomsList 2022-03-30 09:50:36 +02:00
JC Brand
523566c218 Move MUC tests into their own files 2022-03-30 09:48:39 +02:00
JC Brand
cd1c6a4d23 Update the style guide 2022-03-29 22:55:48 +02:00
JC Brand
c3933426b9 Refactor checkFileTypes
- Don't check the protocol in `checkFileTypes`, it should be doing one
    thing only, and that is check whether the URL ends with a particular
    file extension.
- Raise an error when a URI object can't be created from the passed in URL

Adds new function `isAllowedProtocolForMedia` which checks whether the
URL points to a file on the file system (`file:`), is in a Chrome
extension or uses HTTPs.

Use that in `shouldRenderMediaFromURL` to filter out URLs that shouldn't
be rendered.

Re-add utility methods to the `u` object so that 3rd party plugins can
use them.
2022-03-29 19:41:16 +02:00
Keith Maika
be561addfa Fix endless loop of adding .png to image URL. 2022-03-29 19:08:39 +02:00
JC Brand
c379fe80fb Handle 'forbidden' MUC errors with type 'cancel' and add fallthrough 2022-03-29 10:36:32 +02:00
JC Brand
5ef0f3ad5d CSS: various color fixes between light/dark themes 2022-03-29 10:35:25 +02:00
JC Brand
d570b6095e Don't make the connection URL input required
It might be that it's shown in response to a failed XEP-156 lookup
because the user mistyped.

In which case the user can just correct the JID and try again, without
entering a connection URL.
2022-03-25 08:54:38 +01:00
JC Brand
fca275b7c9 Refactor the login form
Render the form based on `api.settings` instead of its own model.

When the login form is submitted, save the JID, password and connection
URL to `api.settings`.

Set the `service` on the Strophe connection object just before
connecting for the first time, otherwise a user supplied URL (via the
login form) is never used.

New API setting: show_connection_url_input
2022-03-24 23:15:30 +01:00
JC Brand
e160ee2ed5 Add JID and password values to login form (if available) 2022-03-24 21:05:40 +01:00
JC Brand
70aa22d12d Update to latest LTS version of NodeJS 2022-03-23 22:14:19 +01:00
JC Brand
fbfd6c3ac4 Updates #2849: add test for incoming MUC OMEMO corrections 2022-03-23 21:30:53 +01:00
JC Brand
7355c2c5fe Updates #2849
Add test case for incoming OMEMO message corrections.

The correction was being ignored because the parsed `msgid` of an
incoming correction was set to the `msgid` of the message being
replaced.
2022-03-22 23:12:45 +01:00
JC Brand
297869c59f Don't explicitly sort messages.
Apparently not necessary, I was wrong about the race condition in 82fb263438
2022-03-15 21:24:32 +01:00
JC Brand
defea1631c Bugfix. Don't ignore groupchat messages that contain receipt requests 2022-03-15 11:35:15 +01:00
JC Brand
82fb263438 Explicitly sort messages before pruning
to avoid a race-condition where messages aren't sorted and the wrong
message gets pruned.
2022-03-14 21:19:43 +01:00
JC Brand
d2b9c954d9 MUC: move some tests to headless plugin 2022-03-14 20:35:01 +01:00
JC Brand
f9a9d327d1 Use body as attribute for the message body text
For error messages we still use the `message` attribute, since error
messages generally don't have a body, and if one does, it likely refers
to the `body` of a rejected message that the error refers to.

We're still setting both `body` and `message` attributes, but usage of
`message` for a normal `chat`, `groupchat` or `headline` stanza should
be considered deprecated.
2022-03-14 09:28:34 +01:00
JC Brand
d2622f6fed Fixes #2557
Add the ability to send OMEMO corrections.

Refactor how OMEMO messages are sent to avoid having to override
`sendMessage` and thereby also allowing corrections of OMEMO messages to
be sent out.

Add two new hooks.
- getOutgoingMessageAttributes
- createMessageStanza
2022-03-13 10:02:34 +01:00
JC Brand
731e98b07c OMEMO fixes for completely new user
Fix bugs related to there not being a server-side device list (not even an empty one) for a new user.
2022-03-13 10:02:34 +01:00
JC Brand
89a3c81a19 OMEMO: don't wait for all device lists...
to be fetched from the server before triggering OMEMOInitialized.

For some contacts, the IQ to fetch the device list never receives a
response. IQ stanzas take 20 seconds to timeout, which means that all
OMEMO operations are blocked for 20 seconds (because everything waits
for `OMEMOInitialized`).

Create a new API method `api.omemo.devicelists.get` and use that to
fetch and `await` for any devicelist. That way we lazily wait for
devicelists to be fetched from the server and can continue with other
OMEMO operations unrelated to users who's clients don't respond to
devicelist queries.
2022-03-10 20:51:04 +01:00
JC Brand
2133241998 CSS: Fix chat title width and elipsis color
in overlayed view mode.
2022-03-10 20:51:04 +01:00
JC Brand
47b016599e Stop using this in tests.
It will be unsupported in future versions of Jasmine
2022-03-09 12:44:49 +01:00
JC Brand
e52056bb33 Refactor the emoji-picker somewhat
Trigger an `emojiSelected` event instead of manually calling `insertIntoTextArea` on the `converse-message-form` a component.
This loosens the coupling between the emoji picker and `converse-message-form`.

Call `disableArrowNavigation` when the emoji-picker is disconnected from
the DOM or when escape is pressed. See #2754
2022-03-09 12:44:33 +01:00
JC Brand
1c0ce25f12 Move keycodes and chat states to constants.js 2022-03-09 12:22:44 +01:00
JC Brand
c42bd90c9d Don't clear textarea on escape, unless we're correcting a message 2022-03-09 11:24:32 +01:00
SilverYoCha
7409668a5d Fixes #2754 2022-03-08 16:40:26 +01:00
JC Brand
d432bab73a Remove and recreate lockfiles
To see if that fixes Github Actions CI
2022-02-28 13:34:40 +01:00
JC Brand
9328db645d Update to latest Skeletor
So that we can use the `getAll` IndexedDB method to fetch multiple
entries at once. Should result in a significant speedup.
2022-02-28 10:37:58 +01:00
JC Brand
21d3159081 Replace TravisCI badge with Github Actions badge 2022-02-24 06:19:52 +01:00
JC Brand
b7ad1eaade Fix failing tests 2022-02-22 11:44:53 +01:00
JC Brand
727bad01c7 Don't send <show>online</show> joining a MUC 2022-02-22 11:30:38 +01:00
JC Brand
b248803a4b Fixes #2822 2022-02-20 19:17:52 +01:00
JC Brand
a468a0fb24 Don't load Converse in the docs 2022-02-20 18:45:21 +01:00
JC Brand
c2ba8ecf97 Upgrade Python dependencies
Allows for docs to be built on Python3.9
2022-02-20 18:45:21 +01:00
JC Brand
7b63b7b30f Make various error messages ephemeral.
Also make it possible to specify the timeout for an ephemeral message.
2022-02-19 23:11:22 +01:00
JC Brand
ca20f687bf minimize: initialize chat via event instead of override 2022-02-19 23:10:17 +01:00
JC Brand
bbef09346a Various CSS fixes and use converse-icon for nav button 2022-02-19 23:09:39 +01:00
JC Brand
1c8085f00e CSS: Set modal header color for error alerts
Also fix various element colors for Dracula theme
2022-02-19 21:32:25 +01:00
JC Brand
beb220f188 Updates #2781
Only send presence status update when a MUC is entered, and when joining
a MUC, include the `<show>` element.
2022-02-18 10:55:20 +01:00
JC Brand
20cd90855f Dracula theme: Set correcting color 2022-02-16 10:14:53 +01:00
JC Brand
39e9ed8fe4 Updates #2733
Rather use `false` for a bool
2022-02-15 14:48:01 +01:00
JC Brand
22a7e1b35f Updates #2733
Set `is_error` to back to undefined
2022-02-15 14:46:00 +01:00
JC Brand
9a95c2d048 Normalize URL path
Udates #2814

Otherwise `"` gets escaped as `&quot;` by lit-html which is not correct.
2022-02-15 14:38:40 +01:00
JC Brand
9a2424fa26 Fixes #2814. Links are mangled on open/copy 2022-02-15 14:10:40 +01:00
JC Brand
b44e1c82f0 Updates #2733
- Clear timer when a messages changes from epehemeral to non-ephemeral
- Set MUC occupant on `groupchat` message when `type` changes to `groupchat` (from `error`)
- Set roster contact on `chat` message when `type` changes to `chat` (from `error`)

Thanks @afriedmanGlacier
2022-02-15 12:23:46 +01:00
JC Brand
a07bd7c817 Use SVG icons for refresh button and toggle switch 2022-02-15 11:17:41 +01:00
JC Brand
85d75a5494 Fixes #2745. Wraps MUC details in converse-rich-text
Also fixed an issue where the `config` model on the MUC wasn't being
properly persisted and fetched.
2022-02-15 11:17:33 +01:00
JC Brand
a2c7e83812 Take offset into account when parsing text for URLs 2022-02-14 19:08:26 +01:00
JC Brand
7c7b667745 MUC: Register handler to parse for commands in the plugin index.js 2022-02-14 15:17:05 +01:00
JC Brand
e1a919749f Add Prime Sound as sponsor 2022-02-14 15:01:14 +01:00
JC Brand
8dff87658f Remove Pluckeye as sponsor 2022-02-14 13:05:49 +01:00
JC Brand
38519a6261 Updates #2733
Properly handle the same OMEMO message being recieved twice, with the
2nd one failing to decrypt.
2022-02-14 12:59:49 +01:00
JC Brand
f6c524f760 Move MUC modals to the muc-views plugin 2022-02-14 12:59:49 +01:00
JC Brand
94d29bc617 Create Github action to run tests
Also remove .travis.yml since tests no longer run on Travis
2022-02-14 10:55:40 +01:00
JC Brand
0fb4dcac96 Translated using Weblate (Spanish)
Currently translated at 90.1% (460 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/es/
2022-02-10 14:24:06 +01:00
Xosé M
caf8360745 Translated using Weblate (Galician)
Currently translated at 100.0% (510 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/gl/
2022-02-10 14:24:06 +01:00
Dalde Pro
ea63c9a17d Translated using Weblate (Spanish)
Currently translated at 90.1% (460 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/es/
2022-02-10 14:24:06 +01:00
ButterflyOfFire
6a293de86b Translated using Weblate (Arabic)
Currently translated at 74.3% (379 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/ar/
2022-02-10 14:24:06 +01:00
translator
5caa5aa9ae Translated using Weblate (French)
Currently translated at 100.0% (510 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/fr/
2022-02-10 14:24:06 +01:00
Yaron Shahrabani
b8487cfaa6 Translated using Weblate (Hebrew)
Currently translated at 73.3% (374 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/he/
2022-02-10 14:24:06 +01:00
aitzol berasategi
203afea72b Translated using Weblate (Basque)
Currently translated at 99.8% (509 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/eu/
2022-02-10 14:24:06 +01:00
JC Brand
7f40d1a2f2 Fix #2627 2022-02-10 13:36:22 +01:00
JC Brand
47f3109957 Dracula: Set colors for unread messages indicator and nickname autocomplete 2022-02-10 13:03:47 +01:00
JC Brand
066d29d637 Fix alignment of close button for MUC sidebar 2022-02-10 12:09:02 +01:00
JC Brand
12a2354d9e CSS: Fix chat heading colors 2022-02-09 21:38:30 +01:00
JC Brand
d8f6a16936 Avoid unnecessary call to requestUpdate and use updateComplete 2022-02-09 21:22:38 +01:00
JC Brand
8a9e0f6d23 CSS fix for emoji picker when there are no search results 2022-02-09 20:47:29 +01:00
JC Brand
f4fdc36d31 Add modal for changing your nickname...
once you're already in a MUC.
2022-02-09 20:05:30 +01:00
JC Brand
ba52defdae Move nickname tests into a new file 2022-02-09 20:05:30 +01:00
JC Brand
505416a59e Let bookmarks be created/removed via a modal 2022-02-09 20:05:30 +01:00
JC Brand
9d250c3cbf Fix failing test due to converse-icon being used 2022-02-09 20:05:30 +01:00
JC Brand
46e6cfb0d4 Fix some failing tests after #2803 2022-02-09 20:05:30 +01:00
afriedmanGlacier
3d8a583101
Wait for parseMessages before queuing to UI (#2803)
* parse messages before queuing

* update CHANGES

* remove unused variable

Co-authored-by: aFriedmanGlacier <afriedman@glaciersecurity.com>
2022-02-05 22:02:24 +01:00
JC Brand
337638034f Fix TypeError when trying to use @converse/headless
Fixes #2788
2022-02-03 12:39:59 +01:00
JC Brand
0f648ed1eb Don't re-initialize OMEMO on reconnection
Promises only get recreated upon logout, not reconnection.

However OMEMO was getting re-initialized on reconnection and
`_converse.omemo_store` was also deleted.

This caused a race condition where an incoming MAM message would cause
`parseEncryptedMessage` that then throws an AttributeError because
`_converse.omemo_store` is undefined because OMEMO isn't yet
initialized.

Waiting for the `OMEMOInitialized` promise doesn't help because it's
still the old (already resolved) promise from before the reconnection.
2022-02-02 23:18:45 +01:00
JC Brand
d3fa925bff Move reconnection code to Connection class
And avoid calling `tearDown` twice
2022-02-02 13:53:05 +01:00
Keith Maika
cb0b1765f3 Fix webpack configuration on Windows 2022-01-31 23:02:57 +01:00
JC Brand
bef2cbb462 Use SVG icons and tweak message padding 2022-01-31 23:00:26 +01:00
Rob j Loranger
125f45c447
increase stanza timeout to 20s (#2799)
* increase stanza timeout to 20s

fixes issues with higher latency connections timing out fetching stanzas
2022-01-31 12:06:30 +01:00
JC Brand
817b1200ca CSS: fix hover color 2022-01-29 12:29:54 +01:00
JC Brand
8dcacd41bf Add hover color for svg icons 2022-01-29 12:12:36 +01:00
JC Brand
2e9f478c87 CSS: tweak padding for avatar in message 2022-01-29 11:46:02 +01:00
JC Brand
b13c674047 Show encrypted lock icon in message as svg 2022-01-29 11:31:09 +01:00
JC Brand
dd539c7675 CSS: fix unread msgs indicator in Dracula theme
Also try to create some initial structure with the CSS properties to
make theming easier
2022-01-29 11:19:00 +01:00
JC Brand
4f89c4c10f Closes #1761 2022-01-28 21:22:10 +01:00
JC Brand
818ad0955a Add ability to switch between dark and light modes 2022-01-28 21:20:12 +01:00
JC Brand
ac473fd297 Add dark theme Dracula
https://draculatheme.com
2022-01-28 20:28:48 +01:00
JC Brand
11bbbb4899 Create separate theme files 2022-01-28 12:43:24 +01:00
JC Brand
0d0ee294ad Don't fetch vcard if failed attempt was already made today 2022-01-28 12:43:24 +01:00
JC Brand
7c51147023 Use the parseMessageForCommands hook to also parse MUC commands
Also fix issue where `model.getAllowedCommands()` prevents 3rd party
implementations.
2022-01-28 12:40:21 +01:00
JC Brand
003a90c71c Don't explicitly trigger the hook parseMessageForCommands
inside `parseMessageForMUCCommands`.

If the function doesn't find any core MUC commands, it calls
`parseMessageForCommands` which will trigger the hook.

I think it's appropriate to give built-in commands preference above
commands by 3rd party plugins and this also solves the issue of the hook
being triggered twice (once in `parseMessageForMUCCommands` and
then again in `parseMessageForCommands`).
2022-01-27 19:12:35 +01:00
JC Brand
d06761e2a8 Fix failing tests 2022-01-27 19:12:35 +01:00
Dele Olajide
c83cc69cef Implement new hook parseMessageForCommands for plugins to add custom commands 2022-01-27 14:34:20 +01:00
JC Brand
351212cd13 Move webpack files into dir 2022-01-27 13:08:40 +01:00
JC Brand
93ec6e4e83 Also build a non-minified version of converse-headless
Relevant to #2788
2022-01-27 11:51:54 +01:00
JC Brand
007b4bce2f Set BOSH wait period to 59 seconds also when attaching to a session 2022-01-25 13:13:14 +01:00
JC Brand
46a5a64dda Set id on MUC join presence
This is necessary for the Bifrost Matrix-XMPP bridge
2022-01-25 13:07:03 +01:00
JC Brand
72eb9d9595 Bump Strophe version 2022-01-21 20:25:01 +01:00
JC Brand
ba6da97416 Fix syntax error in po file 2022-01-12 11:17:58 +01:00
JC Brand
fab83139f8 Translated using Weblate (Afrikaans)
Currently translated at 100.0% (510 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/af/
2022-01-10 15:19:05 +01:00
wroot
6cd05eab39 Update changelog 2022-01-10 14:54:27 +01:00
wroot
16626c80a7 Update Lithuanian (LT) translation 2022-01-10 14:54:27 +01:00
Andrey
c809141ee6 Translated using Weblate (Russian)
Currently translated at 98.2% (501 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/ru/
2022-01-10 14:54:02 +01:00
Reza Almanda
53df0f8942 Translated using Weblate (Indonesian)
Currently translated at 66.2% (338 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/id/
2022-01-10 14:54:02 +01:00
ssantos
17678f06f6 Translated using Weblate (Portuguese)
Currently translated at 100.0% (510 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/pt/
2022-01-10 14:54:02 +01:00
Anas Yaseen
5da069d585 Translated using Weblate (Arabic)
Currently translated at 73.7% (376 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/ar/
2022-01-10 14:54:02 +01:00
Xosé M
10264e1647 Translated using Weblate (Galician)
Currently translated at 100.0% (510 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/gl/
2022-01-10 14:54:02 +01:00
Allan Nordhøy
900bb11fb0 Translated using Weblate (Norwegian Bokmål)
Currently translated at 70.7% (361 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/nb_NO/
2022-01-10 14:54:02 +01:00
Wie Paw
1b3ab06614 Translated using Weblate (Polish)
Currently translated at 96.8% (494 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/pl/
2022-01-10 14:54:02 +01:00
aitzol berasategi
a20188e7a8 Translated using Weblate (Basque)
Currently translated at 86.0% (439 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/eu/
2022-01-10 14:54:02 +01:00
random r
d55fc92c1c Translated using Weblate (Italian)
Currently translated at 100.0% (510 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/it/
2022-01-10 14:54:02 +01:00
nautilusx
0a9444c41b Translated using Weblate (German)
Currently translated at 100.0% (510 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/de/
2022-01-10 14:54:02 +01:00
nautilusx
7ebb35d80c Translated using Weblate (German)
Currently translated at 99.4% (507 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/de/
2022-01-10 14:54:02 +01:00
Eric
cada8146b6 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (510 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/zh_Hans/
2022-01-10 14:54:02 +01:00
Oğuz Ersen
68bcf51ed8 Translated using Weblate (Turkish)
Currently translated at 99.6% (508 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/tr/
2022-01-10 14:54:02 +01:00
Xosé M
ed089d0546 Translated using Weblate (Galician)
Currently translated at 100.0% (510 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/gl/
2022-01-10 14:54:02 +01:00
JC Brand
6ee3ddbc8c Make sure we're connected to MUC before sending status update 2021-12-17 20:55:57 +01:00
JC Brand
c3aafdf341 Fix TypeError and remove tab 2021-12-17 20:55:52 +01:00
JC Brand
9411860f69 Document issues around keeping users logged in across page reloads 2021-12-17 17:27:03 +01:00
JC Brand
4dc78c3742 Bump to Strophe 1.4.3 2021-12-17 17:27:03 +01:00
Dele Olajide
ee4ab47442 corrected as advised 2021-12-16 15:44:43 +01:00
Dele Olajide
4bb4f932cf fix #2751 - Media not rendered when Converse runs in a browser extension 2021-12-16 15:44:43 +01:00
JC Brand
f25f110e0e Avoid infinite loop when BOSH URL returns 404 2021-12-11 12:37:02 +01:00
JC Brand
e9ae5306e3 Bugfix. Avoid calling this.authenticate twice in one method 2021-12-11 12:28:04 +01:00
JC Brand
8ad097f23f Catch and log parser errors 2021-12-10 22:57:33 +01:00
JC Brand
048560908e Login form: Allow user to choose the connection URL
if `websocket_url` and `bosh_service_url` are not set and XEP-0156
lookup was unsuccessful.
2021-12-10 22:57:33 +01:00
JC Brand
0dee9897dd Use CustomElement instead of ElementView for login form 2021-12-10 22:57:33 +01:00
JC Brand
a673086941 Rename loginpanel to loginform
Run prettier and move constants to `constants.js`
2021-12-10 22:57:33 +01:00
JC Brand
b16d035975 Move setUserJID to init.js 2021-12-10 22:57:33 +01:00
JC Brand
ca9e13a047 Update embedded view mode documentation 2021-12-10 22:21:16 +01:00
JC Brand
dc66c3a101 Make sure converse.initialize still returns a Promise 2021-11-30 16:11:52 +01:00
JC Brand
47bab27f7b Fix JSDoc syntax error and update RELEASE.md 2021-11-29 10:11:56 +01:00
JC Brand
077162529d Release 9.0.0 2021-11-29 10:00:38 +01:00
Siddhesh Mhadnak
32bc8917ab Translated using Weblate (Marathi)
Currently translated at 5.5% (28 of 509 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/mr/
2021-11-29 09:35:28 +01:00
Kiiryth X
b418db5643 Translated using Weblate (Bulgarian)
Currently translated at 32.0% (163 of 509 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/bg/
2021-11-29 09:35:28 +01:00
Siw Falch
1c247969b4 Translated using Weblate (Norwegian Bokmål)
Currently translated at 71.1% (362 of 509 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/nb_NO/
2021-11-29 09:35:28 +01:00
Eric
c178cbbcd8 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (509 of 509 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/zh_Hans/
2021-11-29 09:35:28 +01:00
52871299hzy
d31f1ce317 Translated using Weblate (Chinese (Simplified))
Currently translated at 99.2% (505 of 509 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/zh_Hans/
2021-11-29 09:35:28 +01:00
random r
209bea2fcc Translated using Weblate (Italian)
Currently translated at 100.0% (509 of 509 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/it/
2021-11-29 09:35:28 +01:00
Kim Alvefur
c820920b2c Translated using Weblate (Swedish)
Currently translated at 99.0% (504 of 509 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/sv/
2021-11-29 09:35:28 +01:00
Quentin PAGÈS
ed7efb2c61 Translated using Weblate (Occitan)
Currently translated at 80.5% (410 of 509 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/oc/
2021-11-29 09:35:28 +01:00
random r
801a21e049 Translated using Weblate (Italian)
Currently translated at 99.0% (504 of 509 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/it/
2021-11-29 09:35:28 +01:00
52871299hzy
a8a397d8b2 Translated using Weblate (Chinese (Simplified))
Currently translated at 97.0% (494 of 509 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/zh_Hans/
2021-11-29 09:35:28 +01:00
Ali Frh
bdc7390eca Translated using Weblate (Persian)
Currently translated at 23.9% (122 of 509 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/fa/
2021-11-29 09:35:28 +01:00
Nikita Epifanov
0f99d4833e Translated using Weblate (Russian)
Currently translated at 98.6% (502 of 509 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/ru/
2021-11-29 09:35:28 +01:00
Jakub Tabor
b96150a629 Translated using Weblate (Polish)
Currently translated at 92.3% (470 of 509 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/pl/
2021-11-29 09:35:28 +01:00
Emmanuel Gil Peyrot
6001273c6f Translated using Weblate (French)
Currently translated at 100.0% (509 of 509 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/fr/
2021-11-29 09:35:28 +01:00
Oğuz Ersen
430f1f5a0e Translated using Weblate (Turkish)
Currently translated at 100.0% (509 of 509 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/tr/
2021-11-29 09:35:28 +01:00
Gediminas Murauskas
128079f2a4 Translated using Weblate (Lithuanian)
Currently translated at 64.0% (326 of 509 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/lt/
2021-11-29 09:35:28 +01:00
Xosé M
8efafc7c25 Translated using Weblate (Galician)
Currently translated at 100.0% (509 of 509 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/gl/
2021-11-29 09:35:28 +01:00
nautilusx
20666a334e Translated using Weblate (German)
Currently translated at 100.0% (509 of 509 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/de/
2021-11-29 09:35:28 +01:00
JC Brand
c81841e036 Fix margin issues at different viewport sizes 2021-11-26 09:52:52 +01:00
JC Brand
3d74ed31c2 Fixes #2683, Updates #1317 2021-11-24 22:44:02 +01:00
JC Brand
1a6a7ade73 Fixes #2715 2021-11-24 21:52:40 +01:00
JC Brand
ee4e056125 Fixes #2718: Message is not displayed if it contains an invalid URL 2021-11-24 21:43:20 +01:00
JC Brand
e4da0f894d MUC: Make info messages ephemeral
Otherwise they pollute the history and it's not easy to dedupe them
because they can be created before the MAM history is fetched.
2021-11-24 21:28:11 +01:00
JC Brand
284eccf047 Create converse-omemo-profile component
Removes the need to override the ProfileModal
2021-11-24 21:14:11 +01:00
JC Brand
bad2577e5e OMEMO Refactoring
When calling `getDeviceList`, wait for the devices to be fetched

Otherwise a race condition might occur, whereby a new device gets
created in the collection, and then removed again as the collection is
replaced with the values fetched from the browser-storage cache.

Also created `converse-omemo-fingerprints` component to asynchronously
render fingerprints in the user details modal. Was done as part of this
commit because due to `getDeviceList` being async, the relevant test for
the modal were also failing
2021-11-24 21:14:11 +01:00
JC Brand
9b1a7c70a3 Wait on OMEMOInitialized promise...
before parsing message stanza for encryption parameters.

Otherwise we might not know what our own device-id/sid is, and therefore
can't decrypt the incoming message.

Fixes #2733
2021-11-24 21:14:11 +01:00
JC Brand
a06d180827 Could not find dependency "converse-controlbox" for plugin "converse-muc"
Fixes #2423
2021-11-21 12:13:13 +01:00
JC Brand
2af758e66d Not sending headers with upload request
Fixes #2728
2021-11-21 11:56:53 +01:00
JC Brand
fa562cabae Don't fetch member list if not affiliated
Fixes #1426
2021-11-21 11:05:23 +01:00
JC Brand
07b2425ff9 Don't show unnecessary errors for undecryptable OMEMO messages
As mentioned in the XEP, don't show error messages for OMEMO messages
that can't be decrypted because they were already decrypted before or
because they weren't encrypted for this device.
2021-11-20 13:43:27 +01:00
JC Brand
d48d748e30 Don't cache the most recent message.
Since messages are ordered by time, the call to get it isn't very
expensive and by not caching we avoid getting a stale cache value
2021-11-20 13:43:27 +01:00
JC Brand
33f3cb76ad Use the extended MAM message data to get the sender's real JID
That solves the problem of not being able to look up OMEMO session data
from incoming MAM messages.

See here: https://github.com/conversejs/converse.js/issues/2241#issuecomment-974626847

Updates #2241
2021-11-20 12:50:25 +01:00
JC Brand
78846ab984 Fix: don't show avatars for followup messages 2021-11-19 23:05:16 +01:00
JC Brand
afbb46bd8c Add converse-image custom element
And use that to render images in unfurls.

This solves the issue of github URL unfurl images not having an image
extension and then being rendered as a hyperlink by `converse-rich-text`.

Instead, we know that it's supposed to be a url, so we just use `converse-image`.
2021-11-19 22:32:46 +01:00
JC Brand
ed63902ac1 Send presence status change to all connected MUCs
Fixes #2725
2021-11-19 21:26:35 +01:00
JC Brand
35947e3d62 Show avatars in MUC occupants sidebar
Fixes #1322

(Also clean up some loose threads)
2021-11-19 21:08:51 +01:00
JC Brand
bdac6f1b47 Split vcard plugin up into multiple files 2021-11-19 13:42:59 +01:00
Andy Friedman
c76e6fb86b Compress new avatar images 2021-11-19 13:01:09 +01:00
JC Brand
664f290001 Use converse-avatar for setting avatar 2021-11-19 13:01:09 +01:00
JC Brand
c62ea03e2e Use converse-avatar for roster items 2021-11-19 13:01:09 +01:00
JC Brand
8db12e61bf Use converse-avatar and fix bug...
where avatar didn't show in 1:1 chat heading (due to a race condition)
2021-11-19 11:07:09 +01:00
JC Brand
f36c3fefdd Fix the MUC occupant modal and add more info
Fixes #1419
2021-11-19 11:07:09 +01:00
JC Brand
a5b73f0309 Create the converse-avatar custom element 2021-11-19 10:00:04 +01:00
JC Brand
e347621dc8 Add JSDoc example 2021-11-17 09:42:38 +01:00
JC Brand
1ee75b78b7 Replace more font icons with svg icons
Updates #1004
2021-11-14 22:53:04 +01:00
JC Brand
571cb3bac1 Remove unused loader in webpack 2021-11-14 22:43:04 +01:00
JC Brand
5dd0065936 Embedded demo: Make links relative
Otherwise https://converse.js/trunk/demo/embedded.html wrongly uses files from the site root.
2021-11-14 08:20:29 +01:00
JC Brand
ecfc3e9fcf Implement support for XEP-0421 occupant ids
This let's us populate the `from_real_jid` attribute for messages in
cases where the user's nickname has changed.

Only save the occupant-id if the MUC supports it

Store all advertised features on the `chatbox.features` model.
This allows us to look up a feature without using the async
`disco.supports` API.

Updates #2241
2021-11-06 22:25:02 +01:00
JC Brand
a60127e66f Avoid possible exception when leaving/reconnecting in a MUC
- Unregister nickname before sending unavailable presence
- Send unavailable presence before destroying state
- Call `leave` after unregistering, otherwise the disco entry for the MUC gets removed in `leave` while it's still necessary to unregister
- Wrap `this.leave` in  try/except in `onConnectionStatusChanged` handler
- Add new MUC connection status, `CLOSING` to avoid `this.leave()` being called when `hidden` gets set to `true` while the MUC is in the process of being closed.
2021-11-04 19:21:29 +01:00
JC Brand
93e1758a0b Mention new fix in changelog 2021-10-30 21:36:18 +02:00
JC Brand
2fb8ea3ea0 Only register new nick if auto_register_muc_nickname is set 2021-10-30 21:30:53 +02:00
John Spurlock
1c6ada4af8 Fix send button not working in a muc room
Was looking at the wrong form
2021-10-30 21:16:11 +02:00
JC Brand
ca02bdcb61 Bugfix. Use real JID when setting up a device session in a MUC
Thanks to @orbitz, see: https://github.com/conversejs/converse.js/issues/1481#issuecomment-509183431

Updates #1481
2021-10-30 21:14:11 +02:00
JC Brand
90d93b364a Reregister nick when changing it in a members-only MUC 2021-10-30 20:56:23 +02:00
JC Brand
6177afd5b1 MUC: Don't send markers for non-groupchat messages.
I noticed that a marker was sent for an error message (created due to an
unencryptable OMEMO messages), and this caused the user to be kicked
from the MUC.
2021-10-30 20:56:23 +02:00
JC Brand
5abec5bff0 Remove tabs 2021-10-30 20:56:23 +02:00
Kim Alvefur
ec792abbda Map XEP-0122 data types to HTML5 form field types
This should invoke nicer UI some browsers have for certain types, like numbers.
2021-10-26 11:57:05 +02:00
Kim Alvefur
6890da11ed Factor out input field type mapping into a function to allow modified logic 2021-10-26 11:57:05 +02:00
JC Brand
1b31e80f25 Render MEP message reason as rich text 2021-10-21 10:43:24 +02:00
JC Brand
d2a33bc210 Add the ability to retract XEP-0316 MEP messages 2021-10-20 17:49:58 +02:00
JC Brand
3cfdf4c946 Fix trimming of chats in overlayed view mode 2021-10-14 17:49:20 +02:00
JC Brand
5a7f16b6f9 Bugfix. 'closed' value only relevant in overlayed view mode 2021-10-14 16:15:17 +02:00
JC Brand
32e521fdc7 Bugfix. MEP messages appear at bottom when returned from MAM 2021-10-13 21:14:57 +02:00
JC Brand
521f3d88d2 Move MUC MAM tests into a new file 2021-10-13 20:01:09 +02:00
JC Brand
cf8522b1ef Fix attribute error 2021-10-04 10:56:13 +02:00
JC Brand
6cff47c6d8 Remove muc_ogp_show_unfurls setting
And instead use the `render_media` setting to determine whether unfurls
should be shown.
2021-10-01 13:22:17 +02:00
JC Brand
366932e999 Allow render_media setting to be an array of domains
This allows for more flexibility in configuring which media URLs will
automatically render and which media URLs may be manually rendered by
the user (via the message actions dropdown).

For example, suppose you want to automatically render all media URLs
from https://xmpp.org, but still allow other media (which won't render
by default) to be rendered manually by the user (by clicking the "Show
URL previews" message dropdown action).

In this case, you set `render_media` to `['xmpp.org']` and
`allowed_image_domains` to `null` or `undefined`.

Or if you want to automatically render images from xmpp.org, and
restrict the domains users might manually click to render, you can add
those extra domains to `allowed_image_domains`.
2021-09-30 16:30:30 +02:00
JC Brand
be2ded3b7e No need to pass in render_media as a prop 2021-09-29 13:19:00 +02:00
JC Brand
1809e38911 Move isUniView function to utils 2021-09-29 12:03:21 +02:00
JC Brand
06ec539839 Update lit imports 2021-09-29 11:20:14 +02:00
JC Brand
84c6a0039c Fix embedded, singleton mode.
It's now necessary to add a `converse-root` element in the DOM where you
want Converse to render (previously it was any element with the id
`#conversejs`).

Also, turned `converse-chats` element into a Lit element and re-render
`converse-root` and `converse-chats` when the `view-mode` or `singleton`
settings change. This is a step towards being able to change the view
mode on the fly and have the entire chat re-render appropriately.

Fixes #2647
2021-09-24 11:53:49 +02:00
JC Brand
5ff57258ec Fix nickname form width 2021-09-23 22:31:30 +02:00
JC Brand
d4f6b040f3 Bugfix. Read jid from settings
Now that app settings are now longer saved directly on the `_converse` object
2021-09-23 22:27:49 +02:00
JC Brand
1104b28758 Bugfix. URL is passed in, not object 2021-09-23 21:56:32 +02:00
JC Brand
881a9a6d27 Re-render message if relevant config settings change 2021-09-23 21:50:24 +02:00
JC Brand
48f37aa1c0 Call initialize in CustomElement's connectedCallback method 2021-09-23 14:25:42 +02:00
JC Brand
7f2ab05f97 Move tests to separate file 2021-09-22 16:45:57 +02:00
JC Brand
de092f8f00 Emit events on the settings object
instead of on a separate object
2021-09-22 16:36:28 +02:00
JC Brand
9e48fdc91c Emit an event when a configuration setting gets changed 2021-09-21 17:08:30 +02:00
JC Brand
05dcb4e8d7 Breaking change: stop setting config variables on the _converse object 2021-09-21 17:08:30 +02:00
JC Brand
864e8910c4 Move settings related files into one directory 2021-09-21 17:08:30 +02:00
JC Brand
efafc2d691 Allow media to be invidually shown/rendered...
even if the global configuration is to disallow it.

* When parsing, include all media URLs, not just the ones from allowed domains.
  That makes it possible to change allowed domains on-the-fly,
  while still allowing media in individual messages to be shown manually
  (via the message actions dropdown).
* Merge `embed_audio`, `embed_video` and `show_images_inline` into `render_media`
* Create new config settings for allowable domains for images, video and audio
* Check the URL domain against a whitelist for the message actions dropdown
2021-09-21 17:08:30 +02:00
JC Brand
ed490fc202 Create directory for modal plugin 2021-09-20 11:13:26 +02:00
ayu
ae6dbeb287 Update vcard.js
Example code wouldn't work anymore.
2021-09-18 21:59:17 +02:00
JC Brand
75fee76693 Fixes #2650 2021-09-14 22:27:49 +02:00
JC Brand
caffcaaef2 Move occupant-related tests into new file 2021-09-14 22:03:10 +02:00
JC Brand
2b7624e622 Make sure all files are used when generating API docs 2021-09-14 15:04:12 +02:00
JC Brand
ad501d4309 Avoid AttributeError when _converse.disco_entities is undefined 2021-09-13 14:23:46 +02:00
JC Brand
126fa1809e Update changelog 2021-09-13 13:45:12 +02:00
Ariel Fuggini
d44abbb48e
Adds hook to fetchLoginCredentials function (#2640)
* Adds hook to fetchLoginCredentials function

* Adds documentation
2021-09-10 16:12:46 +02:00
JC Brand
40a49042e9 Postrelease 2021-09-09 22:43:37 +02:00
JC Brand
6b3f8a3f39 Release 8.0.1 2021-09-09 22:09:26 +02:00
Allan Nordhøy
2c1d6e3ecb Translated using Weblate (Norwegian Bokmål)
Currently translated at 70.9% (362 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/nb_NO/
2021-09-09 21:45:42 +02:00
JC Brand
906a606010 Get rid of unnecessary specificity and functions 2021-09-09 11:35:00 +02:00
JC Brand
ef2c206507 Fix failing test 2021-09-09 11:12:31 +02:00
JC Brand
b78c19f6f2 Fix showing of HTML5 notifications for MEP messages 2021-09-08 17:30:30 +02:00
JC Brand
8aa16ea0be Fix broken import 2021-09-08 10:52:37 +02:00
JC Brand
8d01d7a710 Use optional chaining and update changelog 2021-09-08 10:35:46 +02:00
The Stranjer
660d765c59
Ensure that the converse session is actually present (#2636)
* Ensure that the converse session is actually present before trying to get anything out of it

* Update changelog
2021-09-08 10:32:59 +02:00
JC Brand
8f34065fc0 Also create MEP messages received from a MAM archive 2021-09-08 10:22:26 +02:00
JC Brand
f40a8f69ae Don't show minimized chats when logged out 2021-09-06 22:08:36 +02:00
JC Brand
0950555b49 Fix loading of CSS 2021-09-06 22:07:51 +02:00
JC Brand
286ab1ad83 Fixes #2633. 2021-09-06 21:56:56 +02:00
JC Brand
90cac3ecae Fixes #2326: 404 for asset /logo/conversejs-filled.svg 2021-09-06 21:29:35 +02:00
JC Brand
f04a376653 Fixes #2628: Open bookmarks toggle emits an error 2021-09-06 21:29:35 +02:00
JC Brand
b75e67fafa Fixes #2629 OMEMO button tooltip is wrong in private chat 2021-09-06 20:59:26 +02:00
JC Brand
8854f67c20 Bugfix: Image previews not loading when not serving Converse locally
Fixes #2634
2021-09-06 20:00:01 +02:00
JC Brand
9b4ce0011e Postrelease 2021-09-04 09:42:45 +02:00
JC Brand
c03bc7d600 Prepare release 8.0.0 2021-09-03 15:40:11 +02:00
random r
8f2f3e6498 Translated using Weblate (Italian)
Currently translated at 100.0% (510 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/it/
2021-09-03 14:44:41 +02:00
ButterflyOfFire
730cb9c822 Translated using Weblate (Arabic)
Currently translated at 69.8% (356 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/ar/
2021-09-03 14:44:41 +02:00
Tymofii Lytvynenko
acbd6000fc Translated using Weblate (Ukrainian)
Currently translated at 33.7% (172 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/uk/
2021-09-03 14:44:41 +02:00
Xosé M
e80a12a8a4 Translated using Weblate (Galician)
Currently translated at 100.0% (510 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/gl/
2021-09-03 14:44:41 +02:00
Quentin PAGÈS
a21abae5f6
Translated using Weblate (Occitan)
Currently translated at 81.5% (416 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/oc/
2021-09-03 14:38:43 +02:00
JC Brand
5095027a0b Don't render OOB url if it's the same as the body
Otherwise the file gets shown/rendered twice.
2021-09-01 10:35:32 +02:00
JC Brand
5dc89fb2b3 Ignore 'minimized' flag when not in overlayed view mode 2021-08-31 12:11:27 +02:00
JC Brand
353a90788c Make IndexedDB the default persistent store 2021-08-31 12:11:27 +02:00
JC Brand
90ea092e4d Register a XEP-0316 MEP handler
Add caps element to the MUC join presence, so that the MUC MEP node can
know whether we're interested in receiving MEP messages.

Create info messages for any `conference-info` tags that contain `activity` tags.

Check for both `headline` and `normal` MEP messages (even though the XEP
only show `headline` examples), since `normal` messages can be archived
in MAM, but `headline` ones not.

Update the XEP-0372 reference-parsing code to take the `anchor`
attribute into consideration, specifically to check which text element
the reference applies to.

Add support for rendering XEP-0372 mentions in "info" messages and for
triggering HTML5 Desktop notifications for such mentions.

Background:
-----------

XEP-0316 describes a way for a MUC to send out PEP-like messages to MUC
participants. This feature can be used to describe custom activity happening
in the MUC.
2021-08-31 11:23:49 +02:00
JC Brand
7e88ffd098 Move MUC functions to utils 2021-08-31 11:23:49 +02:00
JC Brand
6827e21df1 Fix race conditions in tests 2021-08-31 11:23:49 +02:00
JC Brand
b4d00f86a8 Rename image links to use dashes
For cache invalidation on Github
2021-08-29 14:20:31 +02:00
JC Brand
c4ccde1b4d Fixes #2385: Add new screenshots 2021-08-29 00:29:01 +02:00
JC Brand
0c0af2d00b Fix the minimized chats toggle
Clicking didn't make the minimized chats appear.
Also turn it into a Lit component
2021-08-29 00:15:45 +02:00
JC Brand
6c3a3dd1d3 Fix background for overlayed mode 2021-08-29 00:15:45 +02:00
JC Brand
fc51257ee1 Fix badge.svg in index.html as well 2021-08-28 22:42:48 +02:00
JC Brand
47b8337ff6 Fix path to chat badge 2021-08-28 22:39:46 +02:00
JC Brand
8d62c2b103 Bump dompurify to latest version 2021-08-26 06:58:00 +02:00
JC Brand
726dbddea7 Bump webpack-dev-server 2021-08-26 06:42:35 +02:00
JC Brand
88d778bdea Set widths for sponsor images in readme 2021-08-26 06:31:42 +02:00
JC Brand
9edab0729f Bump localforage 2021-08-26 06:30:39 +02:00
JC Brand
9cef50323a Add two new sponsors 2021-08-26 06:24:02 +02:00
JC Brand
df53282b6e Bump dayjs 2021-08-25 14:32:34 +02:00
JC Brand
b936824348 Bump eslint 2021-08-25 14:16:36 +02:00
JC Brand
a0ff85d74e Update theming and development documentation
* The templates are no longer `.html` files and are dispersed throughout the source code.
* The Sass files are also no longer all in one place
* Add a section on webpack aliases for modifying templates without touching the original files

Updates #2603
2021-08-25 11:55:06 +02:00
JC Brand
f739b9d37d Fix encrypted images not showing inline.
Updates #1182 #2554
2021-08-24 20:03:04 +02:00
JC Brand
8eac031047 Re-add wrapper anchor for unfurl images
We don't want the wrapper for interactive elements (GIF, video, audio),
but for images we still want them to link to the unfurled URL.
2021-08-10 13:45:56 +02:00
JC Brand
edd3b681c5 Create converse-message-versions component
Enables re-use outside of the message versions modal.
2021-08-10 10:48:50 +02:00
JC Brand
82ade54caa Use converse-icon to show message edited icon/toggle 2021-08-09 15:53:50 +02:00
JC Brand
610e334bed Use converse-icon in the modtools modal 2021-08-06 13:38:12 +02:00
JC Brand
44a573b6c4 Handle GIFs inside Unfurls
- Add ability to play/pause by using `converse-rich-text`
- Make `converse-rich-text` component configurable whether the media URLs for GIF/audio/video are shown
- Add fallback options for GIFs that have errors
2021-08-03 12:14:13 +02:00
JC Brand
95fbd55a19 Fixes #2583 2021-07-30 09:58:35 +02:00
JC Brand
d0627f800c Clear unread message counters when chat becomes visible 2021-07-30 09:56:17 +02:00
JC Brand
ac36407d1d Immediately draw and clear pause icon...
as you move the mouse over or away from a gif
2021-07-29 21:21:51 +02:00
JC Brand
ebfda5c86e Fix GIF rendering
- Fix some GIFs getting stuck
- Add a delay of 80ms for GIFs that specify a delay of 0
- Refactor slightly and add JSDoc
- Remove the unused `loop_delay` option, to allow further simplification of the code
2021-07-29 13:24:27 +02:00
JC Brand
106cde9262 Update modtools component...
to accept jid and affiliation and to not use a Model to store state
2021-07-28 13:28:01 +02:00
JC Brand
7b4f8954b3 No longer necessary to import Bootstrap dropdown styles in index 2021-07-27 14:51:43 +02:00
JC Brand
0242fdb020 Extract moderator tools functionality and put it in a component
This makes it easier for 3rd parties to embed it in other modals (besides the bootstrap modal).
2021-07-27 12:53:39 +02:00
JC Brand
10c610232c Use converse-icon instead of webfonts in heading dropdown 2021-07-27 11:11:36 +02:00
JC Brand
c961615609 Move converse-dropdown styles in separate file
And add some tweaks
2021-07-27 10:53:23 +02:00
JC Brand
55146820e3 Use converse-icon in the converse-dropdown component
Instead of using webfonts
2021-07-26 19:27:59 +02:00
JC Brand
0ccf25d986 Add support for controlling (e.g. pausing, looping) gifs
- Create new component `converse-gif`
- Draw gif in canvas and add controlls
2021-07-23 19:31:43 +02:00
JC Brand
316748988b Allow contact's profile modal to be shown...
even if there is now OMEMO device info
2021-07-23 18:30:07 +02:00
JC Brand
7075c9feee Move modal test out of spec 2021-07-19 16:40:40 +02:00
JC Brand
5cce34eb40 Split push plugin up into multiple files 2021-07-19 16:40:40 +02:00
JC Brand
60826ac6c6 Move functions out of core.js 2021-07-19 16:40:40 +02:00
JC Brand
8931c61876 Prevent attribute error on timeout 2021-07-19 16:40:40 +02:00
JC Brand
d1abf3a04e Wait for roster to be initialized 2021-07-19 16:40:40 +02:00
JC Brand
2bdea0dd18 Move settings API from core.js to own file
Move CORE_PLUGINS to `constants.js`
2021-07-19 15:50:50 +02:00
JC Brand
d2a35d4ce1 Turn converse-roster and converse-roster-filter into Lit elements 2021-07-15 17:26:09 +02:00
JC Brand
8de4671603 Replace more elements that use font icons with svg icons 2021-07-15 16:28:12 +02:00
JC Brand
b22127a877 Downgrade css-loader to 5.2.7
Fixes an issue with fonts not showing properly
2021-07-15 15:59:07 +02:00
JC Brand
d7af120154 Bump css-loader to 6.0.0 2021-07-15 14:36:28 +02:00
JC Brand
7bc70f728a Bump style loader to version 3.1.0 2021-07-15 14:32:53 +02:00
JC Brand
664c3522a7 Update postcss-loader to 6.1.1 2021-07-15 14:28:34 +02:00
JC Brand
c209b9e2b9 Bump urijs to 1.19.7 2021-07-15 14:18:51 +02:00
JC Brand
2bcf01f5ab Use DOMPurify instead of XSS.js
Remove exports-loader, which is therefore no longer necessary
2021-07-15 14:16:41 +02:00
JC Brand
14e5e3b3a6 Bump more deps and update changelog to mention required Node version 2021-07-15 12:47:19 +02:00
JC Brand
3c0a621b47 Bump various dependencies 2021-07-15 11:54:55 +02:00
JC Brand
fe3650d766 Bugfix. XEP-0198 stream management not working when using IndexedDB
The issue was that batched writing was incorrectly also being applied
for sessionStorage stores, so when the `active` flag in
`_converse.session` was being set to `false` on window unload, the
change wasn't persisted before the window was unloaded.

This caused a new session to be created upon reload, thereby losing the
SMACKS data.

We already solved this for persistent stores by flushing them, and
doing so for the session stores would also work, but session stores
don't have to be batched in the first place, so we turn that off.
2021-07-08 15:57:06 +02:00
JC Brand
46201613a6 Bump skeletor to 0.0.5 2021-07-08 10:33:35 +02:00
JC Brand
f2aa39e1c3 Identify media URLs during message parsing 2021-07-06 13:35:22 +02:00
JC Brand
b90a435833 Move url related utility methods to @converse/headless 2021-07-05 18:35:58 +02:00
JC Brand
bff714f24c OMEMO: Include XEP-0380 EME tag in encrypted messages 2021-07-05 18:35:58 +02:00
JC Brand
06460507d4 Don't let message actions drop upwards if...
it's the first (or second) message in the history, otherwise it might
appear behind the chat header.
2021-07-05 18:35:58 +02:00
JC Brand
01efb02f9e Make sure XEP-0363 urls are also OMEMO encrypted
by re-using `ChatBox.prototype.sendMessage`.

updates #1182
2021-07-03 00:22:03 +02:00
JC Brand
3d8852950d Add ability to let dropdown appear at the top, left-aligned
And use that for the last message in the chat history, otherwise the
dropdown is obscured.
2021-07-01 15:23:37 +02:00
JC Brand
e675c853f3 Add XEP-0454 support for encrypting files
Fixes #1182
2021-07-01 14:35:48 +02:00
JC Brand
27bc548552 Update more 3rd party dependencies 2021-06-29 16:46:40 +02:00
JC Brand
424a0c43a3 Upgrade babel 2021-06-29 16:27:32 +02:00
JC Brand
6665bef76c Fix failing tests
Handle missing message model (happens during tests)
2021-06-29 16:00:10 +02:00
JC Brand
dff5f485c9 Split out MUC tests 2021-06-29 15:59:49 +02:00
JC Brand
4047d619a1 Remove lodash dependency in tests 2021-06-29 15:59:49 +02:00
JC Brand
956a890b94 Don't reject on error in sendTimedMessage
It's the only way I could get a failing test (due to the Jasmine upgrade AFAIK) to pass.

I don't understand why this happens, given that the promise has a
`catch` clause in `retractOwnMessage`, but for some reason the promise
rejection gets caught by Jasmine, causing the test to fail.
2021-06-29 15:59:49 +02:00
JC Brand
767d5ec91d fix failing test 2021-06-29 15:59:49 +02:00
JC Brand
335a491e0d Stop using the Jasmine "done" callback 2021-06-29 15:59:49 +02:00
JC Brand
3e9f028bf4 Update more 3rd party deps 2021-06-29 13:00:36 +02:00
JC Brand
8506646db2 Remove unnecessary event trigger 2021-06-29 12:57:48 +02:00
JC Brand
be329a2d10 Don't subclass the chatbox for the controlbox model 2021-06-29 12:55:29 +02:00
JC Brand
73989e09a9 Fixes concerning dropdowns 2021-06-29 11:33:24 +02:00
JC Brand
46f567d0d1 Fix memory leak in sessionStorage
The disco entities collection gets recreated and repopulated every time
the connection is re-established or after the user logs in again after
having logged out.

The old disco entities weren't being removed, due to an erroneous
`shouldClearCache` call (not applicable to sessionStorage data).

In addition we need a handler to fire and clear the entities cache when
Converse is going to restart.
2021-06-29 11:20:50 +02:00
JC Brand
18f883545b Remove duplicate method 2021-06-25 18:19:01 +02:00
Licaon_Kter
7a22afa9ec Config docs typos 2021-06-25 17:29:26 +02:00
ubermanu
524e14f464 Register the document events once the picker is connected 2021-06-25 17:29:06 +02:00
ubermanu
7503de27c5 Remove document event listener once the dropdown is disconnected 2021-06-25 17:29:06 +02:00
JC Brand
f4da817cb2 Upgrades
babel/cli, lerna/ mini-css-extract-plugin, postcss-clean and webpack-merge
2021-06-25 17:17:34 +02:00
JC Brand
51e0237f5d Upgrade lit to 2.0.0-rc.2 2021-06-25 11:34:56 +02:00
JC Brand
14020125b9 Remove sinon and bump npm 2021-06-25 11:21:17 +02:00
JC Brand
0f82b76c09 fix failing test due to i18n string change 2021-06-25 10:59:13 +02:00
JC Brand
4c6c774251 Bump jasmine from 3.5.0 to 3.7.0 2021-06-25 10:55:56 +02:00
JC Brand
fe28b3e6af Upgrade copy-webpack-plugin to 9.0.0 2021-06-25 10:51:36 +02:00
dhruva dhruva
f9a2719507 Translated using Weblate (Romanian)
Currently translated at 43.7% (223 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/ro/
2021-06-25 10:43:37 +02:00
juliojulian
0b00d4f9e1 Translated using Weblate (Spanish)
Currently translated at 90.7% (463 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/es/
2021-06-25 10:43:37 +02:00
Luna Jernberg
aa80093665 Translated using Weblate (Swedish)
Currently translated at 99.6% (509 of 511 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/sv/
2021-06-25 10:43:33 +02:00
G
778121010f Translated using Weblate (Polish)
Currently translated at 92.7% (473 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/pl/
2021-06-25 10:43:07 +02:00
lilim
a5c391a6a3 Translated using Weblate (French)
Currently translated at 100.0% (510 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/fr/
2021-06-25 10:43:07 +02:00
ssantos
f846cb1b20 Translated using Weblate (Portuguese)
Currently translated at 100.0% (510 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/pt/
2021-06-25 10:43:07 +02:00
bashl
789d3438e3 Translated using Weblate (Portuguese (Brazil))
Currently translated at 98.8% (504 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/pt_BR/
2021-06-25 10:43:07 +02:00
Xosé M
f6de5247d6 Translated using Weblate (Galician)
Currently translated at 100.0% (510 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/gl/
2021-06-25 10:43:07 +02:00
member7me
c80d65cf60 Translated using Weblate (Russian)
Currently translated at 100.0% (510 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/ru/
2021-06-25 10:43:07 +02:00
Oğuz Ersen
cba44998b9 Translated using Weblate (Turkish)
Currently translated at 100.0% (510 of 510 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/tr/
2021-06-25 10:43:07 +02:00
JC Brand
ba0ea6c2c4 Update translations based on suggestions from Zash on weblate 2021-06-25 10:38:38 +02:00
JC Brand
7848d8cb2f Add support for decrypting XEP-0454 OMEMO media 2021-06-25 09:24:18 +02:00
JC Brand
2c0fbec43c Move arraybuffer utility methods into their own file 2021-06-24 18:57:32 +02:00
JC Brand
c5de9dd9f1 Render embedded media with full width in overlayed view mode 2021-06-24 16:13:02 +02:00
JC Brand
92093d6d28 Further style tweaks for embedded media 2021-06-24 13:04:25 +02:00
JC Brand
670f435c64 Set max widths with embedded audio and video content 2021-06-24 12:51:02 +02:00
JC Brand
846dfd6762 Allow subdomains to be passed for domain whitelists 2021-06-24 12:36:51 +02:00
JC Brand
e00bf3da36 Make sure unread messages are cleared when showing a chat 2021-06-23 17:18:32 +02:00
JC Brand
9e21813251 Move tests into new file 2021-06-23 17:11:13 +02:00
JC Brand
3d3242c00d Bugfix. Images automatically load in modal 2021-06-23 13:24:05 +02:00
JC Brand
522998bade converse-roster: dedupe group names 2021-06-23 12:02:47 +02:00
JC Brand
629f382642 converse-roster: Move functions to utils 2021-06-23 12:02:47 +02:00
JC Brand
ad96db994e Fix failing tests on Travis 2021-06-23 10:52:32 +02:00
JC Brand
958d98a1a1 Use mock method in test 2021-06-22 17:04:27 +02:00
JC Brand
fb6bafdf6c Styling: Fix an offset bug
That caused empty inline code hints to be considered valid.

Also update the tests that were failing due to the changes in the
previous commit.
2021-06-22 16:54:05 +02:00
JC Brand
6dea5959cc Use API to get chat/room models in components 2021-06-22 14:47:35 +02:00
JC Brand
afd737f965 Fixes #2520 2021-06-22 12:50:50 +02:00
JC Brand
8de6e78729 In converse-muc-chatarea, use API to get room
and handle asynchronicity.
2021-06-18 11:56:35 +02:00
JC Brand
be8a47b672 Avoid rendering borders for empty unfurl 2021-06-18 11:37:33 +02:00
JC Brand
cf11f2588c Rename method 2021-06-18 11:35:38 +02:00
JC Brand
bb60f8cff4 Move trigger out of while loop 2021-06-18 10:21:03 +02:00
JC Brand
42b15497fc New event historyPruned 2021-06-18 10:07:30 +02:00
JC Brand
f598b7d267 Fix function not being exported 2021-06-17 16:32:58 +02:00
JC Brand
9349ba200e Update travis badge link 2021-06-17 16:07:23 +02:00
JC Brand
619fb538d7 Show video download URL 2021-06-17 15:50:10 +02:00
JC Brand
095d9b60cd Render audio from URLs in messages 2021-06-17 15:24:25 +02:00
JC Brand
33b426c79e Render videos from URLs in messages 2021-06-17 14:06:18 +02:00
JC Brand
2ac49fb9a5 Bugfix. Images being rendered when they shouldn't 2021-06-17 14:06:18 +02:00
JC Brand
b071a0e22f MAM: Prevent multiple simultaneous queries when scrolling up 2021-06-17 11:39:20 +02:00
JC Brand
b6f2662ad7 Set 'scrolled' flag on model.ui
This prevents it from being persisted across page loads and makes more
sense logically.

Also move markScrolled to utils and MUC unread messages indicator to bottom panel.
2021-06-17 11:39:20 +02:00
JC Brand
5ea9564cc3 Add new configuration setting prune_messages_above
If set to a positive integer, the chat history will be kept to that size
by removing older messages.

This happens as new messages come in (as long as the chat isn't scrolled up)
and when the user scrolls down.

Also add the `pruning_behavior` setting
2021-06-17 11:39:20 +02:00
JC Brand
85a651ae79 Move functions to utils 2021-06-17 11:35:06 +02:00
JC Brand
dc711d494f Add a placeholder to indicate a gap in the message history
The user can click the placeholder to fill in the gap.
2021-06-17 11:35:06 +02:00
JC Brand
14f0ed43c5 Add dayjs as dependency to @converse/headless 2021-06-16 14:47:34 +02:00
JC Brand
6f318bc86d Fix reference error 2021-06-16 14:47:34 +02:00
JC Brand
bbc952b265 Fix MUC and headlines heaidngs, so that they still work
as ElementViews, since I ran out of time converting them to lit
components as well.

This reverts commit 1121a90af0.
2021-06-15 11:09:34 +02:00
JC Brand
1121a90af0 Revert "Turn heading into a lit component"
This reverts commit 969b2f2e11.
2021-06-15 10:52:17 +02:00
JC Brand
969b2f2e11 Turn heading into a lit component 2021-06-15 10:33:33 +02:00
JC Brand
8907adc236 Move method to utils 2021-06-15 10:03:10 +02:00
JC Brand
c8304497b5 Remove onStatusMessageChanged handler
It's no longer necessary and calls a method that doesn't exist anymore.
2021-06-15 09:59:40 +02:00
JC Brand
68f0be996f Let chats be closed by calling close on the models
Instead of on the views/components.

We still have `close` methods on the components, but they are just
event handlers and not external API methods to be called by other code.
Instead `close` should be called on the model.
2021-06-15 09:59:40 +02:00
JC Brand
9fb92080f2 Get rid of the APIs to fetch chat views
This is largely a leftover from the Backbone.View days and makes less
sense now that the UI is componentized.

Ideally we don't want to call commands on the "views themselves, instead
we should be working on the the models and let the "views" update
themselves automatically.

Also, given that the `jid` attribute on the chat views might change,
especially when rendered declaratively in other frameworks like React,
a view might not be available at times where we previously might have
expected it to be (since it's been repurposed for a different JID).
2021-06-15 09:59:40 +02:00
JC Brand
ba1b712fee Move functions to utils 2021-06-14 12:03:27 +02:00
JC Brand
543cf9066a Bugfix. TypeError: cannot read property 'length' of undefined 2021-06-14 10:50:58 +02:00
JC Brand
bccd4a81b8 Add missing test file 2021-06-11 16:55:37 +02:00
JC Brand
17d9d2766d BUgfix. undefined used as store prefix 2021-06-11 16:53:19 +02:00
JC Brand
2bbb889196 Unfurls fix 2021-06-10 13:37:11 +02:00
JC Brand
ff1b6d3adf MUC: Don't first check if we're registered before unregistering
The IQ stanza being sent to check was in any case incorrect and it
doesn't seem necessary.
2021-06-10 10:40:45 +02:00
JC Brand
39d60f05c3 Remove twitter link from homepage. Make navbar more visible 2021-06-10 10:07:19 +02:00
JC Brand
54d6a6af56 Unfurls: gracefully handle missing OGP data 2021-06-09 20:54:08 +02:00
JC Brand
5b3d03bc63 Ran npx browserslist@latest --update-db 2021-06-09 16:41:09 +02:00
JC Brand
878a3b49a7 Prevent multiple 'New messages' dividers from appearing
Would happen when scrolled up and a new message comes in
2021-06-07 19:58:55 +02:00
JC Brand
825e2643ae Use flex-direction: column-reverse
On the `<converse-chat-content>` element. This removes the need for all
the manual scrolling.

Firefox finally supports this feature. Unfortunately Firefox ESR doesn't
yet, but I can't wait anymore.
2021-06-07 19:26:16 +02:00
JC Brand
9bcf5f2947 Scrolling fixes
* Remove extra `_markScrolled` function
* Only try to maintain scrolling position when some non-scrolling change has happened.
2021-06-07 17:54:38 +02:00
JC Brand
c966c49304 Fixes #2500
This wrongly stored value wasn't inlcuded in the published the bundle
because the libsignal store was used, which had the right value for the public key.

Instead, this value was used locally by being passed to the libsignal
session builder to verify signed prekey.
2021-06-07 13:49:21 +02:00
JC Brand
90dff612c7 Re-initialize chat components when jid attribute changes 2021-06-07 12:53:35 +02:00
JC Brand
9e4a4ba2ff Add example for retractOtherMessage 2021-06-07 10:10:19 +02:00
JC Brand
e3612e8c62 Turn the chats into Lit components
Previously they were of type ElementView from @converse/skeletor

The ElementView component is merely a helper to allow us to eventually
migrate everything to Lit
2021-06-04 15:22:52 +02:00
JC Brand
06c4ded063 Get rid of impperative code to render help messages
in 1:1 chat
2021-06-04 13:41:01 +02:00
JC Brand
ff233a5b1c Merge branch 'jcbrand/declarative-scrolling' 2021-06-04 12:59:52 +02:00
JC Brand
982586b0e6 Move protocol tests to plugin 2021-06-04 12:53:03 +02:00
JC Brand
ae5a13bb06 Move emojis tests into plugins 2021-06-04 12:53:03 +02:00
JC Brand
f3efbba26c Create converse-message-form component
More work on making bottom panel sub-components declarative

- Handle auto-completion in the converse-muc-message-form element
- Make message limit indicator a component
- Rename template
2021-06-04 12:53:03 +02:00
ubermanu
2f7dcb6bbc Move decodeHTMLEntities util into headless 2021-06-03 19:23:49 +02:00
JC Brand
623deac3ec Fix race condition in test 2021-06-03 18:36:26 +02:00
JC Brand
58d96c8594 Use intersection observer to remember scrolling position 2021-06-03 18:24:55 +02:00
Christoph Scholz
8701708b53 fix /nick command not working 2021-06-03 17:29:45 +02:00
JC Brand
279a3c3413 Add saveScrollPosition method on ChatContent 2021-06-03 15:32:39 +02:00
JC Brand
fe3e63d8c5 Declarative scrolling and rendering new messages indicator
- Increment `num_unread` when new messages appear while scrolled up
- Set scrolling state in model code (as opposed to view)
2021-06-03 14:16:03 +02:00
JC Brand
ec93e2fff3 Render chat messages loading spinner declaratively
instead of imperatively.

Add new non-persisted UI model for rendering UI changes. Currently only
being used for rendering the spinner
2021-06-03 00:02:33 +02:00
JC Brand
59d55b3526 Add option to deregister nickname when closing a MUC
By setting `auto_register_muc_nickname` to `'unregister'`
2021-06-02 22:06:57 +02:00
JC Brand
0756af2b30 Refactor chat close methods
- Remove the shared base-class method.
- Trigger `chatBoxClosed` on the model
- Send CSN from the model, not the view
2021-06-02 17:55:52 +02:00
JC Brand
1598640c80 Remove line-breaks from message image markup
We use `white-space: pre-wrap` to render the messages, so line-breaks in
the markup add unnecessary space.
2021-06-01 14:56:43 +02:00
JC Brand
994e528b45 Bugfix. Properly escape | character in mentioned nicknames 2021-05-19 14:47:20 +02:00
JC Brand
06f03fc884 MUC: Store disconnection data on the session 2021-05-13 15:45:12 +02:00
JC Brand
698f3a7b15 Bugfix. Can't call tagName on a Strophe.Builder object 2021-05-13 14:41:44 +02:00
JC Brand
c0c8fbac38 Wrongly passed data to the context parameter in hook
Causes `undefined` to be returned from `constructPresence` when `converse-caps` is not enabled
2021-05-13 12:15:39 +02:00
JC Brand
19b34231d4 JSDoc improvements 2021-05-13 11:44:19 +02:00
JC Brand
ad53a3c9a1 Message styling fix
Don't parse text that falls within XEP-0372 references ranges for
message styling hints.
2021-05-13 11:20:03 +02:00
JC Brand
58b59fe263 Move more tests from spec folder 2021-05-12 12:41:19 +02:00
JC Brand
d71ab6d30d Bugfix. Need to pass in group name since this is undefined 2021-05-12 12:26:16 +02:00
JC Brand
2b12f8e257 Use lodash-es everywhere 2021-05-12 12:14:28 +02:00
JC Brand
9e81fa495e Upgrade pluggable.js and skeletor 2021-05-12 12:13:10 +02:00
JC Brand
f40bbbf145 Turn status plugin into folder
Remove the use of an override and add a hook `presenceConstructed` instead
2021-05-11 17:04:15 +02:00
JC Brand
1fc44b9d8e Turn caps plugin into folder.
Move more test files to plugins
2021-05-11 16:18:34 +02:00
JC Brand
7bd0d9a83f Bugfix. Don't re-init bookmarks on reconnection
This causes an empty bookmarks list in the controlbox, because the
collection gets cleared (and then asynchronousy repopulated) while the
`bookmarksInitialized` promise stays `true` (resulting in a race
condition).

Alternative fix could be to clear the bookmarks and recreate the promise
before reconnecting but doesn't seem necessary to do all that work.
2021-05-07 12:27:29 +02:00
JC Brand
c8f0406c84 Refactor bookmark plugins
Mainly moving functions and methods to utils
2021-05-07 12:27:29 +02:00
JC Brand
18e3b618b4 Some light chat views refactoring
- Move `showModeratorToolsModal` method from view to utils
- Move `getNicknameRequiredTemplate` method from view to utils
- Move common `close` code to base class
2021-05-07 11:23:52 +02:00
JC Brand
fdc81fa4ea Use .conversejs instead of .converse-root
as the class that designates standalone Converse components.
2021-05-06 12:21:35 +02:00
JC Brand
dd609c1cec Get the webpack dev server to work again
This required triggering the `converse-loaded` event in the entry.js
file, which means it won't be triggered for `@converse/headless` when
used in isolation.

Not ideal, but probably ok because consumers of `@converse/headless`
should probably import it into their own project in any case.
2021-05-06 12:07:44 +02:00
JC Brand
d0594a6bfc Add new test for <converse-muc> 2021-04-30 18:01:53 +02:00
JC Brand
9c11e0dc32 Use .converse-root class instead of #conversejs id 2021-04-30 17:36:42 +02:00
JC Brand
4bdafb8ea3 Break Sass up into more files
And import where appropriate to allow for custom builds that are still styled properly
2021-04-30 17:36:40 +02:00
JC Brand
8966290369 Don't make bundled dependencies devDependencies
Otherwise you need to manually include them in downstream consumer projects
2021-04-30 14:17:46 +02:00
Shaun Wu
9ea8653ef7 Upgrade to Webpack 3
Had to make various other changes due to incompatibilities.

- Use the new `lit` package instead of `lit-html` or `lit-element`
- Drop `haunted` since it breaks the rules by specifying `type: module`
  but then doesn't import with file extensions
- Use Sass Dart instead of node-sass (fixes #2445)
- Upgrade Karma
2021-04-30 13:50:50 +02:00
dependabot-preview[bot]
fe29a86af9 Upgrade to GitHub-native Dependabot 2021-04-30 09:44:05 +02:00
Shaun Wu
1cb2b1f7a9 Adding configurable url history changing 2021-04-29 11:59:28 +02:00
JC Brand
4870d41aae Apply babel to mergebounce 2021-04-29 10:38:17 +02:00
JC Brand
754f1fcb25 Split smacks plugin up into multiple files 2021-04-28 18:50:54 +02:00
JC Brand
3d58b67517 Use @converse/openpromise 2021-04-28 18:35:08 +02:00
JC Brand
57ccf4c20e Batched writes to IndexedDB
- Update to the latest @converse/skeletor (which uses mergebounce to batch writes)
- Flush storage before logging out
- Flush when reloading the tab
- Create initStorage method
2021-04-28 16:53:50 +02:00
JC Brand
4c804fcf2d Wait on chatBoxesFetched in API
Otherwise we can run into race conditions when using IndexedDB with
mergebounce
2021-04-28 12:05:40 +02:00
JC Brand
1f7fecab21 Make show_images a prop of converse-chat-mesage-body
That way, when the setting changes and we call `requestUpdate` on
`converse-chat-message`, the body will rerender.
2021-04-26 12:08:16 +02:00
JC Brand
d86f3094b9 Fix failing test 2021-04-23 12:05:30 +02:00
JC Brand
4b737c1c93 Disable interval handler when running tests 2021-04-23 12:00:29 +02:00
JC Brand
ff14a706cf Fix parameters signature for onDiscoInfoRequest 2021-04-23 11:49:45 +02:00
JC Brand
8e0701f7bb Fix TypeError
The view isn't yet defined when we call `maybeFocus`. This is in any case
not the right place to call something like this.
2021-04-23 11:49:45 +02:00
JC Brand
a5d428c42d Fix closing MUC from rooms list
View isn't defined if chat is in background
2021-04-23 11:42:30 +02:00
JC Brand
b2445d36d1 Bugfix. pretty_time was undefined 2021-04-23 10:59:50 +02:00
JC Brand
db12e8a1e6 ping: use setInterval to continuously send out pings 2021-04-22 16:27:19 +02:00
JC Brand
f7432672e4 Fix key in vcard mock data 2021-04-22 14:51:33 +02:00
JC Brand
7b49296a24 Bugfix. Avoid creating an undefined store 2021-04-22 14:47:01 +02:00
JC Brand
b678df8d23 Move tests file to plugin folder 2021-04-22 14:41:17 +02:00
JC Brand
a4b90e3ab2 Move tests to headless plugin 2021-04-21 12:25:28 +02:00
JC Brand
458c51b32d Move tests for message image rendering to new file 2021-04-21 12:06:10 +02:00
JC Brand
6af9142810 Move ping plugin into folder 2021-04-21 11:18:48 +02:00
JC Brand
7b7ec45db8 Move disco plugin into folder and import lodash utilities separately 2021-04-21 11:03:22 +02:00
JC Brand
f283dd848e Try to fix failing test on Travis 2021-04-20 10:39:05 +02:00
JC Brand
b2f09f64c3 Use API to get room 2021-04-19 15:23:58 +02:00
JC Brand
3558936b46 Refactor message component to require less attributes 2021-04-16 13:11:30 +02:00
JC Brand
9e90b60a4f Add test case for #2461 2021-04-16 09:47:42 +02:00
JC Brand
a129638fd1 Move MUC styling test to plugin folder 2021-04-16 09:45:10 +02:00
ubermanu
649e813ee8 Fixes an endless loop when styling code blocks with a bad format 2021-04-16 09:44:40 +02:00
JC Brand
943ad96d52 Move tests to plugin folder 2021-04-15 16:42:10 +02:00
JC Brand
fdde708327 Add a new MUC room state: converse.ROOMSTATUS.BANNED
This makes it easier to distinguish between being banned from a room, or
being disconnected for other reasons.
2021-04-15 12:34:00 +02:00
JC Brand
b439ae1cc4 Bugfix. Don't set fake nick...
when creating occupant from affiliation change stanza.

This means that when a presence for that occupant arrives, a duplicate
occupant is created (presumably because the original can't be find due
to the wrong nick being set).
2021-04-14 18:02:41 +02:00
JC Brand
cd9977c94e Add an API for setting affiliations
This allows us to set affiliations in MUCs without having to first enter
the MUC in order to create a `ChatRoom` instance.
2021-04-14 10:44:31 +02:00
JC Brand
383f5c1d60 Extract affiliation-related methods out of the ChatRoom model
and put them together in a utils file
2021-04-14 10:44:31 +02:00
JC Brand
13e19eb7f8 Split omemo plugin into more files 2021-04-12 05:09:44 +02:00
JC Brand
42581b1d12 Split mam-views plugin into multiple files 2021-04-11 21:12:37 +02:00
JC Brand
573cc3e8d9 Split omemo plugin up into multiple files 2021-04-11 21:12:37 +02:00
JC Brand
a67603f689 Move various tests to plugin folders 2021-04-11 21:12:37 +02:00
Giuseppe Pignataro (Fasbyte01)
2b984e7851 Translated using Weblate (Italian)
Currently translated at 98.0% (501 of 511 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/it/
2021-04-09 13:32:58 +02:00
Kim Alvefur
e57bc316d1 Translated using Weblate (Swedish)
Currently translated at 99.6% (509 of 511 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/sv/
2021-04-09 13:32:35 +02:00
Hangyu Feng
ee0628085b Translated using Weblate (Chinese (Simplified))
Currently translated at 98.0% (501 of 511 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/zh_Hans/
2021-04-09 13:31:44 +02:00
Xosé M
b24ece11e5 Translated using Weblate (Galician)
Currently translated at 100.0% (511 of 511 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/gl/
2021-04-09 13:31:08 +02:00
nautilusx
e5240c1a45 Translated using Weblate (German)
Currently translated at 100.0% (511 of 511 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/de/
2021-04-09 13:30:22 +02:00
JC Brand
00f1aae38d Translated using Weblate (Afrikaans)
Currently translated at 100.0% (511 of 511 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/af/
2021-04-09 13:29:24 +02:00
JC Brand
be9db63718 Fixes #2443 2021-04-09 10:17:38 +02:00
JC Brand
548021b556 Only add view to chatboxviews after this.model has been set
Otherwise race-conditions arise where `this.model` is undefined
2021-04-08 10:17:26 +02:00
JC Brand
24e57244d1 Remove the messageSend event 2021-04-08 10:17:02 +02:00
JC Brand
724a6855ed Fixes #2443 2021-04-01 13:05:36 +02:00
JC Brand
e7ddd07d56 Remove unused method 2021-03-31 14:27:44 +02:00
JC Brand
65742d32ec Move icons template to shared folder 2021-03-29 13:16:32 +02:00
JC Brand
6d60a79369 MUC: Move function to utils 2021-03-26 11:34:45 +01:00
JC Brand
ccd60f76c3 Cleanup
- Move top-level functinos to utils files
- Get rid of unused/obsolete overrides
- Only import components there where they're used
- Bump version in package.json
2021-03-26 10:58:51 +01:00
ubermanu
3bfd60a3df Move the httpToGeoUri util into core 2021-03-25 09:08:39 +01:00
JC Brand
3129dd9351 Bugfix. Scroll position not respected in MUC 2021-03-24 14:35:33 +01:00
JC Brand
c2a6b09a25 Use converse-rich-text component to render unfurl descriptions 2021-03-24 12:41:17 +01:00
JC Brand
f897596215 Move files around to try and create some consistency and order 2021-03-24 12:41:17 +01:00
JC Brand
7f5a1d205e Rename MessageText to RichText
since it's now used to render more than just messages
2021-03-24 12:41:17 +01:00
JC Brand
b31eaadfab Add option to converse-rich-text for /me messages 2021-03-24 12:41:17 +01:00
JC Brand
bd8a57e0c3 Use the converse-rich-text component to render the topic 2021-03-24 12:41:17 +01:00
JC Brand
65efe5ad43 Let the message body be rendered with the rich-text directive 2021-03-24 11:27:19 +01:00
JC Brand
41d82a54b6 Create rich text component and directive 2021-03-24 11:13:11 +01:00
JC Brand
864f5fd7d3 Rename file 2021-03-24 10:43:42 +01:00
JC Brand
1fd3e3676a Update the MesageText class to not require a Model object
This allows us to use it to transform any piece of text and not just
text from a chat message.
2021-03-24 10:42:22 +01:00
JC Brand
16e7133e31 update to newer webpack-http-dev-server 2021-03-23 16:18:46 +01:00
JC Brand
6d01a3153e Move relevant files into converse-rootview plugin folder 2021-03-22 14:34:18 +01:00
JC Brand
3c99f1f840 Fixes #2348
Don't automatically hide the first MUC opened in uni-view
2021-03-22 11:39:17 +01:00
JC Brand
b28594a976 Import toolbar styles in the component 2021-03-19 15:10:57 +01:00
JC Brand
3bdae848b3 Fix this binding bug 2021-03-19 13:02:56 +01:00
JC Brand
89906f4826 Update bootstrap to version 4.6.0
Also update webpack-merge, webpack-cli and @babel/plugin-proposal-nullish-coalescing-operator
2021-03-19 13:02:56 +01:00
JC Brand
fde371b90f Remove apparently unnecessary tooltip bootstrap scss 2021-03-19 12:47:32 +01:00
JC Brand
453b993cfb Split up CSS into more files 2021-03-19 12:47:32 +01:00
JC Brand
90ab412628 Move fullscreen styles into relevant plugin 2021-03-19 12:47:32 +01:00
JC Brand
1b91d9b69e Move roster, bookmarks and minimize styles to plugin folders 2021-03-19 11:53:22 +01:00
JC Brand
79a4006a61 Move headlines scss to plugin folder 2021-03-19 11:48:48 +01:00
JC Brand
73c4c21533 Move MUC styles to plugin folder 2021-03-19 11:47:13 +01:00
JC Brand
b189fc83b0 Move chatbox styles to plugin folder 2021-03-19 11:43:16 +01:00
JC Brand
005cf4dc96 Move controlbox styles to plugin folder 2021-03-19 11:36:19 +01:00
JC Brand
f805f0d1ef Move sass files into src and closer to the relevant components 2021-03-19 11:28:35 +01:00
JC Brand
9d5d94a8f4 Update to latest Skeletor with localforage-setitems optimization 2021-03-18 16:21:15 +01:00
JC Brand
e896361b2f Remove the No message history available message
It's misleading because it shows before MAM has finished (which also causes
flashing)

Showing it only after MAM has finished would be preferable but too much
work, so I'm removing it for now.
2021-03-17 12:36:56 +01:00
JC Brand
224336e232 Remove last backbone-like declarative event handler from the MUC view 2021-03-17 12:28:16 +01:00
JC Brand
05abb1dae9 Move method from view to model 2021-03-17 11:27:13 +01:00
JC Brand
8f21b020b1 Move method to view unread messages to relevant component 2021-03-17 11:20:13 +01:00
JC Brand
7126ee2df9 Add new component for navigating back to controlbox
in small viewports
2021-03-17 11:19:58 +01:00
JC Brand
19e701683d Turn the controlbox toggle into a lit-element component 2021-03-17 10:37:19 +01:00
JC Brand
d548180f20 Add support for more languages, 'da', 'sw', 'th' 2021-03-17 10:20:19 +01:00
JC Brand
bd452a04e8 Fix more mangled i18n strings 2021-03-17 10:12:55 +01:00
JC Brand
001fe37059 Fix i18n message
Got mangled via search-and-replace
2021-03-17 09:48:16 +01:00
JC Brand
fff431737b Add support for new languages 'fa', 'el', 'lt' 2021-03-17 09:41:58 +01:00
JC Brand
0aec04a9c9 Update po files 2021-03-17 09:34:00 +01:00
Tomáš Obšívač
cc0ddc92b3 Translated using Weblate (Czech)
Currently translated at 77.0% (389 of 505 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/cs/
2021-03-17 09:17:39 +01:00
Reza Almanda
2461d433e8 Translated using Weblate (Indonesian)
Currently translated at 60.7% (307 of 505 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/id/
2021-03-17 09:17:39 +01:00
JC Brand
859d4ff640 Translated using Weblate (Afrikaans)
Currently translated at 100.0% (505 of 505 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/af/
2021-03-17 09:17:39 +01:00
Efterpi Kavvadia
249f0b4e79 Added translation using Weblate (Greek) 2021-03-17 09:17:39 +01:00
Kornelijus Tvarijanavičius
02a821aa3c Translated using Weblate (Lithuanian)
Currently translated at 62.3% (315 of 505 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/lt/
2021-03-17 09:17:39 +01:00
make-file
1b4787df99 Translated using Weblate (Persian)
Currently translated at 10.6% (54 of 505 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/fa/
2021-03-17 09:17:39 +01:00
make-file
6c39cbca5e Translated using Weblate (Persian)
Currently translated at 10.6% (54 of 505 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/fa/
2021-03-17 09:17:39 +01:00
make-file
e3faa3c443 Added translation using Weblate (Persian) 2021-03-17 09:17:39 +01:00
aitzol berasategi
94e4ff9cdd Translated using Weblate (Basque)
Currently translated at 80.9% (409 of 505 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/eu/
2021-03-17 09:17:39 +01:00
Vincent Finance
bb302b91c4 Translated using Weblate (French)
Currently translated at 100.0% (505 of 505 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/fr/
2021-03-17 09:17:39 +01:00
Lilian Wang
5dc3639831 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (505 of 505 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/zh_Hans/
2021-03-17 09:17:39 +01:00
Juanro49
c3f03e0e3e Translated using Weblate (Spanish)
Currently translated at 93.0% (470 of 505 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/es/
2021-03-17 09:17:39 +01:00
Isak Holmström
3e6634c1e4 Translated using Weblate (Swedish)
Currently translated at 1.1% (6 of 505 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/sv/
2021-03-17 09:17:39 +01:00
Quentin PAGÈS
a1e788b958 Translated using Weblate (Occitan)
Currently translated at 82.7% (418 of 505 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/oc/
2021-03-17 09:17:39 +01:00
LL Magical
5450e0ccde Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (505 of 505 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/pt_BR/
2021-03-17 09:17:39 +01:00
Xosé M
164d2898c9 Translated using Weblate (Galician)
Currently translated at 100.0% (505 of 505 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/gl/
2021-03-17 09:17:39 +01:00
Oğuz Ersen
884b5a7661 Translated using Weblate (Turkish)
Currently translated at 100.0% (505 of 505 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/tr/
2021-03-17 09:17:39 +01:00
Sergiu
76a64898ef Translated using Weblate (Romanian)
Currently translated at 39.4% (199 of 505 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/ro/
2021-03-17 09:17:39 +01:00
zilliu
7e793f9514 Translated using Weblate (Chinese (Traditional))
Currently translated at 99.0% (500 of 505 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/zh_Hant/
2021-03-17 09:17:39 +01:00
zilliu
9555f7610d Translated using Weblate (Chinese (Simplified))
Currently translated at 99.0% (500 of 505 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/zh_Hans/
2021-03-17 09:17:39 +01:00
Zijian Liu
e023c1b47d Translated using Weblate (Chinese (Traditional))
Currently translated at 98.6% (498 of 505 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/zh_Hant/
2021-03-17 09:17:39 +01:00
Xosé M
9e089a5090 Translated using Weblate (Galician)
Currently translated at 100.0% (505 of 505 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/gl/
2021-03-17 09:17:39 +01:00
JC Brand
dde3ef206d Update to Strophe with a SASL fix 2021-03-16 15:10:09 +01:00
JC Brand
c7c077074f Chat: Move two methdos from component to the model 2021-03-16 11:01:10 +01:00
JC Brand
f62b9ab665 Remove debugger statement 2021-03-15 15:22:39 +01:00
JC Brand
56a7050160 Don't insert newline after submitting message 2021-03-15 15:15:20 +01:00
Kim Alvefur
da1eeb9cfa Add XEP-0115 to XEP list
Based on a message from JC in the chat.
2021-03-15 15:02:59 +01:00
Kim Alvefur
96f5b07bec doap: Add versions based on changelog
Versions of Converse.js when support was added, that is.
2021-03-15 15:02:59 +01:00
Kim Alvefur
e0ccba9e24 Add Description Of A Project (DOAP) file
Project summary, including supported XEPs in a machine-readable format,
for automated listings, aggregation of XEP implementation status and
other nice things.

See https://xmpp.org/extensions/xep-0453.html

This list was simply scraped from the README and mangled into XML using
`csv2 | sed | 2xml` and amended with a few other details from e.g.
package.json and links on the website.
2021-03-15 15:02:59 +01:00
JC Brand
35ad4d31a1 Remove erroneous changelog entry 2021-03-15 15:01:49 +01:00
JC Brand
d8daedea0d Render the MUC view component declaratively 2021-03-15 12:34:56 +01:00
JC Brand
851bfc61e0 Move MUC API tests into own file 2021-03-13 12:04:07 +01:00
JC Brand
5006ebcbae Bottom panel fixes
- Restore textarea size when it gets manually cleared
- Don't reload page when pressing send button
2021-03-12 10:14:34 +01:00
JC Brand
69a9adb459 Rename and move some files around 2021-03-12 09:58:17 +01:00
JC Brand
4646956922 Don't render hidden chats 2021-03-11 13:05:03 +01:00
JC Brand
2dbe50fc97 Refactor converse-muc-sidebar
- To only take the MUC JID as attribute
- To be responsible for closing itself
2021-03-11 11:34:52 +01:00
JC Brand
349b6d616d Move functions for resizing the MUC sidebar to converse-muc-chatarea 2021-03-11 11:22:46 +01:00
JC Brand
4ca30c4b93 Create converse-muc-chatarea component 2021-03-11 10:26:09 +01:00
JC Brand
4fd848ff3e Bugfix. Use init settings to check for test env 2021-03-10 12:39:17 +01:00
JC Brand
d3ab68011a Split core.js file into multiple smaller ones
Update storing of app settings. Store settings in a closured
`app_settings` object inside `@converse/headless/shared/settings`

Remove the `_converse.settings` object.
2021-03-09 14:11:28 +01:00
JC Brand
a921e303ac Make sure chat scrolls down once image has loaded 2021-03-08 16:54:09 +01:00
JC Brand
0d9c7bade3 Don't propagate paste events in chat textarea 2021-03-08 11:20:32 +01:00
JC Brand
b19a1e79f5 Security fix update for uri.js 2021-03-08 11:20:07 +01:00
JC Brand
051eeb9980 Don't show list dots for README sponsors 2021-03-08 09:35:44 +01:00
JC Brand
6400710b56 Add links to sponsor sites and show as list 2021-03-05 18:57:58 +01:00
JC Brand
08a47b9ad9 Fix path to logo 2021-03-05 18:46:21 +01:00
JC Brand
68d461bd42 Add the ability to show/hide unfurls 2021-03-05 18:42:14 +01:00
JC Brand
a24aa1487e Add mailbox.org as sponsor 2021-03-05 15:28:23 +01:00
JC Brand
541613d1fe Add more OGP metadata attributes to save 2021-03-04 17:56:24 +01:00
JC Brand
19a9da3032 CSS: Don't show border on empty element 2021-03-04 16:17:19 +01:00
JC Brand
698ad90c43 Move insertIntoTextarea methods from view to bottom panel component
That way we further decouple the various components and make it easier
to use them indepenent of one another.
2021-03-04 15:53:04 +01:00
JC Brand
3e5bd34141 Fixes #2381 2021-03-03 22:25:04 +01:00
JC Brand
a778f3866a Show URL in unfurl card 2021-03-02 13:50:40 +01:00
JC Brand
c90b7a9691 Only render unfurl images from allowed domains
as specified by `show_images_inline` when it's set to an array of
domains.
2021-03-02 11:03:35 +01:00
JC Brand
1bd4572957 Restrict unfurl description to message_limit setting 2021-03-02 11:03:35 +01:00
JC Brand
8dd8c7d1dd Don't show unfurl card if there's nothing to show 2021-03-02 11:03:35 +01:00
JC Brand
64fd0ebcf6 Unfurls: Remove URL check
Url parameters mean that we don't get a match even when the URLs
actually match.

Could potentially use URI.js but gets cumbersome and since we restrict
to metadata coming from the MUC service (which we trust) I think it's OK
to remove it.
2021-03-02 11:03:35 +01:00
JC Brand
68ca5dd279 Unfurl: JID wasn't defined 2021-03-01 22:21:45 +01:00
JC Brand
9bac86fe1a Don't add the same OGP metadata multiple times 2021-03-01 21:31:57 +01:00
JC Brand
16e1f95790 New config setting: muc_show_ogp_unfurls 2021-03-01 14:00:28 +01:00
JC Brand
426bf1d631 Tighten up security around unfurls
Dont render OGP metadata:
- for URLs not actually found in the original message
- from MUC participants (only from the MUC itself)
2021-03-01 11:35:12 +01:00
JC Brand
49837c2da4 Ensure that help messages are always shown 2021-02-24 16:34:46 +01:00
JC Brand
ce1c5ec7f6 Updates #2413
Wrap `history.start` in try/catch clause.
2021-02-24 15:48:11 +01:00
JC Brand
d8cab006c8 Move methods to utils
So that they can also be used independently of the components
2021-02-24 15:18:09 +01:00
JC Brand
d335a11119 Move more muc templates to plugin folder and use dashes 2021-02-24 09:51:37 +01:00
JC Brand
4d0012f672 Two small changes
- Fix controlbox spec to work with newer Jasmine
- Don't import Strophe in the non-headless code
2021-02-24 09:12:31 +01:00
JC Brand
c11b3d03f4 Make sure dist/converse-headless.min.js gets built
Fixes #2377
2021-02-24 07:57:56 +01:00
JC Brand
5cab477bf4 fixes #2396: @converse/headless wrongly depends on CustomElement from the view layer 2021-02-24 07:36:10 +01:00
Dele Olajide
61dacfd2a5 fix #2409 - Integrate App Badging API for unread messages 2021-02-24 06:55:59 +01:00
JC Brand
8d74e063af Don't import the entire chatview plugin for the muc-views one 2021-02-24 06:35:49 +01:00
JC Brand
ccfa00d7b8 mod_ogp now sends messages with type="groupchat" 2021-02-23 11:07:00 +01:00
JC Brand
f158a996f4 Turn converse-chatboxes plugin into folder 2021-02-22 21:07:54 +01:00
JC Brand
ae3b2c597d Bugfix. Login form is shown after reconnection 2021-02-22 20:53:59 +01:00
JC Brand
f4bcfa5c44 Move various template files into plugin folders 2021-02-22 20:37:13 +01:00
JC Brand
16edc2954d Add support for rendering unfurls via Prosody's mod_ogp
See here: https://modules.prosody.im/mod_ogp.html
2021-02-22 17:55:20 +01:00
JC Brand
c69eb6e1bf Split ad-hoc commands code into smaller files 2021-02-16 13:51:59 +01:00
JC Brand
de4fd466dc Move more MUC related views and components to muc-views plugin 2021-02-16 13:46:25 +01:00
JC Brand
c43969fece Move MUC sidebar component to plugin folder
and fix update issue where occupants weren't being shown in the sidebar
when reloading the page
2021-02-12 15:01:00 +01:00
JC Brand
3ae71a45a2 Move chatbox template to chatview plugin folder 2021-02-12 14:38:26 +01:00
JC Brand
a8a2bb4681 Componentize the chat headings 2021-02-12 14:32:55 +01:00
JC Brand
906fa93812 MUC: combine two methods doing roughly the same thing 2021-02-12 14:32:55 +01:00
JC Brand
9ce4092a7c Turn the bottom panel into a custom element 2021-02-12 14:32:55 +01:00
JC Brand
94bc087f50 Move MUC templates to the plugin folder 2021-02-11 20:25:20 +01:00
JC Brand
8b052e20b9 Fix tests by pinning to latest @converse/skeletor 2021-02-10 16:14:34 +01:00
JC Brand
45e0ba7f9b Use this.listenTo instead of api.listen.on in components
So that event handlers are automatically deregistered when the component is dismounted.
2021-02-10 11:44:04 +01:00
JC Brand
a32b7b64bf Fix display of lgoged-out controlbox in fullpage mode 2021-02-10 11:37:48 +01:00
JC Brand
78fb5935c7 Handle scrolling down in converse-chat-content component 2021-02-09 18:20:52 +01:00
JC Brand
b2ac138c88 Remove reference to view.el in tests 2021-02-09 16:41:39 +01:00
JC Brand
95c14e5a26 Don't pass chatview object to converse-chat-content
and any child components.

This makes it easier to use these components independently of one
another and the overarching view.
2021-02-09 16:40:00 +01:00
JC Brand
f81292e955 Bugfix in window state change handler 2021-02-09 15:48:21 +01:00
JC Brand
790caf9f5a Render converse-chat-content declaratively 2021-02-09 15:48:21 +01:00
JC Brand
18e48be5c4 Move CSS fixes before merge 2021-02-09 15:48:21 +01:00
JC Brand
3f24720633 Use repeat directive to render roster items 2021-02-09 15:48:21 +01:00
JC Brand
28fb2472a4 Chats: use repeat directive 2021-02-09 15:48:21 +01:00
JC Brand
f33fa1e9fc Fix more tests 2021-02-09 15:48:21 +01:00
JC Brand
22b6b4b502 minchats: Use utility methods instead of mixins
Various fixes to chat minimization
2021-02-09 15:48:21 +01:00
JC Brand
7abc81f8a4 MUC: Wait until occupants are fetched before updating them 2021-02-09 15:48:21 +01:00
JC Brand
ea6e370347 MUC: Fix error message logging 2021-02-09 15:48:21 +01:00
JC Brand
9f5dbad589 Turn roster into a custom element 2021-02-09 15:48:21 +01:00
JC Brand
7407a5a681 Fix auto-insert into converse-root 2021-02-09 15:48:21 +01:00
JC Brand
b8d710800a Move more methods from ChatBoxView to shared base class 2021-02-09 15:48:21 +01:00
JC Brand
bb317d1abb Combine RoomsPanel with RoomsList element 2021-02-09 15:48:21 +01:00
JC Brand
b31f334109 Fix event handlers in BookmarksView 2021-02-09 15:48:21 +01:00
JC Brand
05c00c5e1c Call minimize on the model
Fix minimizing by listening to change event

Fixes around showing/hiding and minimizing/maximizing

Don't trigger a `show` event on the model to show a chat, instead rely
on the `hidden` attribute which causes a rerender and will show/hide
chats.
2021-02-09 15:48:21 +01:00
JC Brand
704b50fb3e Turn HeadlinesBox into a custom element 2021-02-09 15:48:21 +01:00
JC Brand
fa7443be95 Don't render unnecessary components when not in overlayed view mode
Specifically `converse-minimized-chats` and `converse-controlbox-toggle`
2021-02-09 15:48:21 +01:00
JC Brand
d1c807ec79 Fixes to the bookmarks-list view 2021-02-09 15:48:21 +01:00
JC Brand
66abe309f6 Fix order for the minimized chats widget 2021-02-09 15:48:21 +01:00
JC Brand
336adac1ef CSS: fix order of boxes in overlayed view mode 2021-02-09 15:48:21 +01:00
JC Brand
d6c0129c86 Various CSS fixes 2021-02-09 15:48:21 +01:00
JC Brand
fd2f253c09 Add .chatroom class to converse-muc and remove .logged-out to controlbox 2021-02-09 15:48:21 +01:00
JC Brand
a029ece808 Controlbox related bugfixes 2021-02-09 15:48:21 +01:00
JC Brand
e64798208f Remove overrides of renderLoginPanel
which has also been removed earlier
2021-02-09 15:48:21 +01:00
JC Brand
be9016a081 Fix switching between login and register panels 2021-02-09 15:48:21 +01:00
JC Brand
75b8a16465 Fix CSS and work on declaratively rendering the controlbox toggle 2021-02-09 15:48:21 +01:00
JC Brand
a59920e6e5 Turn XMPPStatusView into the converse-user-profile component 2021-02-09 15:48:21 +01:00
JC Brand
6ca2183e24 Remove unneeded ControlBoxPane view 2021-02-09 15:48:21 +01:00
JC Brand
bb7d1c5cba Turn login and register panels into element views 2021-02-09 15:48:21 +01:00
JC Brand
0ecd86ecf7 Turn MinimizedChatsView into an ElementView subclass 2021-02-09 15:48:21 +01:00
JC Brand
ccfb29f1b3 Turn BookmarksView into a custom element 2021-02-09 15:48:21 +01:00
JC Brand
b9bf577ccd Turn rooms list into a custom element 2021-02-09 15:48:21 +01:00
JC Brand
7f869ea72d Make the headlines panel an ElementView
Don't manually insert HeadlinesBoxView
we'll have to convert it to an ElementView
2021-02-09 15:48:21 +01:00
JC Brand
dea2eea919 Componentize dragresize 2021-02-09 15:48:21 +01:00
JC Brand
1949356ede Work on turning chat views into custom elements
The eventual goal is to avoid UI-related stanza processing if the relevant chats
aren't in the DOM.

With the current architecture, chatboxes are created (and the stanzas
related to them processed) even if `#conversejs` isn't in the DOM.

* Initial work on making controlbox an element
* Create a shared base class
* Ceate ChatBoxViews proxy
* Update sass now that certain classes are moved to converse-chats element
2021-02-09 15:48:21 +01:00
JC Brand
eb65f75f45 Move headlines panel template to plugin 2021-02-09 15:48:21 +01:00
Ariel Fuggini
758c46c5aa Fixes infinite loop bug when appending .png to allowed image urls 2021-02-09 15:38:06 +01:00
JC Brand
581f892613 Add JSDoc string 2021-02-06 11:26:25 +01:00
JC Brand
0a1cbf87b8 MUC: Ensure that MAM query is from latest cached messages
In some cases a race condition can occur where a new message is received
before the MAM query starts.

Previously, the newly received message would be considered the latest
message to query from, thereby causing a gap in the history.
2021-02-03 10:27:46 +01:00
JC Brand
5feaab9a95 MUC: Add test for showing cached messages before entering 2021-02-02 15:12:31 +01:00
JC Brand
a294827211 Make sure Notification spy has relevant methods 2021-02-02 10:30:13 +01:00
JC Brand
9568d57e5f Pass message attrs to shouldNotifyOfGroupMessage 2021-02-01 17:50:46 +01:00
JC Brand
5d1b5ac6c9 Notifiations: Add new hook shouldNotifyOfGroupMessage 2021-02-01 17:14:35 +01:00
JC Brand
50dda3244e Move converse-notifications plugin into a folder and split up 2021-02-01 16:15:55 +01:00
JC Brand
7f851208aa Move converse-roster plugin into folder and split up 2021-01-26 14:34:36 +01:00
JC Brand
7199e63fd7 Move converse-profile plugin into folder 2021-01-22 15:49:16 +01:00
JC Brand
85bd192f3c Move converse-minimize into a folder
Also, use utility methods instead of adding a mixin to ChatBoxViews
(since we're planning on removing it).
2021-01-18 12:56:17 +01:00
JC Brand
1a88aff179 Decided to still collapse newlines...
and to solve the offset issue by replacing excessive newlines with
the zero-width space unicode character.
2021-01-18 12:18:33 +01:00
JC Brand
61bb0cfab7 Don't collapse newlines.
This causes index offset issues with any rich elements in the message.

We could try to fix the offsets, or alternatively replace the collapsed
newlines with spaces (to maintain the original offsets), but I don't
think it's worth the effort since I'm not sure that it's a good idea to
collapse newlines in the first place.
2021-01-18 11:27:01 +01:00
JC Brand
2c7b220453 RAI: Always send the presence to enable RAI when leaving a MUC
Looking at the Prosody code, it appears to be cheap since
Prosody will do nothing if you're already registered and this works
around a bug in mod_muc_rai where events aren't fired for each resource
of the same joined nick joining or leaving the MUC.
2021-01-15 13:55:40 +01:00
JC Brand
8bd2114d8a MUC has its own method for sending markers 2021-01-15 11:39:09 +01:00
JC Brand
c0249b9c28 New configuration setting send_chat_markers
Can be used to fine-tune which (if any) of the XEP-0333 chat markers
will be sent out.
2021-01-15 11:11:38 +01:00
JC Brand
26c1c483da MAM fix: Get newest page when not paging
This is done by using `before: ''` and filtering by `start`.
Otherwise we get the oldest page.
2021-01-13 13:33:28 +01:00
JC Brand
dcd1407109 New config setting mam_request_all_pages 2021-01-13 10:42:22 +01:00
JC Brand
b5b35a97c6 Bugfix. Ad-hoc form fields didn't render.
Also... clear info message before executing ad-hoc command so that user
gets visiual indication.
2021-01-11 15:06:51 +01:00
JC Brand
58c5e9676a Handle forwarded mentions coming from the MUC, not the host 2021-01-08 18:25:36 +01:00
JC Brand
5e6a6ba6ac Fix failing bookmark tests 2021-01-08 14:36:48 +01:00
JC Brand
9a2678450a Move converse-bookmarks plugin into folder 2021-01-08 14:28:36 +01:00
JC Brand
bb8c7423b6 Ignore XEP-0437 indicators and forwarded mentions in a joined MUC
Otherwise the mentions will be counted twice.
2021-01-08 10:38:03 +01:00
JC Brand
2f5cc3b271 Bugfix. Make sure arguments are passed to all triggered events 2021-01-08 09:39:35 +01:00
JC Brand
11023dfef9 Don't clear occupants when leaving a MUC, only when closing it
Otherwise, when leaving as part of RAI and in a MUC where we only get
presence info based on probes, we lose occupant info that doesn't get
recreated when we rejoin.
2021-01-07 15:08:29 +01:00
JC Brand
2da2dbff71 Move converse-bookmark-views into folder 2021-01-07 13:29:55 +01:00
JC Brand
eaa67dab91 Bugfix. Filtering of contacts stopped working after refactoring 2021-01-07 12:52:56 +01:00
JC Brand
680701667e Bugfix: Image modal didn't have src attr on render 2021-01-06 15:07:19 +01:00
JC Brand
3f47c4d3dd Use real JID in XEP-0372 references only when the MUC is non-anonymous 2021-01-04 14:24:23 +01:00
JC Brand
d55c4eb66e Remove lodash template loader 2020-12-30 19:36:38 +01:00
JC Brand
9a2ded5a9a Remove global lodash 2020-12-29 15:12:45 +01:00
JC Brand
c1847a0b34 Use lit-html to render room description in modal 2020-12-29 12:49:09 +01:00
JC Brand
5e0b05356f dragresize: use lit-html to render the template 2020-12-29 12:40:16 +01:00
JC Brand
12bb9375f4 Move converse-dragresize plugin to folder 2020-12-29 12:38:17 +01:00
JC Brand
f2ef8c7206 controlbox: render the toggle via lit-html 2020-12-29 12:23:39 +01:00
JC Brand
3f40098144 Render logo for registration form
Also fix showing of version number in login form
2020-12-29 12:16:23 +01:00
JC Brand
9372ad2dff register: Use lit-html to render templates 2020-12-29 11:49:25 +01:00
JC Brand
e31fa1f7dd Move converse-register plugin to folder 2020-12-29 10:36:59 +01:00
JC Brand
828eac1e72 rosterview: Move more lodash templates to lit-html 2020-12-28 21:20:18 +01:00
JC Brand
bb3ac36098 Render the roster container and filter with lit-html
This is the first commit that makes use of the `ElementView` from
Skeletor, which lets us turn views into custom elements.
2020-12-28 20:56:37 +01:00
JC Brand
794a709690 Move converse-rosterview plugin into folder 2020-12-28 19:46:40 +01:00
JC Brand
da131715ba Use lit-html to render form fields 2020-12-28 18:25:51 +01:00
JC Brand
62dbb1062f Add support for protoXEP: MUC mention notifications 2020-12-21 14:02:43 +01:00
JC Brand
6b9c718df7 RAI: Handle MUCs that start out hidden
When a MUC starts out hidden, we first need to join in order to find out
whether we're affiliated before we can know whether we should enable RAI
or join the MUC as usual.
2020-12-21 12:07:00 +01:00
JC Brand
986f7550f3 Clear messages upon reconnection as late as possible
To avoid a long empty flash while new messages are being fetched again.
2020-12-17 16:23:47 +01:00
JC Brand
1f476b8793 Move converse-mam plugin into own folder 2020-12-17 14:48:50 +01:00
JC Brand
8db1f3e3f3 MAM: refactor to functions instead of extending chats with methods 2020-12-17 14:10:28 +01:00
JC Brand
4349b016eb MUC: Only clear messages when MUC is left intentionally
by the user, and not as part of cleanup during logout or when leaving
automatically in order to receive XEP-0437 activity indicators.
2020-12-17 14:00:18 +01:00
Licaon_Kter
c09511adb8 Fix typo in xep-0437 link 2020-12-17 13:33:45 +01:00
JC Brand
18e6ebe9af MUC: Bugfix, don't set state to entered on unavailable presence 2020-12-17 13:04:24 +01:00
JC Brand
594332181b Call 'clearMessages' 2020-12-17 13:04:24 +01:00
JC Brand
2121766623 More RAI improvements
- Add test for incoming RAI message
- Only enable RAI if the user is affilated in MUC being left
- Handle error presence indicating a resouce-constraint
- Don't unregister stanza handlers in `leave`, since we still want to
  listen to RAI-related stanzas. Instead unregister upon the `destroy`
  event.
2020-12-17 13:04:24 +01:00
JC Brand
fe365a6561 Move converse-roomslist plugin into folder 2020-12-16 14:05:34 +01:00
JC Brand
eed9ee8033 RAI: Add tests 2020-12-16 13:48:14 +01:00
JC Brand
e80afbfe39 Move MUC and stanza utils into shared and plugin-specific files 2020-12-14 16:30:13 +01:00
JC Brand
e8eea6324e MUC: Send XEP-0333 markers with the MUC stanza id
See: https://xmpp.org/extensions/xep-0333.html#rules-muc
2020-12-14 16:30:13 +01:00
JC Brand
c457081597 WIP: Add support for XEP-437: Room Activity Indicators
- Send marker for last message before leaving and before subscribing to RAI
- clear cache of RAI-subscribed domains on reconnection
2020-12-14 13:11:24 +01:00
JC Brand
e6e416306e Properly handle child nodes for api.presence.send 2020-12-14 13:11:24 +01:00
JC Brand
2f244da8b1 Fix failing test 2020-12-11 14:06:37 +01:00
JC Brand
14c9b2f4ae Clear message cache when closing a MUC 2020-12-11 13:57:16 +01:00
JC Brand
3b00a0e30d Bump lit-element and xss 2020-12-10 17:29:47 +01:00
JC Brand
b771827d2a Fix corrections tests 2020-12-10 17:13:40 +01:00
JC Brand
5a82478381 Declare sizzle as a dependency for @converse/headless 2020-12-10 17:13:40 +01:00
JC Brand
c855d2f4ce Updates #2350 Avoid bundling Strophe twice
by not importing Strophe outside of @converse/headless
2020-12-10 16:32:01 +01:00
JC Brand
4ece50d07c Add ability to pass child nodes to api.user.presence.send 2020-12-10 14:39:24 +01:00
JC Brand
23a4a20dc2 Bugfixes
Mesage versions modal didn't open on subsequent clicks
Autocomplete: avoid undefined error
2020-12-10 14:12:20 +01:00
JC Brand
bb3f52d2f2 Move the autocomplete code into ./shared
And remove it as a plugin.
2020-12-10 11:17:57 +01:00
JC Brand
9174be8ff3 Styling: Use only "local" offset for mentions 2020-12-09 18:09:38 +01:00
JC Brand
af2df84fc1 Styling: Fix offsetting of mentions mixed in with styles 2020-12-09 18:05:08 +01:00
JC Brand
8572c86941 Styling: Trim leading whitespace inside blockquote
As demanded by XEP-0393
2020-12-09 15:11:54 +01:00
JC Brand
58586ab2e4 Styling: quotes should start on newlines
And when nested, have no spaces between them.
2020-12-09 14:19:31 +01:00
JC Brand
240fab99f4 Split chatboxviews/index.js into multiple files 2020-12-08 10:16:34 +01:00
JC Brand
e31d5ba939 Move converse-headlines-view plugin into a folder 2020-12-08 09:50:17 +01:00
JC Brand
c0fafcec70 Move converse-muc into a folder 2020-12-08 09:50:17 +01:00
JC Brand
e8536ebc88 Move converse-muc-views plugin into own folder 2020-12-08 09:50:17 +01:00
JC Brand
2b6c56f148 Move converse-chatview plugin into folder 2020-12-08 09:50:17 +01:00
JC Brand
ecfaba0781 Move converse-chatboxviews plugin into folder 2020-12-08 09:50:17 +01:00
JC Brand
4c1813d6d4 Move converse-controlbox plugin into folder 2020-12-08 09:50:17 +01:00
JC Brand
e3ebde9741 Move converse-chat plugin into folder 2020-12-07 16:30:11 +01:00
JC Brand
01e03fc677 Bump to Strophe 1.4.1 2020-12-04 14:06:04 +01:00
JC Brand
d47c72711b Document the button hooks 2020-12-03 16:56:54 +01:00
JC Brand
824bf2ed30 Move all plugin files to ./plugin folders
Rename converse-core.js to core.js
2020-12-03 16:41:15 +01:00
JC Brand
5dc7a442f6 New hook getMesageActionButtons
Allows 3rd party plugins to add more buttons to the message actions dropdown
2020-12-03 16:08:54 +01:00
JC Brand
c0dc8c8915 Bump 3rd party dev dependencies 2020-12-03 12:25:43 +01:00
Xavi Ferrer
f4b6b93b8b update info messages visibility 2020-12-03 11:45:25 +01:00
JC Brand
160ab3452e Rename ids of two modals 2020-12-03 11:43:04 +01:00
JC Brand
1a161ad2c7 Add api for managing modals
Set passed-in properties on modal
2020-12-03 11:36:02 +01:00
JC Brand
b18cc6bcc5 Move modals and their templates into ./modals/ 2020-12-03 11:02:35 +01:00
JC Brand
34cba68432 Allow user modals to be opened from message headings 2020-12-03 11:02:35 +01:00
JC Brand
5a3aaeb056 Prevent default when opening chat via xmpp: URI 2020-12-03 10:45:08 +01:00
JC Brand
01ee942920 Styling fixes
* Calculate proper length for :geo URI matches
* Don't strip out line-break after quotes, instead use CSS `display: inline-block`
2020-12-01 10:21:21 +01:00
JC Brand
21dfd8a325 Bugfix: Set protocol after discovering connection methods
Otherwise if an endpoint was passed in with `converse.initialize`, then
that endpoint's protocol is (wrongly) used.
2020-11-30 18:21:33 +01:00
JC Brand
f5707c51c0 Update lt translations based on #1844 2020-11-30 14:49:30 +01:00
JC Brand
c608958eb3 Handle special case of two @ signs preceding a nickname 2020-11-27 22:06:22 +01:00
JC Brand
f86efca9a6 autocomplete: Use regex instead of hardcoded list...
to determine valid characters to form a boundary before an `@` mention

Also fixed an issue with mentions looking like they're part of URLs, by
first processing mentions separately.
2020-11-27 22:06:22 +01:00
Xavi Ferrer
8b9c97745f Allow selected characters to precede a mention 2020-11-27 14:12:29 +01:00
JC Brand
35db01d316 Styling: Take offset into consideration when adding templates 2020-11-27 11:12:19 +01:00
JC Brand
30e784b8ec Fix: use_system_emojis was false but unicode emojis shown in picker 2020-11-27 10:26:06 +01:00
JC Brand
33f62bb93c Update changelog for previous revert and add title for img emoji 2020-11-26 14:25:54 +01:00
JC Brand
a65da05094 Revert "fix emoji-picker for use_system_emojis==false"
This reverts commit e0088a45da.
2020-11-26 14:19:30 +01:00
JC Brand
c002600ac5 Rename update_title setting to show_tab_notifications 2020-11-25 16:30:52 +01:00
JC Brand
fb316ff010 Styling: Remove line-break at end of blockquote
since the DOM element breaks the line already
2020-11-25 16:12:00 +01:00
JC Brand
d2074afe9a Document breaking changes to message transformation events 2020-11-25 14:53:27 +01:00
JC Brand
f9650f33be Add support for XEP-0393 message styling
Fixes #1083

Directives are rendered as templates and their bodies are MessageText instances.
We thereby achieve the necessary nesting of directives (and other rich
elements inside directives) by letting each directive
body render itself similarly to how the whole message body is rendered.
2020-11-24 16:06:48 +01:00
JC Brand
7ae2b48da9 Move /me message tests to own file
Test mention inside a /me message
2020-11-24 16:06:48 +01:00
JC Brand
357b6406e2 Postrelease 2020-11-23 10:29:42 +01:00
JC Brand
db1905fdb6 Release 7.0.2 2020-11-23 10:18:35 +01:00
nautilusx
c0e0a209e4 Translated using Weblate (German)
Currently translated at 100.0% (505 of 505 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/de/
2020-11-23 10:10:15 +01:00
Allan Nordhøy
77b737ad87 Translated using Weblate (Norwegian Bokmål)
Currently translated at 71.4% (361 of 505 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/nb_NO/
2020-11-23 10:10:15 +01:00
JC Brand
4e3a81d697 Fixes #2337
Newly opened headline chat isn't hidden by default in fullscreen view

Also include some CSS fixes for fullscreen headlines boxes
2020-11-19 13:20:02 +01:00
JC Brand
1b50696ca7 Make sure all necessary files are included in the NPM package 2020-11-19 13:12:13 +01:00
Yaron Shahrabani
2918a175ee Translated using Weblate (Hebrew)
Currently translated at 75.6% (382 of 505 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/he/
2020-11-19 12:44:45 +01:00
JC Brand
a70e82c82b Mention new translations in changelog 2020-11-19 11:44:35 +01:00
Oğuz Ersen
b03ea65943 Translated using Weblate (Turkish)
Currently translated at 100.0% (505 of 505 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/tr/
2020-11-19 11:41:42 +01:00
Xosé M
f2e1b5983e Translated using Weblate (Galician)
Currently translated at 100.0% (505 of 505 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/gl/
2020-11-19 11:41:13 +01:00
JC Brand
4520a04be9 Postrelease 2020-11-19 11:37:56 +01:00
JC Brand
85375842a8 Release 7.0.1 2020-11-19 11:23:04 +01:00
J. Lavoie
93d03106b6 Translated using Weblate (Portuguese (Brazil))
Currently translated at 99.8% (501 of 502 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/pt_BR/

Translated using Weblate (Spanish)

Currently translated at 90.6% (455 of 502 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/es/

Translated using Weblate (Finnish)

Currently translated at 86.0% (432 of 502 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/fi/

Translated using Weblate (Italian)

Currently translated at 100.0% (502 of 502 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/it/

Translated using Weblate (Polish)

Currently translated at 80.8% (406 of 502 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/pl/

Translated using Weblate (French)

Currently translated at 100.0% (502 of 502 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/fr/
2020-11-18 18:47:44 +01:00
JC Brand
3638056dd7 Added translation using Weblate (Swedish) 2020-11-18 18:47:44 +01:00
Tymofij Lytvynenko
503ec61a04 Translated using Weblate (Ukrainian)
Currently translated at 34.4% (173 of 502 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/uk/
2020-11-18 18:47:44 +01:00
zilliu
3fa5ae08d5 Translated using Weblate (Chinese (Traditional))
Currently translated at 99.2% (498 of 502 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/zh_Hant/
2020-11-18 18:47:44 +01:00
Balázs Meskó
c82c6961d7 Translated using Weblate (Hungarian)
Currently translated at 100.0% (502 of 502 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/hu/
2020-11-18 18:47:44 +01:00
Emmanuel Gil Peyrot
557ddf974f Translated using Weblate (French)
Currently translated at 99.4% (499 of 502 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/fr/
2020-11-18 18:29:24 +01:00
nautilusx
e56cd9024d Translated using Weblate (German)
Currently translated at 100.0% (502 of 502 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/de/
2020-11-18 18:28:55 +01:00
Andrey
4a692e510e Translated using Weblate (Russian)
Currently translated at 83.0% (417 of 502 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/ru/
2020-11-18 18:28:26 +01:00
Allan Nordhøy
90ab459ad4 Translated using Weblate (Norwegian Bokmål)
Currently translated at 71.7% (360 of 502 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/nb_NO/
2020-11-18 18:27:13 +01:00
Quentin PAGÈS
3201b6865b Translated using Weblate (Occitan)
Currently translated at 82.8% (416 of 502 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/oc/
2020-11-18 18:26:25 +01:00
ssantos
26d33aade2 Translated using Weblate (Portuguese)
Currently translated at 74.3% (373 of 502 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/pt/
2020-11-18 18:25:57 +01:00
Oğuz Ersen
fbf05e9d5e Translated using Weblate (Turkish)
Currently translated at 100.0% (502 of 502 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/tr/
2020-11-18 18:25:34 +01:00
Xosé M
8f2a742a09 Translated using Weblate (Galician)
Currently translated at 100.0% (502 of 502 strings)

Translation: Converse.js/Translations
Translate-URL: https://hosted.weblate.org/projects/conversejs/translations/gl/
2020-11-18 18:21:52 +01:00
JC Brand
16b16a109e Make sure JS files in templates are included in package 2020-11-18 18:00:21 +01:00
Christoph Scholz
e0088a45da fix emoji-picker for use_system_emojis==false 2020-11-18 17:22:14 +01:00
JC Brand
76aa1ef3ec make postrelease 2020-11-18 13:07:51 +01:00
805 changed files with 186508 additions and 141524 deletions

View File

@ -1,7 +1,7 @@
{
"parser": "babel-eslint",
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2017,
"ecmaVersion": 2020,
"sourceType": "module",
"allowImportExportEverywhere": true
},
@ -10,8 +10,12 @@
"jasmine": true,
"es6": true
},
"plugins": ["lodash"],
"extends": ["eslint:recommended", "plugin:lodash/canonical"],
"plugins": ["@typescript-eslint"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended"
],
"globals": {
"Uint8Array": true,
"Promise": true,
@ -21,20 +25,6 @@
"window": true
},
"rules": {
"lodash/prefer-lodash-chain": "off",
"lodash/prefer-lodash-method": "off",
"lodash/import-scope": "off",
"lodash/prefer-constant": "off",
"lodash/prefer-get": "off",
"lodash/prefer-includes": "off",
"lodash/prefer-invoke-map": "off",
"lodash/prefer-is-nil": "off",
"lodash/prefer-lodash-typecheck": "off",
"lodash/prefer-noop": "off",
"lodash/prefer-startswith": "off",
"lodash/preferred-alias": "off",
"lodash/matches-prop-shorthand": "off",
"lodash/prop-shorthand": "off",
"accessor-pairs": "error",
"array-bracket-spacing": "off",
"array-callback-return": "error",

28
.github/CONTRIBUTING.md vendored Normal file
View File

@ -0,0 +1,28 @@
# Contribution Guidelines
Thanks for contributing to [Converse.js](https://conversejs.org)
## Support questions
The Github issue tracker is used for bug reports and feature requests, not for general tech support.
For support, you can join our [XMPP webchat](https://inverse.chat/#converse/room?jid=discuss@conference.conversejs.org).
Instead of the webchat, you can also open the room in your XMPP client, [click here](xmpp://discuss@conference.conversejs.org?join).
You can also ask questions on [StackOverflow](https://stackoverflow.com/questions/tagged/converse.js)
## Contributing Code
Please follow the usual Github workflow. Create a fork of this repository, make your changes and then submit a pull request.
### Before submitting a pull request
Please read the [style guide](https://conversejs.org/docs/html/style_guide.html) and make sure that your code follows it.
### Add tests for your bugfix or feature
Add a test for any bug fixed or feature added.
Tests can be found in various `./tests` folders in the Converse source code.
To run the tests, you can run `make check` on Linux and Mac, or `./node_modules/bin/karma start karma.conf` on Windows.

View File

@ -1,37 +0,0 @@
=======================
Contribution Guidelines
=======================
Thanks for contributing to `Converse.js <https://conversejs.org>`_.
Support questions
=================
Please ask support and setup questions on the mailing list: conversejs@librelist.com
The issue tracker is only for bugs (i.e. issues) and feature requests.
Contributing Code
=================
Please follow the usual github workflow. Create your own local fork of this repository,
make your changes and then submit a pull request.
Before submitting a pull request
--------------------------------
Please read the `style guide <https://conversejs.org/docs/html/style_guide.html>`_ and make sure that your code follows it.
Add tests for your bugfix or feature
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Add a test for any bug fixed or feature added. We use Jasmine
for testing.
Take a look at `tests.html <https://github.com/jcbrand/converse.js/blob/master/tests.html>`_
and the `spec files <https://github.com/jcbrand/converse.js/blob/master/tests.html>`_
to see how tests are implemented.
Check that the tests pass
~~~~~~~~~~~~~~~~~~~~~~~~~
Check that all tests complete sucessfully.
Run ``make check`` in your terminal or open `tests.html <https://github.com/jcbrand/converse.js/blob/master/tests.html>`_
in your browser.

2
.github/codeql-config.yml vendored Normal file
View File

@ -0,0 +1,2 @@
paths-ignore:
- '**/tests/*.js'

61
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,61 @@
version: 2
updates:
- package-ecosystem: npm
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10
ignore:
- dependency-name: mini-css-extract-plugin
versions:
- 1.3.5
- 1.3.6
- 1.3.7
- 1.3.8
- 1.3.9
- 1.4.0
- 1.4.1
- 1.5.0
- dependency-name: css-loader
versions:
- 5.0.1
- 5.0.2
- 5.1.0
- 5.1.1
- 5.1.2
- 5.1.3
- 5.2.0
- 5.2.1
- dependency-name: y18n
versions:
- 4.0.2
- dependency-name: sinon
versions:
- 10.0.0
- 9.2.4
- dependency-name: bootstrap
versions:
- 4.6.0
- dependency-name: "@babel/plugin-proposal-nullish-coalescing-operator"
versions:
- 7.12.1
- 7.12.13
- 7.13.0
- 7.13.8
- dependency-name: webpack-cli
versions:
- 4.4.0
- 4.5.0
- dependency-name: webpack-merge
versions:
- 5.7.3
- dependency-name: xmldom
versions:
- 0.5.0
- dependency-name: urijs
versions:
- 1.19.4
- 1.19.6
- dependency-name: sass-loader
versions:
- 10.1.1

43
.github/workflows/codeql.yml vendored Normal file
View File

@ -0,0 +1,43 @@
name: "CodeQL"
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
schedule:
- cron: "11 18 * * 6"
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ javascript ]
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
config-file: ./.github/codeql-config.yml
languages: ${{ matrix.language }}
queries: +security-and-quality
- name: Autobuild
uses: github/codeql-action/autobuild@v2
if: ${{ matrix.language == 'javascript' }}
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{ matrix.language }}"

34
.github/workflows/karma-tests.yml vendored Normal file
View File

@ -0,0 +1,34 @@
# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
name: CI Tests
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
env:
DISPLAY: :99.0
strategy:
matrix:
node-version: [18.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Run Karma tests
uses: GabrielBB/xvfb-action@v1
with:
run: make check ARGS=--single-run

3
.gitignore vendored
View File

@ -1,6 +1,9 @@
# Distribution directory
dist
# conversejs/media repo checkout
media
# Editor fluff
*~
.sw?

2
.nvmrc
View File

@ -1 +1 @@
v12.13.1
v18.15.0

View File

@ -1,6 +1,5 @@
{
"arrowParens": "avoid",
"printWidth": 100,
"printWidth": 120,
"quoteProps": "preserve",
"singleQuote": true,
"spaceBeforeFunctionParen": true,

View File

@ -1,15 +0,0 @@
dist: bionic
language: node_js
cache:
directories:
- node_modules
addons:
chrome: stable
node_js:
- "14"
install: make node_modules
services:
- xvfb
before_script:
- export DISPLAY=:99.0
script: make check ARGS=--single-run

36541
3rdparty/libsignal-protocol.js vendored Normal file

File diff suppressed because one or more lines are too long

1
3rdparty/libsignal-protocol.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,11 +1,294 @@
# Changelog
## 10.1.6 (2023-08-31)
- #3246: Badge color not responsive to dark theme
- Fix a GIF rendering bug that causes a memory overflow
## 10.1.5 (2023-06-29)
- #3209: Fix error when importing the `converse` global with bootstrap modal API
- #3207: `.po` translation files weren't included in previous release
- Updated Galician and Portuguese translations
## 10.1.4 (2023-06-25)
- Fix `dist` directory not included in NPM package
## 10.1.3 (2023-06-23)
- Add the ability to set roles and affiliations via the MUC occupant modal
- Fix `isOnlyEmojis is not a function` when using only `@converse/headless`
- Fix `autojoin` checkbox state in MUC bookmark form
- Remove call to `api.confirm` in `@converse/headless`
- Generate TypeScript declaration files into `dist/types`
- Removed documentation about the no longer implemented `fullname` option.
- Updated translations
- #3123: Contacts do not show up online until chat is opened with them.
- #3156: Add function to prevent drag stutter effect over iframes when resize is called in overlay mode
- #3165: Use configured nickname in profile view in the control box
- New config option [stanza_timeout](https://conversejs.org/docs/html/configuration.html#stanza-timeout)
## 10.1.2 (2023-02-17)
- #1490: Busy-loop when fetching registration form fails
- #1556: Can't switch to registration form afrer logout
- #3137: Various UI/UX bugfixes regarding the registration form
- XEP-0437: Room Activity Indicators (RAI) optimizations
## 10.1.1 (2023-02-15)
- #1851: Sort open groupchats alphabetically
- #2240: Ad-Hoc command result form not shown
- #3128: Second bookmarked room shows info of the first one
- Bugfix. Uyghur translations weren't loading
## 10.1.0 (2023-01-07)
- #326: Add the ability to reset your password
- #2759: Don't automatically log in again if the user manually logged out
- #2816: Chat highlight behaves odd
- #2925: File upload is not always enabled
- #3001: Add option to save SCRAM details and to use them to stay logged in upon reload
- Add a "Add to Contacts" button in MUC occupant modals
- Updated translations and add support for Uyghur
- New config option [reuse_scram_keys](https://conversejs.org/docs/html/configuration.html#reuse-scram-keys)
## 10.0.0 (2022-10-30)
- Update to Strophe.js 1.6.0 which adds support for SCRAM-SHA-256 and SCRAM-SHA-512
- Don't automatically convert OpenStreetMap URLs into `geo:` URIs in sent messages
- Remove the `allow_chat_pending_contacts` config option.
- Show roster contacts with `subscription` set to `none`
- Remove the `converse-carbons` plugin and make carbons part of the `converse-chat` plugin.
- Remove the `message_carbons` configuration setting. Carbons are now always enabled.
- Move the `converse-oauth` plugin to the [community-plugins](https://github.com/conversejs/community-plugins)
- Don't apply message corrections when the MUC occupant-id doesn't match.
- Update `nick` attribute on ChatRoom when user nickname changes
- Restrict editing of MUC messages to ones with the same XEP-0421 occupant ID
- Remove unfurls for links removed in a subsequent message correction
- Bookmarks now appear in a modal and the `hide_open_bookmarks` config setting has been removed.
- #1004: Stop using fonts to render icons and use SVG instead
- #2797: Weird unicode characters rendering outside of line-height
- #2870: Fix for multiple URLs to be linkified when sent together in chat and adds a test for this.
- #2879: Quotes, lines not aligned to the first line
- #2925: Fix missing disco-items in browser storage.
- #2936: Fix documentation about enable_smacks option, which is true by default.
- #2939: Data forms with a field named "username" are not displayed
- #3005: Fix MUC messages with a fallback body not rendering.
- #3007: Fix links becoming text when a message is edited
- #3018: Fix MUC icons not functioning.
- #3028: Fix encrypted media from Conversations/Quicksy not properly decrypting
## 9.1.1 (2022-05-05)
- GIFs don't render inside unfurls and cause a TypeError
- Improve how the `muc_domain` setting is populated via service discovery
- Remove local (non-requesting) contacts not returned from a full roster response
- Improve performance by looking up VCards via map instead of traversing an array
- Fix infinite loop when receiving service discovery entities with a circular dependency
- #1130: Display the rooms vCard-temp avatar
- #2746: Always reply to all iqs, even those not understood
- #2794: Some display problems with mobile view mode
- #2868: Selected emoji is inserted into all open chat boxes
Remove the very old and largely unused config option `allow_muc`.
If you don't want MUC support, you can add `'converse-muc'` to the
`blacklisted_plugins` setting.
## 9.1.0 (2022-04-02)
- Updated translations: af, ar, es, eu, fr, gl, he, lt
- Increased stanza timeout from 10 to 20 seconds
- Replace various font icons with SVG icons
- Fix bug where MUC config wasn't persisted across page loads
- Add support for calling the IndexedDB `getAll` method to speed up fetching models from storage.
- #1761: Add a new dark theme based on the [Dracula](https://draculatheme.com/) theme
- #2557: Allow OMEMO encrypted messages to be edited
- #2627: Spoiler toggles only after switching to another tab and back
- #2733: Fix OMEMO race condition related to automatic reconnection and SMACKS
- #2733: Wait for decrypted/parsed message before queuing to UI
- #2751: Media not rendered when Converse runs in a browser extension
- #2754: Navigation keys doesn't work anymore into chat input message
- #2781: Flashing error when connecting to a room
- #2786: Fix webpack configuration not working on Windows OS
- #2788: `TypeError` when trying to use `@converse/headless`
- #2789: Implement new hook `parseMessageForCommands` for plugins to add custom commands
- #2814: Links are mangled on open/copy
- #2822: Singleton doesn't work in overlayed view mode
- New config option [show_connection_url_input](https://conversejs.org/docs/html/configuration.html#show-connection-url-input)
## 9.0.0 (2021-11-26)
- Compress new avatar images before uploading them
- Add initial support for XEP-0421 occupant Ids.
- Use more specific types for form fields based on XEP-0122
- Fix trimming of chats in overlayed view mode
- OMEMO bugfix: Always create device session based on real JID.
- If `auto_register_muc_nickname` is set, make sure to register when the user changes current nick.
- #1322: Display occupants avatars in the occupants list
- #1419: Clicking on avatar should show bigger version
- #1426: Don't fetch member list if not affiliated
- #2423: Could not find dependency "converse-controlbox" for plugin "converse-muc"
- #2640: Add `beforeFetchLoginCredentials` hook
- #2647: Singleton mode doesn't work
- #2650: Clicking on occupant in sidebar should add nickname to textarea
- #2683: Show error messages that don't refer to specific chat messages
- #2704: Send button doesn't work in a multi-user chat
- #2715: Singleton + fullscreen mode styling issue
- #2718: Message is not displayed if it contains an invalid URL
- #2725: Send new presence status to all connected MUCs
- #2728: Not sending headers with upload request
- #2733: OMEMO Messages received while client closed not decrypted
- Emit a `change` event when a configuration setting changes
- 3 New configuration settings:
- [render_media](https://conversejs.org/docs/html/configuration.html#render-media)
- [allowed_audio_domains](https://conversejs.org/docs/html/configuration.html#allowed-audio-domains)
- [allowed_video_domains](https://conversejs.org/docs/html/configuration.html#allowed-video-domains)
- [allowed_image_domains](https://conversejs.org/docs/html/configuration.html#allowed-image-domains)
Three config settings have been obsoleted:
- embed_audio
- embed_video
- show_images_inline
- muc_show_ogp_unfurls
### Breaking Changes
Configuration settings are no longer available on the `_converse` object.
Instead, use `api.settings.get` and `api.settings.set`.
## 8.0.1 (2021-09-09)
- #2326: 404 for asset /logo/conversejs-filled.svg
- #2628: Open groupchats toggle emits an error
- #2629: OMEMO button tooltip is wrong in private chat
- #2633: Excessive logging of warning
- #2634: Image previews not loading when not serving Converse locally
- #2636: Don't fail when setting up a new XEP-0198 managed stream and `_converse.session` is undefined
- Bugfix: Don't show minimized chats when logged out
## 8.0.0 (2021-09-03)
- Requires Node 12 or above
### Issues and features
- #1083: Add support for XEP-0393 Message Styling
- #1182: Add support for XEP-0454 OMEMO Media sharing
- #1823: New config options [mam_request_all_pages](https://conversejs.org/docs/html/configuration.html#mam-request-all-pages)
- #2275: Allow punctuation to immediately precede a mention
- #2348: `auto_join_room` not showing the room in `fullscreen` `view_mode`.
- #2400: Fixes infinite loop bug when appending .png to allowed image urls
- #2409: Integrate App Badging API for unread messages
- #2464: New configuration setting [allow_url_history_change](https://conversejs.org/docs/html/configuration.html#allow-url-history-change)
- #2497: Bugfix /nick command is not working
- Add a Description Of A Project (DOAP) file
- Add ability to deregister nickname when closing a MUC by setting `auto_register_muc_nickname` to `'unregister'`.
- Add support for XEP-0437 Room Activity Indicators see [muc-subscribe-to-rai](https://conversejs.org/docs/html/configuration.html#muc-subscribe-to-rai)
- Add support for rendering unfurls via [mod_ogp](https://modules.prosody.im/mod_ogp.html)
- Bugfix: Connection protocol not updated based on XEP-0156 connection methods
- Bugfix: Use real JID in XEP-0372 references only when the MUC is non-anonymous
- Bugfix: `null` inserted by emoji picker and can't switch between skintones
- File structure reordering: All plugins are now in `./plugins` folders.
- Show a gap placeholder when there are gaps in the chat history. The user can click these to fill the gaps.
- Use the MUC stanza id when sending XEP-0333 markers
- Add support for pausing Gif images
- Add limited support for XEP-0316 MUC notifications
### New configuration setings
- [show_tab_notifications](https://conversejs.org/docs/html/configuration.html#show-tab-notifications)
- [muc_clear_messages_on_leave](https://conversejs.org/docs/html/configuration.html#muc-clear-messages-on-leave)
- [send_chat_markers](https://conversejs.org/docs/html/configuration.html#send-chat-markers)
- [muc_show_ogp_unfurls](https://conversejs.org/docs/html/configuration.html#muc-show-ogp-unfurls)
- [prune-messages-above](https://conversejs.org/docs/html/configuration.html#prune-messages-above)
- [pruning_behavior](https://conversejs.org/docs/html/configuration.html#pruning-behavior)
### New hooks and events
- New hook: [getMessageActionButtons](https://conversejs.org/docs/html/api/-_converse.html#event:getMessageActionButtons)
- New hook: [shouldNotifyOfGroupMessage](https://conversejs.org/docs/html/api/-_converse.html#event:shouldNotifyOfGroupMessage)
- New hook: [presenceConstructed](https://conversejs.org/docs/html/api/-_converse.html#event:presenceConstructed)
- New event: [historyPruned](https://conversejs.org/docs/html/api/-_converse.html#event:historyPruned)
### Breaking Changes
The default persistent store, set via the [persistent_store](https://conversejs.org/docs/html/configuration.html#persistent-store),
is now IndexedDB. This main advantage of using IndexedDB is that it doesn't
have a fixed size limit. We don't provide a tool to migrate data from
localStorage to IndexedDB. For almost all data this is not a problem since
the data can be fetched again from the XMPP server. However,
decrypted OMEMO messages cannot be fetched again from the server, since the
double ratchet makes it impossible to again decrypt them. This means your
decrypted OMEMO history will be lost in the transition.
The [afterMessageBodyTransformed](https://conversejs.org/docs/html/api/-_converse.html#event:afterMessageBodyTransformed) and [beforeMessageBodyTransformed](https://conversejs.org/docs/html/api/-_converse.html#event:beforeMessageBodyTransformed) events now has a different signatures.
When leaving a MUC, the message history is deleted. This means that decrypted
OMEMO messages are gone and cannot be recovered on that device. See [muc_clear_messages_on_leave](https://conversejs.org/docs/html/configuration.html#muc-clear-messages-on-leave).
Removed events:
* `bookmarkViewsInitialized`
* `chatBoxInsertedIntoDOM`
* `contactStatusMessageChanged`
* `messageSend` (use `sendMessage` instead)
* `rosterGroupsFetched`
The `chatBoxClosed`, `chatBoxMaximized` and `chatBoxMinimized` events now have the `model` as
payload and not the `view`.
The `api.chatviews` and `api.roomviews` API groupings and methods have been
removed. The original "views" don't really exist anymore, the UI is now composed web
components which should update reactively based on changes made on the models.
## 7.0.6 (2021-06-11)
- #2500: Wrong assignment in OMEMO code
## 7.0.5 (2021-03-16)
- #2377: The @converse/headless NPM package is missing the dist directory, causing import errors
- #2396: @converse/headless wrongly depends on `CustomElement` from the view layer
- #2381: Converse does not reflect the browser language
## 7.0.4 (2020-12-09)
Bugfix: Set protocol after discovering connection methods
Otherwise if an endpoint was passed in with `converse.initialize`, then
that endpoint's protocol is (potentially wrongly) used.
## 7.0.3 (2020-12-02)
- Bugfix: `null` inserted by emoji picker and can't switch between skintones
## 7.0.2 (2020-11-23)
- Updated translations: de, nb, gl, tr
- Still more necessary files not included in the 7.0.1 NPM package, causing `Module not found` errors.
- #2337: Newly opened headline chat isn't hidden by default
## 7.0.1 (2020-11-19)
- Updated translations: de, es, fi, fr, gl, hu, nb_NO, oc, pl, pt, pt_BR, ru, tr, uk, zh
- #2328: Honor `use_system_emojis` in emoji-picker
- Not all template/*.js files were included in the 7.0.0 NPM package, causing:
`Module not found: Error: Can't resolve 'templates/*.js'`
## 7.0.0 (2020-11-18)
*Note for plugin authors:*
configuration settings should now be accessed via `_converse.api.settings.get` and not directly on the `_converse` object.
Soon we'll deprecate the latter, so prepare now.
- #515 Add support for XEP-0050 Ad-Hoc commands
- #2231: add sort_by_query and remove sort_by_length
- #1313: Stylistic improvements to the send button
- #1481: MUC OMEMO: Error No record for device
@ -15,7 +298,6 @@ Soon we'll deprecate the latter, so prepare now.
- #1793: Send button doesn't appear in Firefox in 1:1 chats
- #1820: Set focus on jid field after controlbox is loaded
- #1822: Don't log error if user has no bookmarks
- #515 Add support for XEP-0050 Ad-Hoc commands
- #1823: New config options [muc_roomid_policy](https://conversejs.org/docs/html/configuration.html#muc-roomid-policy)
and [muc_roomid_policy_hint](https://conversejs.org/docs/html/configuration.html#muc-roomid-policy-hint)
- #1826: A user can now add himself as a contact
@ -35,13 +317,15 @@ Soon we'll deprecate the latter, so prepare now.
- #2213: added CustomElement to converse.env
- #2220: fix rendering of emojis in case `use_system_emojis == false` (again).
- #2092: fixes room list update loop when having the `locked_muc_domain` truthy or `'hidden'`
- #2259: Rename configuration setting `muc_show_join_leave` to `muc_show_info_messages`. Now accepts a list of events to show instead of a boolean.
- #2285: Rename config option `muc_hats_from_vcard` to [muc_hats](https://conversejs.org/docs/html/configuration.html#muc-hats). Now accepts a list instead of a boolean and allows for more flexible choices regarding user badges.
- #2300: Fix message reorder issue after message correction.
- #2304: Custom emojis (stickers) images not shown
- #2304: Custom emojis (stickers) images not shown
- #2307: BootstrapModal is not accessible to plugins
- #2308: Allow getHats method to be overriden in the `overrides` object in plugins.
- #2321: When Converse runs inside a browser extension, enable browser sync and local storage for persistent storage
- #1250: Change favicon color when unread messages
- Updated translations: de, es, fi, fr, gl, hu, nb_NO, oc, pl, pt, pt_BR, ru, tr, uk, zh
- The `trusted` configuration setting has been removed in favor of two new settings:
[allow_user_trust_override](https://conversejs.org/docs/html/configuration.html#allow-user-trust-override)
[clear_cache_on_logout](https://conversejs.org/docs/html/configuration.html#clear-cache-on-logout)
@ -73,7 +357,7 @@ Soon we'll deprecate the latter, so prepare now.
## 6.0.0 (2020-01-09)
- [enable_smacks](https://conversejs.org/docs/html/configuration.html#enable-smacks) is not set to `true` by default.
- [enable_smacks](https://conversejs.org/docs/html/configuration.html#enable-smacks) is now set to `true` by default.
- Refactor some presence and status handling code from `converse-core` into `@converse/headless/converse-status`.
- It's now possible to navigate the emoji-picker via the keyboard arrow keys.

View File

@ -2,7 +2,7 @@
*
* An XMPP chat client that runs in the browser.
*
* Version: 7.0.0
* Version: 10.1.6
*
* Copyright: JC Brand 2013-2018
* Except for 3rd party dependencies.

119
Makefile
View File

@ -1,22 +1,18 @@
# You can set these variables from the command line.
BABEL ?= node_modules/.bin/babel
BOOTSTRAP = ./node_modules/
BUILDDIR = ./docs
KARMA ?= ./node_modules/.bin/karma
CHROMIUM ?= ./node_modules/.bin/run-headless-chromium
CLEANCSS ?= ./node_modules/clean-css-cli/bin/cleancss --skip-rebase
ESLINT ?= ./node_modules/.bin/eslint
CLEANCSS ?= ./node_modules/clean-css-cli/bin/cleancss
HTTPSERVE ?= ./node_modules/.bin/http-server
HTTPSERVE_PORT ?= 8000
INKSCAPE ?= inkscape
INSTALL ?= install
JSDOC ?= ./node_modules/.bin/jsdoc
LERNA ?= ./node_modules/.bin/lerna
OXIPNG ?= oxipng
PAPER =
RJS ?= ./node_modules/.bin/r.js
NPX ?= ./node_modules/.bin/npx
SASS ?= ./node_modules/.bin/node-sass
SASS ?= ./node_modules/.bin/sass
SED ?= sed
SPHINXBUILD ?= ./bin/sphinx-build
SPHINXOPTS =
@ -62,17 +58,19 @@ serve: node_modules dist
serve_bg: node_modules
$(HTTPSERVE) -p $(HTTPSERVE_PORT) -c-1 -s &
certs:
mkdir certs
cd certs && openssl req -newkey rsa:4096 -x509 -sha256 -days 365 -nodes -out chat.example.org.crt -keyout chat.example.org.key
########################################################################
## Translation machinery
dist/converse-no-dependencies.js: src webpack.common.js webpack.nodeps.js @converse/headless node_modules
npm run nodeps
GETTEXT = $(XGETTEXT) --from-code=UTF-8 --language=JavaScript --keyword=__ --keyword=___ --keyword=i18n_ --force-po --output=src/i18n/converse.pot --package-name=Converse.js --copyright-holder="Jan-Carel Brand" --package-version=7.0.0 dist/converse-no-dependencies.js -c
GETTEXT = $(XGETTEXT) --from-code=UTF-8 --language=JavaScript --keyword=__ --keyword=___ --keyword=i18n_ --force-po --output=src/i18n/converse.pot --package-name=Converse.js --copyright-holder="Jan-Carel Brand" --package-version=10.1.6 dist/converse-no-dependencies.js -c
src/i18n/converse.pot: dist/converse-no-dependencies.js
$(GETTEXT) 2>&1 > /dev/null; exit $$?;
rm dist/converse-no-dependencies.js
rm dist/tmp.css
.PHONY: pot
pot: src/i18n/converse.pot
@ -84,9 +82,9 @@ po:
########################################################################
## Release management
.PHONY: release
release:
$(SED) -i '/^_converse.VERSION_NAME =/s/=.*/= "v$(VERSION)";/' src/headless/converse-core.js
.PHONY: version
version:
$(SED) -i '/^export const VERSION_NAME =/s/=.*/= "v$(VERSION)";/' src/headless/shared/constants.js
$(SED) -i '/Version:/s/:.*/: $(VERSION)/' COPYRIGHT
$(SED) -i '/Project-Id-Version:/s/:.*/: Converse.js $(VERSION)\n"/' src/i18n/converse.pot
$(SED) -i '/"version":/s/:.*/: "$(VERSION)",/' manifest.json
@ -101,25 +99,47 @@ release:
make pot
make po
make dist
npm pack
release-checkout:
git clone git@github.com:conversejs/converse.js.git --depth 1 --branch $(BRANCH) release-$(BRANCH)
cd release-$(BRANCH) && make dist
.PHONY: publish
publish:
make release-checkout
cd release-$(BRANCH) && npm pack && npm publish
cd release-$(BRANCH)/src/headless && npm pack && npm publish
find ./release-$(BRANCH)/ -name "converse.js-*.tgz" -exec mv {} . \;
find ./release-$(BRANCH)/src/headless -name "converse-headless-*.tgz" -exec mv {} . \;
rm -rf release-$(BRANCH)
.PHONY: postrelease
postrelease:
$(SED) -i '/^_converse.VERSION_NAME =/s/=.*/= "v$(VERSION)dev";/' src/headless/converse-core.js
$(SED) -i '/^export const VERSION_NAME =/s/=.*/= "v$(VERSION)dev";/' src/headless/shared/constants.js
.PHONY: deploy
deploy:
git clone --branch v$(VERSION) git@github.com:conversejs/converse.js.git --depth 1 $(VERSION)
cd $(VERSION) && make node && ASSET_PATH=https://cdn.conversejs.org/$(VERSION)/dist/ make dist && make doc
cd .. && git pull && make node && ASSET_PATH=https://cdn.conversejs.org/dist/ make dist && make doc
########################################################################
## Install dependencies
$(LERNA):
npm install lerna
${NVM_DIR}/nvm.sh:
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash
source ~/.bashrc
package-lock.json: package.json
.PHONY: nvm
nvm: ${NVM_DIR}/nvm.sh
.PHONY: node
node: .nvmrc
. $(HOME)/.nvm/nvm.sh && nvm install
node_modules: package.json src/headless/package.json
npm install
node_modules: $(LERNA) package.json package-lock.json src/headless/package.json src/headless/package-lock.json
npm run lerna
npm rebuild node-sass
.PHONY: clean
clean:
npm run clean
@ -136,14 +156,17 @@ devserver: node_modules
########################################################################
## Builds
dist/converse-no-dependencies.js: src webpack/webpack.common.js webpack/webpack.nodeps.js @converse/headless node_modules
npm run nodeps
dist/converse.js:: node_modules
npm run dev
npm run build
dist/converse.css:: node_modules
npm run dev
npm run build
dist/website.css:: node_modules sass
$(SASS) --source-map true --include-path $(BOOTSTRAP) sass/website.scss $@
dist/website.css:: node_modules src/shared/styles/website.scss
$(SASS) --load-path=$(BOOTSTRAP) src/shared/styles/website.scss $@
dist/website.min.css:: node_modules dist/website.css
$(CLEANCSS) dist/website.css > $@
@ -174,11 +197,24 @@ logo/conversejs-filled%.png:: logo/conversejs-filled.svg
@converse/headless: src/headless
src/headless/dist/converse-headless.min.js: src webpack.common.js node_modules @converse/headless
src/headless/dist/converse-headless.js: src webpack/webpack.common.js node_modules @converse/headless
npm run headless-dev
src/headless/dist/converse-headless.min.js: src webpack/webpack.common.js node_modules @converse/headless
npm run headless
dist:: node_modules src/* | dist/converse.js dist/converse.css dist/website.css dist/website.min.css
npm run prod
dist:: node_modules src/* | dist/website.css dist/website.min.css
npm run headless
# Ideally this should just be `npm run build`.
# The additional steps are necessary to properly generate JSON chunk files
# from the .po files. The nodeps config uses preset-env with IE11.
# Somehow this is necessary.
npm run nodeps
$(eval TMPD := $(shell mktemp -d))
mv dist/locales $(TMPD) && \
npm run build && \
mv $(TMPD)/locales/*-po.js dist/locales/ && \
rm -rf $(TMPD)
.PHONY: install
install:: dist
@ -187,24 +223,24 @@ install:: dist
cdn:: node_modules
npm run cdn
.PHONY: types
types:: node_modules
npm run types
########################################################################
## Tests
.PHONY: eslint
eslint: node_modules
$(ESLINT) src/*.js
$(ESLINT) src/utils/*.js
$(ESLINT) src/headless/*.js
$(ESLINT) src/headless/utils/*.js
$(ESLINT) spec/ --global converse
npm run lint
.PHONY: check
check: eslint | dist/converse.js dist/converse.css
$(KARMA) start karma.conf.js $(ARGS)
npm run test -- $(ARGS)
.PHONY: test
test:
$(KARMA) start karma.conf.js $(ARGS)
npm run test -- $(ARGS)
########################################################################
## Documentation
@ -212,13 +248,10 @@ test:
./bin/activate:
python3 -m venv .
.installed.cfg: requirements.txt buildout.cfg
.PHONY: docsdev
docsdev: ./bin/activate requirements.txt
./bin/pip install --upgrade pip==21.3.1
./bin/pip install -r requirements.txt
./bin/pip install --upgrade pip==19.2.1
./bin/pip install --upgrade setuptools==41.0.1
./bin/buildout -v
docsdev: ./bin/activate .installed.cfg
.PHONY: html
html: doc
@ -233,4 +266,4 @@ doc: node_modules docsdev apidoc
PHONY: apidoc
apidoc:
$(JSDOC) --private --readme docs/source/jsdoc_intro.md -c docs/source/conf.json -d docs/html/api src/templates/directives/*.js src/components/*.js src/*.js src/utils/*.js src/headless/*.js src/headless/utils/*.js
find ./src -type d -name node_modules -prune -false -o -name "*.js" | xargs $(JSDOC) --private --readme docs/source/jsdoc_intro.md -c docs/source/conf.json -d docs/html/api

17
README.chapril.md Normal file
View File

@ -0,0 +1,17 @@
# Construire une version Chapril de ConverseJS
```
cd .../conversejs
# La première fois, installer nvm (attention, ça va modifier le .bashrc, entre autres choses)
make nvm
export V=7.0.4
git rebase v${V?}
# [... Résoudre les conflits]
git checkout -b v${V?}-chapril
nvm install
make dist
# [... Tester les livrables présents dans dist/, et si tout est ok :]
make version VERSION=${V?}-chapril
rsync -av dist/ chapril-xmpp:/var/www/xmpp.chapril.org/public_html/dist-custom-chapril-${V?}/
```

View File

@ -5,8 +5,8 @@
</h2>
[![XMPP Chat](https://inverse.chat/badge.svg?room=discuss@conference.conversejs.org)](https://inverse.chat/#converse/room?jid=discuss@conference.conversejs.org)
[![Travis](https://api.travis-ci.org/conversejs/converse.js.png?branch=master)](https://travis-ci.org/conversejs/converse.js)
[![XMPP Chat](https://conference.conversejs.org/muc_badge/discuss@conference.conversejs.org)](https://inverse.chat/#converse/room?jid=discuss@conference.conversejs.org)
[![CI Tests](https://github.com/conversejs/converse.js/actions/workflows/karma-tests.yml/badge.svg)](https://github.com/conversejs/converse.js/actions/workflows/karma-tests.yml)
[![Bountysource bounties](https://img.shields.io/bountysource/team/converse.js/activity.svg?maxAge=2592000)](https://www.bountysource.com/teams/converse.js/issues?tracker_ids=194169)
[![Translation status](https://hosted.weblate.org/widgets/conversejs/-/svg-badge.svg)](https://hosted.weblate.org/engage/conversejs/?utm_source=widget)
@ -40,19 +40,23 @@ which shows you how to use the CDN (content delivery network) to quickly get a d
In overlay mode, Converse appears overlayed chats on top of the website.
![Screenshot of Converse in overlay mode](https://opkode.com/img/Screen-Shot-2018-09-19-at-19.15.16.png)
![Screenshot of Converse in overlay mode](https://conversejs.org/screenshots/Converse-overlayed.png)
### Fullpage
In fullpage mode, Converse behaves like a single-page app that covers the whole browser viewport.
![Screenshot of Converse in fullpage mode](https://opkode.com/img/Screen-Shot-2018-09-19-at-19.16.46.png)
![Screenshot of Converse 9.0.0 in fullpage mode](https://conversejs.org/screenshots/Converse-fullscreen.png)
### Dark mode
![Screenshot of Converse 9.1.0 with a dark theme](https://conversejs.org/screenshots/Converse-Dracula-Theme.png)
### Embedded
In embedded mode, Converse can be embedded into an element in the DOM.
![Screenshot of Converse in embedded mode](https://opkode.com/img/Converse-embedded.png)
![Screenshot of Converse in embedded mode](https://conversejs.org/screenshots/Converse-embedded.png)
## Features
- Available as overlayed chat boxes or as a fullscreen application. See [inverse.chat](https://inverse.chat) for the fullscreen version.
@ -61,6 +65,7 @@ In embedded mode, Converse can be embedded into an element in the DOM.
- A [plugin architecture](https://conversejs.org/docs/html/plugin_development.html) based on [pluggable.js](https://conversejs.github.io/pluggable.js/)
- Chat statuses (online, busy, away, offline)
- Anonymous logins, see the [anonymous login demo](https://conversejs.org/demo/anonymous.html)
- URL Previews (requires server support, for example [mod_ogp](https://modules.prosody.im/mod_ogp.html)
- Translated into over 30 languages
### Supported XMPP Extensions
@ -77,6 +82,7 @@ In embedded mode, Converse can be embedded into an element in the DOM.
- [XEP-0066](https://xmpp.org/extensions/xep-0066.html) Out of Band Data
- [XEP-0077](https://xmpp.org/extensions/xep-0077.html) In-band registration
- [XEP-0085](https://xmpp.org/extensions/xep-0085.html) Chat State Notifications
- [XEP-0115](https://xmpp.org/extensions/xep-0115.html) Entity Capabilities
- [XEP-0124](https://xmpp.org/extensions/xep-0124.html) Bidirectional-streams Over Synchronous HTTP (BOSH)
- [XEP-0144](https://xmpp.org/extensions/xep-0144.html) Roster item exchange
- [XEP-0156](https://xmpp.org/extensions/xep-0156.html) Discovering Alternative XMPP Connection Methods
@ -92,6 +98,7 @@ In embedded mode, Converse can be embedded into an element in the DOM.
- [XEP-0297](https://xmpp.org/extensions/xep-0297.html) Stanza Forwarding (limited support)
- [XEP-0308](https://xmpp.org/extensions/xep-0308.html) Last Message Correction
- [XEP-0313](https://xmpp.org/extensions/xep-0313.html) Message Archive Management
- [XEP-0316](https://xmpp.org/extensions/xep-0316.html) MUC Eventing protocol (limited support)
- [XEP-0317](https://xmpp.org/extensions/xep-0317.html) Hats (limited support)
- [XEP-0333](https://xmpp.org/extensions/xep-0333.html) Chat Markers (limited support)
- [XEP-0352](https://xmpp.org/extensions/xep-0352.html) Client State Indication
@ -101,21 +108,30 @@ In embedded mode, Converse can be embedded into an element in the DOM.
- [XEP-0372](https://xmpp.org/extensions/xep-0372.html) References
- [XEP-0382](https://xmpp.org/extensions/xep-0382.html) Spoiler messages
- [XEP-0384](https://xmpp.org/extensions/xep-0384.html) OMEMO Encryption
- [XEP-0393](https://xmpp.org/extensions/xep-0393.html) Message styling
- [XEP-0422](https://xmpp.org/extensions/xep-0422.html) Message Fastening (limited support)
- [XEP-0424](https://xmpp.org/extensions/xep-0424.html) Message Retractions
- [XEP-0425](https://xmpp.org/extensions/xep-0425.html) Message Moderation
- [XEP-0437](https://xmpp.org/extensions/xep-0437.html) Room Activity Indicators
- [XEP-0453](https://xmpp.org/extensions/xep-0453.html) DOAP Usage in XMPP
- [XEP-0454](https://xmpp.org/extensions/xep-0454.html) OMEMO Media sharing
## Integration into other servers and frameworks
### XMPP servers
- **[Openfire](https://www.igniterealtime.org/projects/openfire/index.jsp)**: [inverse.jar](https://www.igniterealtime.org/projects/openfire/plugins.jsp)
- **[Prosody](https://prosody.im/)**: [mod_conversejs](https://modules.prosody.im/mod_conversejs.html)
- **[Ejabberd](https://ejabberd.im/)**: [mod-conversejs](https://docs.ejabberd.im/admin/configuration/modules/#mod-conversejs)
### Other
- **[Alfresco](https://www.alfresco.com)**: [alfresco-js-chat-share](https://github.com/keensoft/alfresco-js-chat-share)
- **[Django](https://www.djangoproject.com)**: [django-conversejs](https://pypi.python.org/pypi/django-conversejs) or [django-xmpp](https://github.com/fpytloun/django-xmpp)
- **[Elgg](https://elgg.org)**: [plugin](https://elgg.org/plugins/2997196)
- **[Friendica](https://friendi.ca)**: [converse](https://github.com/friendica/friendica-addons/tree/master/xmpp/converse)
- **[Openfire](https://www.igniterealtime.org/projects/openfire/index.jsp)**: [inverse.jar](https://www.igniterealtime.org/projects/openfire/plugins.jsp)
- **[Patternslib](http://patternslib.com)**: [patterns.converse](https://github.com/jcbrand/patterns.converse)
- **[Plone](https://plone.com)**: [collective.converse](https://github.com/collective/collective.converse)
- **[Prosody](https://prosody.im/)**: [mod_conversejs](https://modules.prosody.im/mod_conversejs.html)
- **[Pàdé](https://www.igniterealtime.org/projects/pade/index.jsp)**: [Pàdé](https://www.igniterealtime.org/projects/pade/index.jsp)
- **[Roundcube](https://roundcube.net)**: [roundcube-converse.js-xmpp-plugin](https://github.com/devurandom/roundcube-converse.js-xmpp-plugin)
- **[Ruby on Rails](https://rubyonrails.org)**: [conversejs-rails](https://github.com/mikemarsian/conversejs-rails)
@ -147,3 +163,26 @@ A heartfelt thanks for everyone who has supported this project over the years.
Many people have contributed testing, bugfixes, features and corrections.
We accept donations via [Patreon](https://www.patreon.com/jcbrand) and [Liberapay](https://liberapay.com/jcbrand).
## Sponsors
<p>
<a href="https://bairesdev.com/sponsoring-open-source-projects/?utm_source=conversejs" target="_blank" rel="noopener">
<img alt="BairesDev" src="https://raw.githubusercontent.com/conversejs/media/main/logos/bairesdev-primary.png" width="200">
</a>
</p>
<p>
<a href="https://blokt.com?utm_source=conversejs" target="_blank" rel="noopener">
<img alt="Blokt Crypto & Privacy" src="https://raw.githubusercontent.com/conversejs/converse.js/541613d1fea8aef364af00180f60e959162e5e4b/logo/blokt.png" width="200">
</a>
</p>
<p>
<a href="https://primesound.org/?utm_source=conversejs" target="_blank" rel="noopener">
<img alt="Prime Sound" src="https://raw.githubusercontent.com/conversejs/media/main/logos/primesound.png" width="200">
</a>
</p>
<p>
<a href="https://www.keycdn.com?utm_source=conversejs" target="_blank" rel="noopener">
<img alt="KeyCDN" src="https://raw.githubusercontent.com/conversejs/converse.js/541613d1fea8aef364af00180f60e959162e5e4b/logo/keycdn.png" width="200">
</a>
</p>

View File

@ -1,18 +1,18 @@
# Release checklist
1. Run `make check` to check that all tests pass.
2. Run `make release VERSION=7.0.0`
3. Do a `git diff` to check if things look sane.
4. Do a quick manual test with the `dist` files (via `index.html`)
5. `git commit -am "Release 7.0.0"`
6. `git tag -s v7.0.0 -m "Release 7.0.0"`
7. Run `git push && git push --tags`
8. Update https://conversejs.org
1. Merge weblate translations: https://hosted.weblate.org/projects/conversejs/translations/#repository
2. Run `make check` to check that all tests pass.
3. Run `make version VERSION=10.1.6`
4. Do a `git diff` to check if things look sane.
5. Do a quick manual test with the `dist` files (via `index.html`)
6. `git commit -am "Release 10.1.6"`
7. `git tag -s v10.1.6 -m "Release 10.1.6"`
8. `git push && git push origin v10.1.6`
9. `make publish BRANCH=v10.1.6`
10. Update release page on Github
* Upload tar files
11. Update https://conversejs.org
* `cd /home/conversejs/converse.js`
* `git clone --branch v7.0.0 git@github.com:conversejs/converse.js.git 7.0.0`
* `cd 7.0.0 && ASSET_PATH=https://cdn.conversejs.org/7.0.0/dist/ make dist`
* `cd .. && git pull && ASSET_PATH=https://cdn.conversejs.org/dist/ make dist`
9. Update release page on Github
11. Run `npm publish && cd src/headless/ && npm publish`
* `make deploy VERSION=10.1.6`
12. Update the repository on weblate
13. Decide on next release number and run `make postrelease VERSION=7.0.1`
13. Decide on next release number and run `make postrelease VERSION=10.1.7`

10
babel.config.json Normal file
View File

@ -0,0 +1,10 @@
{
"presets": [
["@babel/preset-env", {
"targets": {
"browsers": [">1%", "not ie 11", "not op_mini all", "not dead"]
}
}]
],
"plugins": []
}

View File

@ -1,15 +0,0 @@
[buildout]
parts =
sphinx
versions = versions
[sphinx]
recipe = zc.recipe.egg
eggs =
Sphinx
sphinx-bootstrap-theme
[versions]
Sphinx = 2.1.2
docutils = 0.15.2

View File

@ -1,23 +0,0 @@
# How to use saved Chrome/Chromium logs to replay events
**NOTE**: This feature is very experimental and in many cases doesn't work
without data massaging and ugly hacks.
It's possible to save the log output from Chrome/Chromium (I haven't tried this
yet with any other browser) and then to replay that log output in the browser.
This can be a very helpful technique to track down bugs.
To do this, follow the following steps:
1. Save the log file (right click and then click "Save as" in the browser's console).
2. Rename the log file, making sure it ends in `.html`
3. Move the log file to the `converse-logs` directory in the converse.js repo.
4. Add `<log>` to the top of the log file and `</log>` to the bottom of the log file.
5. In `converse-logs/converse-logs.js`, add a new entry for the log file (don't
include the `.html` part of the file name.
6. Make sure that `spec/transcripts` is "required"-ed in `tests/main.js`
6. Open `tests.html` in your browser.
Your logs will run first, and then all the other tests will run afterwards.

View File

@ -1,5 +0,0 @@
define("transcripts", [
"tpl!../../converse-logs/missing_messages",
], function () {
return arguments;
});

293
conversejs.doap Normal file
View File

@ -0,0 +1,293 @@
<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF xmlns:doap="http://usefulinc.com/ns/doap#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:xmpp="https://linkmauve.fr/ns/xmpp-doap#" xmlns:schema="https://schema.org/" xml:lang="en">
<Project xmlns="http://usefulinc.com/ns/doap#">
<name>Converse.js</name>
<shortdesc>Browser based XMPP chat client</shortdesc>
<homepage rdf:resource="https://conversejs.org/"/>
<bug-database rdf:resource="https://github.com/conversejs/converse.js/issues"/>
<developer-forum rdf:resource="xmpp:discuss@conference.conversejs.org?join"/>
<support-forum rdf:resource="xmpp:discuss@conference.conversejs.org?join"/>
<category rdf:resource="https://linkmauve.fr/ns/xmpp-doap#category-client"/>
<programming-language>JavaScript</programming-language>
<os>Browser</os>
<os>Linux</os>
<os>macOS</os>
<os>Windows</os>
<schema:logo rdf:resource="https://raw.githubusercontent.com/conversejs/converse.js/master/logo/conversejs-filled.svg"/>
<repository>
<GitRepository>
<browse rdf:resource="https://github.com/conversejs/converse.js"/>
<location rdf:resource="https://github.com/conversejs/converse.js.git"/>
</GitRepository>
</repository>
<implements rdf:resource="https://www.rfc-editor.org/info/rfc6120"/>
<implements rdf:resource="https://www.rfc-editor.org/info/rfc6121"/>
<implements rdf:resource="https://www.rfc-editor.org/info/rfc6122"/>
<implements rdf:resource="https://www.rfc-editor.org/info/rfc7395"/>
<implements rdf:resource="https://www.rfc-editor.org/info/rfc7590"/>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0004.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0030.html"/>
<xmpp:since>0.8.2</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0045.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0048.html"/>
<xmpp:since>2.0.1</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0050.html"/>
<xmpp:since>7.0.0</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0054.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0059.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0060.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0066.html"/>
<xmpp:since>4.0.0</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0077.html"/>
<xmpp:since>0.8.5</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0085.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0115.html"/>
<xmpp:status>partial</xmpp:status>
<xmpp:note>advertises caps but no caching</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0122.html"/>
<xmpp:status>partial</xmpp:status>
<xmpp:note>basic string field sub-type usage</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0124.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0144.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0156.html"/>
<xmpp:since>6.0.0</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0163.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0184.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0198.html"/>
<xmpp:since>5.0.0</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0199.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0203.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0206.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0245.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0249.html"/>
<xmpp:since>0.8.2</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0280.html"/>
<xmpp:since>0.8.0</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0297.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0308.html"/>
<xmpp:since>4.0.0</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0313.html"/>
<xmpp:since>0.9.5</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0317.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0319.html"/>
<xmpp:since>4.0.5</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0333.html"/>
<xmpp:since>4.1.1</xmpp:since>
<xmpp:status>partial</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0352.html"/>
<xmpp:since>0.9.4</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0357.html"/>
<xmpp:since>4.0.0</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0359.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0363.html"/>
<xmpp:since>4.0.0</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0371.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0372.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0382.html"/>
<xmpp:since>3.3.3</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0384.html"/>
<xmpp:since>4.0.0</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0393.html"/>
<xmpp:since>8.0.0</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0410.html"/>
<xmpp:since>5.0.0</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0421.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0422.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0424.html"/>
<xmpp:since>6.0.0</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0425.html"/>
<xmpp:since>6.0.0</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0437.html"/>
<xmpp:since>8.0.0</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0454.html"/>
<xmpp:since>8.0.0</xmpp:since>
</xmpp:SupportedXep>
</implements>
</Project>
</rdf:RDF>

View File

@ -10,20 +10,20 @@
<meta name="keywords" content="xmpp chat webchat converse.js Converse" />
<!-- These files are NOT needed when using converse.js in your own project. -->
<link rel="shortcut icon" type="image/ico" href="/dist/favicon.ico"/>
<link type="text/css" rel="stylesheet" media="screen" href="/dist/website.min.css" />
<noscript><p><img src="//stats.opkode.com/piwik.php?idsite=1" style="border:0;" alt="" /></p></noscript>
<script type="text/javascript" src="analytics.js"></script>
<link rel="shortcut icon" type="image/ico" href="../dist/favicon.ico"/>
<link type="text/css" rel="stylesheet" media="screen" href="../dist/website.min.css" />
<noscript><p><img src="https://stats.opkode.com/piwik.php?idsite=1" style="border:0;" alt="" /></p></noscript>
<script type="text/javascript" src="/analytics.js"></script>
<!-- *********************************************************************** -->
<link rel="manifest" href="/manifest.json">
<link type="text/css" rel="stylesheet" media="screen" href="/dist/converse.min.css" />
<link rel="manifest" href="../manifest.json">
<link type="text/css" rel="stylesheet" media="screen" href="../dist/converse.min.css" />
<script src="https://cdn.conversejs.org/3rdparty/libsignal-protocol.min.js"></script>
<script src="/dist/converse.min.js"></script>
<script src="../dist/converse.min.js"></script>
<style>
.converse-container {
height: 55vh;
height: 50vh;
}
</style>
</head>
@ -44,7 +44,7 @@
<div class="container">
<div class="row">
<div class="col-md-12">
<h1 class="brand-heading fade-in">
<h1 class="brand-heading fade-in" style="margin: 1.5em 0 0 0">
<svg class="converse-svg-logo"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
@ -72,7 +72,7 @@
</h1>
<p class="intro-text">Embedded MUC chat demo</p>
<div class="converse-container">
<div id="conversejs"></div>
<converse-root></converse-root>
</div>
</div>
</div>

View File

@ -10,12 +10,13 @@
<meta name="keywords" content="xmpp chat webchat converse.js" />
<link rel="manifest" href="./manifest.json">
<link rel="shortcut icon" type="image/ico" href="images/favicon.ico"/>
<link type="text/css" rel="stylesheet" media="screen" href="dist/website.css" />
<link type="text/css" rel="stylesheet" media="screen" href="dist/converse.css" />
<script src="https://cdn.conversejs.org/3rdparty/libsignal-protocol.min.js"></script>
<script src="dist/converse.js"></script>
</head>
<body class="reset">
<body class="reset" style="background-color: var(--global-background-color)">
<div id="conversejs-bg"></div>
<script>
@ -27,19 +28,22 @@
});
converse.initialize({
i18n: 'af',
theme: 'dracula',
auto_away: 300,
enable_smacks: true,
i18n: 'af',
loglevel: 'debug',
reuse_scram_keys: true,
prune_messages_above: 100,
message_archiving: 'always',
muc_respect_autojoin: true,
muc_show_logs_before_join: true,
notify_all_room_messages: ['discuss@conference.conversejs.org'],
persistent_store: 'IndexedDB',
theme: 'concord',
view_mode: 'fullscreen',
websocket_url: 'wss://conversejs.org/xmpp-websocket',
// websocket_url: 'wss://conversejs.org/xmpp-websocket',
websocket_url: 'ws://chat.example.org:5380/xmpp-websocket',
whitelisted_plugins: ['converse-debug'],
// connection_options: { worker: '/dist/shared-connection-worker.js' }
});
</script>
</body>

View File

@ -39,7 +39,7 @@ h5 {
}
.sponsors-list {
overflow-y: hidden !important;
overflow-y: auto !important;
overflow-x: hidden;
}
@ -88,21 +88,21 @@ h5 {
/*
Copyright (c) 2012 Terrence Ryan
Permission is hereby granted, free of charge, to any person obtaining a copy of this
software and associated documentation files (the "Software"), to deal in the Software
without restriction, including without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to the following
Permission is hereby granted, free of charge, to any person obtaining a copy of this
software and associated documentation files (the "Software"), to deal in the Software
without restriction, including without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be included in all copies
The above copyright notice and this permission notice shall be included in all copies
or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
OR OTHER DEALINGS IN THE SOFTWARE.
*/
@ -119,42 +119,42 @@ OR OTHER DEALINGS IN THE SOFTWARE.
display: block;
width: 235px;
font-size: 14px;
font-family: Frutiger, "Frutiger Linotype", Univers, Calibri, "Gill Sans", "Gill Sans MT",
"Myriad Pro", Myriad, "DejaVu Sans Condensed", "Liberation Sans", "Nimbus Sans L", Tahoma,
font-family: Frutiger, "Frutiger Linotype", Univers, Calibri, "Gill Sans", "Gill Sans MT",
"Myriad Pro", Myriad, "DejaVu Sans Condensed", "Liberation Sans", "Nimbus Sans L", Tahoma,
Geneva, "Helvetica Neue", Helvetica, Arial, sans serif;
background-color: #333;
color: #FFF;
word-spacing: 2px;
text-decoration: none;
padding: 5px 15px 5px 25px;
position:relative;
left: 20px;
top: -33px;
text-align: center;
-moz-transform-origin: 0 0 ;
-moz-transform:rotate(45deg);
-moz-box-shadow: 1px 1px 5px 1px #666;
-webkit-transform-origin: 0 0 ;
-webkit-transform-origin: 0 0 ;
-webkit-transform:rotate(45deg);
-webkit-box-shadow: 1px 1px 5px 1px #666;
-ms-transform-origin: 0 0 ;
-ms-transform-origin: 0 0 ;
-ms-transform:rotate(45deg);
-ms-box-shadow: 1px 1px 5px 1px #666;
transform-origin: 0 0 ;
transform-origin: 0 0 ;
transform:rotate(45deg);
box-shadow: 1px 1px 5px 1px #666;
background-image: linear-gradient(bottom, #000000 3%, #666666 5%, #000000 7%, #000000 93%, #666666 95%, #000000 97%);
background-image: -o-linear-gradient(bottom, #000000 3%, #666666 5%, #000000 7%, #000000 93%, #666666 95%, #000000 97%);
background-image: -moz-linear-gradient(bottom, #000000 3%, #666666 5%, #000000 7%, #000000 93%, #666666 95%, #000000 97%);
background-image: -webkit-linear-gradient(bottom, #000000 3%, #666666 5%, #000000 7%, #000000 93%, #666666 95%, #000000 97%);
background-image: -ms-linear-gradient(bottom, #000000 3%, #666666 5%, #000000 7%, #000000 93%, #666666 95%, #000000 97%);
background-image: -webkit-gradient(
linear,
left bottom,
@ -165,5 +165,5 @@ OR OTHER DEALINGS IN THE SOFTWARE.
color-stop(0.93, #000000),
color-stop(0.95, #666666),
color-stop(0.97, #000000)
);
);
}

View File

@ -6,11 +6,9 @@
<script src="scripts/prettify/prettify.js"></script>
<script src="scripts/prettify/lang-css.js"></script>
<script src="./analytics.js"></script>
<script src="/dist/converse.min.js"></script>
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
<link type="text/css" rel="stylesheet" href="/docs/source/_static/api.css">
<link type="text/css" rel="stylesheet" href="/dist/converse.min.css">
<link rel="shortcut icon" href="/images/favicon.ico"/>
</head>
@ -61,6 +59,5 @@
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
<script>converse.initialize({'bosh_service_url': 'https://conversejs.org/http-bind/'});</script>
</body>
</html>

View File

@ -2,15 +2,12 @@
{% extends "!layout.html" %}
{# Custom CSS overrides #}
{% set css_files = css_files + ['_static/style.css', "../../dist/converse.min.css"] %}
{% set script_files = script_files + ["../../dist/converse.min.js", "../../analytics.js"] %}
{% set css_files = css_files + ['_static/style.css'] %}
{% set script_files = script_files + ["../../analytics.js"] %}
{# Add some extra stuff before and use existing with 'super()' call. #}
{% block footer %}
{{ super() }}
<script>
converse.initialize({'bosh_service_url': 'https://conversejs.org/http-bind/'});
</script>
{% endblock %}

View File

@ -2,17 +2,21 @@
<h4 class="sidebar-title">Sponsored by</h4>
</span>
<ul class="sponsors-list">
<li><a href="https://www.keycdn.com/?utm_source=conversejs" target="_blank" rel="noopener">
<img style="height: 2em" src="/logo/keycdn.png" alt="KeyCDN">
</a>
</li>
<li><a href="https://www.codefirst.co.uk/?utm_source=conversejs" target="_blank" rel="noopener">
<img style="width: 9em" src="/logo/codefirst.png" alt="Codefirst">
<li><a href="https://bairesdev.com/sponsoring-open-source-projects/?utm_source=conversejs" target="_blank" rel="noopener">
<img style="width: 10em" src="/media/logos/bairesdev-primary.png" alt="BairesDev">
</a>
</li>
<li><a href="https://blokt.com/?utm_source=conversejs" target="_blank" rel="noopener">
<img style="width: 9em" src="/logo/blokt.png" alt="Blokt Crypto & Privacy">
</a>
</li>
<li><a href="https://primesound.org/?utm_source=conversejs" target="_blank" rel="noopener">
<img style="width: 9em" src="/media/logos/primesound.png" alt="Prime Sound">
</a>
</li>
<li><a href="https://www.keycdn.com/?utm_source=conversejs" target="_blank" rel="noopener">
<img style="height: 2.5em" src="/logo/keycdn.png" alt="KeyCDN">
</a>
</li>
</ul>
<span class="centered-text-container patreon-link-container"><a href="https://conversejs.org#sponsors">Become a sponsor</a></span>

View File

@ -1,6 +1,6 @@
.. raw:: html
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/theming.rst">Edit me on GitHub</a></div>
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/api/index.rst">Edit me on GitHub</a></div>
============================================
The API documentation (generated with JSDoc)

View File

@ -48,9 +48,9 @@ copyright = u'2018, JC Brand'
# built documents.
#
# The short X.Y version.
version = '7.0.0'
version = '10.1.6'
# The full version, including alpha/beta/rc tags.
release = '7.0.0'
release = '10.1.6'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.

View File

@ -23,6 +23,38 @@ all the available configuration settings.
Configuration settings
======================
.. _`allowed_audio_domains`:
allowed_audio_domains
---------------------
* Default: ``null``
If falsy, all domains are allowed. Set it to an array to specify a whitelist of allowed domains.
.. _`allowed_image_domains`:
allowed_image_domains
---------------------
* Default: ``null``
If falsy, all domains are allowed. Set it to an array to specify a whitelist of allowed domains.
E.g. ``['imgur.com', 'imgbb.com']``
.. _`allowed_video_domains`:
allowed_video_domains
---------------------
* Default: ``null``
If falsy, all domains are allowed. Set it to an array to specify a whitelist of allowed domains.
E.g. ``['imgur.com']``
authentication
--------------
@ -118,13 +150,6 @@ This setting is only applicable if the ``converse-bookmarks`` plugin is loaded.
See also: `allow_public_bookmarks`_
allow_chat_pending_contacts
---------------------------
* Default: ``false``
Allow the user to chat with pending contacts.
allow_contact_removal
---------------------
@ -149,7 +174,7 @@ allow_dragresize
* Default: ``true``
Allow users to resize chats by dragging the edges. The min-height and min-width
CSS properties set on a chatboxes (specifically on the ``#converse.js .chatbox > .box-flyout`` element)
CSS properties set on a chatboxes (specifically on the ``.chatbox > .box-flyout`` element)
will be honored, IF they are set in pixels.
allow_logout
@ -184,14 +209,14 @@ Determines who is allowed to retract messages. If set to ``'all'``, then normal
users may retract their own messages and ``'moderators'`` may retract the messages of
other users.
allow_muc
---------
allow_message_styling
---------------------
* Default: ``true``
* Possible values: ``true``, ``false``
Determines wehether support for XEP-0393 Message Styling hints are enabled or not.
Allow multi-user chat (muc) in chatrooms. Setting this to ``false`` will remove
the ``Chatrooms`` tab from the control box.
allow_muc_invitations
---------------------
@ -243,6 +268,12 @@ Support for `XEP-0077: In band registration <https://xmpp.org/extensions/xep-007
Allow XMPP account registration showing the corresponding UI register form interface.
allow_url_history_change
------------------------
* Default: ``true``
Allow Converse to change the browser url bar through the History API <https://developer.mozilla.org/en-US/docs/Web/API/History_API>.
allow_user_trust_override
-------------------------
@ -289,6 +320,7 @@ available) and the amount returned will be no more than the page size.
You will be able to query for even older messages by scrolling upwards in the chatbox or room
(the so-called infinite scrolling pattern).
autocomplete_add_contact
------------------------
@ -375,7 +407,6 @@ in to their XMPP account.
So currently if EITHER ``keepalive`` or ``auto_login`` is ``true`` and
`authentication`_ is set to ``login``, then Converse will try to log the user in.
auto_away
---------
@ -422,12 +453,17 @@ auto_register_muc_nickname
--------------------------
* Default: ``false``
* Allowed values: ``false``, ``true``, ``'unregister'``
Determines whether Converse should automatically register a user's nickname
when they enter a groupchat.
If truthy, Converse will automatically register a user's nickname upon entering
a groupchat.
See here fore more details: https://xmpp.org/extensions/xep-0045.html#register
If set to ``'unregister'``, then the user's nickname will be registered
(because it's a truthy value) and also be unregistered when the user
permanently leaves the MUC by closing it.
auto_subscribe
--------------
@ -657,7 +693,7 @@ appear in another.
.. code-block:: javascript
converse.initialize({
connection_options: { 'worker': true }
connection_options: { worker: '/dist/shared-connection-worker.js' }
});
@ -716,6 +752,14 @@ loglevel
You can also set this value by changing a URL fragment `#converse?loglevel=debug`
.. _`dark_theme`:
dark_theme
----------
* Default: ``'dracula'``
The theme being used in dark mode.
default_domain
--------------
@ -732,14 +776,6 @@ JIDs with other domains are still allowed but need to be provided in full.
To specify only one domain and disallow other domains, see the `locked_domain`_
option.
registration_domain
-------------------
* Default: ``''``
Specify a domain name for which the registration form will be fetched automatically,
without the user having to enter any XMPP server domain name.
default_state
-------------
@ -865,7 +901,7 @@ The app servers are specified with the `push_app_servers`_ option.
enable_smacks
-------------
* Default: ``false``
* Default: ``true``
Determines whether `XEP-0198 Stream Management <https://xmpp.org/extensions/xep-0198.html>`_
support is turned on or not.
@ -889,12 +925,6 @@ filter_url_query_params
Accepts a string or array of strings. Any query strings from URLs that match this setting will be removed.
fullname
--------
If you are using prebinding, can specify the fullname of the currently
logged in user, otherwise the user's vCard will be fetched.
geouri_regex
------------
@ -925,22 +955,6 @@ hide_offline_users
If set to ``true``, then offline users aren't shown in the roster.
hide_open_bookmarks
-------------------
* Default: ``false`` (``true`` when the `view_mode`_ is set to ``fullscreen``).
This setting applies to the ``converse-bookmarks`` plugin and specfically the
list of bookmarks shown in the ``Rooms`` tab of the control box.
By default all bookmarks are shown in that list, if this setting is set to
``true``, then only bookmarks for rooms not currently open (i.e. that the
current user hasn't joined), are shown.
Makes sense to set this to ``true`` when also using the non-core
``converse-roomslist`` plugin, which shows a list of currently open (i.e.
"joined") rooms.
.. _`i18n`:
i18n
@ -1064,8 +1078,32 @@ VCard is taken, and if that is not set but `muc_nickname_from_jid`_ is set to
If no nickame value is found, then an error will be raised.
mam_request_all_pages
---------------------
* Default: ``true``
When requesting messages from the archive, Converse will ask only for messages
newer than the most recent cached message.
When there are many archived messages since that one, the returned results will
be broken up in to pages, set by `archived_messages_page_size`_.
By default Converse will request all the pages until all messages have been
fetched, however for large archives this can slow things down dramatically.
This setting turns the paging off, and Converse will only fetch the latest
page.
.. note::
If paging is turned off, there will appear gaps in the message history.
Converse currently doesn't yet have a way to inform the user of these gaps or
to let them be filled.
muc_hats
-------------------
--------
* Default: ``['xep317']``
@ -1141,22 +1179,6 @@ from the XMPP server.
Used in conjunction with ``message_archiving`` and in context of `XEP-0313: Message Archive Management <https://xmpp.org/extensions/xep-0313.html>`_.
message_carbons
---------------
* Default: ``true``
Support for `XEP-0280: Message Carbons <https://xmpp.org/extensions/xep-0280.html>`_
In order to keep all IM clients for a user engaged in a conversation,
outbound messages are carbon-copied to all interested resources.
This is especially important with Converse, where each browser
tab serves as a separate IM client.
XEP-0280 requires server support, so make sure that message carbons are enabled
on your server.
message_limit
-------------
@ -1190,6 +1212,16 @@ If all roles or all affiliations are disabled, then the relevant tab won't be
showed at all.
muc_clear_messages_on_leave
---------------------------
* Default: ``true``
Starting with Converse 8.0.0, when leaving a MUC, all cached messages in the history is cleared.
Note: This means that you lose your history of decrypted OMEMO messages and cannot recover it.
muc_disable_slash_commands
--------------------------
@ -1300,8 +1332,7 @@ If set to ``true``, then whenever Converse receives a MUC message with an autho
any information (i.e. because that user is currently not in the MUC), then Converse will send out a ``<presence>``
stanza of type ``probe`` in order to request the authors presence data.
Prosody has some experimental support in it's contrib branch (hopefully soon to
be merged to trunk).
Prosody has support in `trunk` for this.
The point of sending out presence probes is in order to receive
presence-related metadata, such as `XEP-0317 Hats <https://xmpp.org/extensions/xep-0317.html>`_.
@ -1372,13 +1403,53 @@ Example:
muc_roomid_policy_hint: '<br><b>Policy for groupchat id:</b><br>- between 5 and 40 characters,<br>- lowercase from a to z (no special characters) or<br>- digits or<br>- dots (.) or<br>- underlines (_) or<br>- hyphens (-),<br>- no spaces<br>',
muc_show_join_leave
-------------------
muc_show_info_messages
----------------------
* Default; ``true``
* Default: List composed of MUC status codes, role changes, join and leave events and affiliation changes. The values of converse.MUC_INFO_CODES below are joined to build the default list:
Determines whether Converse will show info messages inside a chatroom
whenever a user joins or leaves it.
.. code-block:: javascript
converse.MUC_AFFILIATION_CHANGES_LIST = ['owner', 'admin', 'member', 'exowner', 'exadmin', 'exmember', 'exoutcast']
converse.MUC_ROLE_CHANGES_LIST = ['op', 'deop', 'voice', 'mute'];
converse.MUC_TRAFFIC_STATES_LIST = ['entered', 'exited'];
converse.MUC_INFO_CODES = {
'visibility_changes': ['100', '102', '103', '172', '173', '174'],
'self': ['110'],
'non_privacy_changes': ['104', '201'],
'muc_logging_changes': ['170', '171'],
'nickname_changes': ['210', '303'],
'disconnect_messages': ['301', '307', '321', '322', '332', '333'],
'affiliation_changes': [...converse.AFFILIATION_CHANGES_LIST],
'join_leave_events': [...converse.MUC_TRAFFIC_STATES_LIST],
'role_changes': [...converse.MUC_ROLE_CHANGES_LIST],
};
This setting determines which info messages will Converse show inside a chatroom.
It is recommended to use the aforementioned Converse object in the following fashion
to build the list of desired info messages that will be shown:
.. code-block:: javascript
muc_show_info_messages: [
...converse.MUC_INFO_CODES.visibility_changes,
...converse.MUC_INFO_CODES.self,
...converse.MUC_INFO_CODES.non_privacy_changes,
...converse.MUC_INFO_CODES.muc_logging_changes,
...converse.MUC_INFO_CODES.nickname_changes,
...converse.MUC_INFO_CODES.disconnect_messages,
...converse.MUC_INFO_CODES.affiliation_changes,
...converse.MUC_INFO_CODES.join_leave_events,
...converse.MUC_INFO_CODES.role_changes,
]
By default all info messages are shown.
The behaviour of this setting is whitelisting, so if it is overriden all the desired
events must be specified.
If an empty list is provided, no info message will be displayed at all.
muc_show_logs_before_join
-------------------------
@ -1387,9 +1458,23 @@ muc_show_logs_before_join
If set to ``true``, when opening a MUC for the first time (or if you don't have
a nickname configured for it), you'll see the message history (if the
server supports [XEP-0313 Message Archive Management](https://xmpp.org/extensions/xep-0313.html))
server supports `XEP-0313 Message Archive Management <https://xmpp.org/extensions/xep-0313.html>`_)
and the nickname form at the bottom.
muc_subscribe_to_rai
--------------------
* Default: ``false``
This option enables support for `XEP-0437 Room Activity Indicators <https://xmpp.org/extensions/xep-0437.html>`_.
When a MUC is no longer visible (specifically, when the ``hidden`` flag becomes ``true``),
then Converse will exit the MUC and subscribe to activity indicators on the MUC host.
When the MUC becomes visible again (``hidden`` gets set to ``false``), the MUC will be rejoined.
.. _`nickname`:
nickname
@ -1582,11 +1667,12 @@ compile time.
This configuration seting allows this value to be set at runtime as well.
.. _persistent-store:
persistent_store
----------------
* Default: ``localStorage``
* Default: ``IndexedDB``
* Valid options: ``localStorage``, ``IndexedDB``, ``sessionStorage``, ``BrowserExtLocal``, ``BrowserExtSync``
Determines which store is used for storing persistent data.
@ -1603,12 +1689,40 @@ From version 7.0.0 onwards, Converse supports storing data in
When Converse is running inside a web browser extension, it can now take advantage of storage optimized to meet the specific storage needs of extensions.
BrowserExtSync represents the sync storage area.
BrowserExtSync represents the sync storage area.
Items in sync storage are synced by the browser and are available across all instances of that browser that the user is logged into, across different devices.
BrowserExtLocal represents the local storage area.
BrowserExtLocal represents the local storage area.
Items in local storage are local to the machine the extension was installed on
prune_messages_above
--------------------
* Default: ``undefined``
* Valid options: Any integer value above 0.
If this option is set to a positive integer, the chat history will be kept to
that number. As new messages come in, older messages will be deleted to
maintain the history size.
.. note::
When deleting locally stored decrypted OMEMO messages, you will **not** be
able to decrypt them again after fetching them from the server archive.
pruning_behavior
----------------
* Default: ``unscrolled``
* Valid options: ``unscrolled``, ``scrolled``
By default the chat history will only be pruned when the chat window isn't
scrolled up (``'unscrolled'``).
If set to ``'scrolled'``, then pruning will also happen when the chat is
scrolled up. Be aware that this will interfere with MAM-based infinite
scrolling, and this setting only makes sense when infinite scrolling with MAM
is disabled.
push_app_servers
----------------
@ -1644,6 +1758,82 @@ For example:
});
registration_domain
-------------------
* Default: ``''``
Specify a domain name for which the registration form will be fetched automatically,
without the user having to enter any XMPP server domain name.
render_media
------------
* Default: ``true``
* Possible values: ``true``, ``false`` or an array of domains for which media
should automatically be rendered.
If ``true``, media URLs (images, audio and video) will be rendered in the chat.
If ``false``, the URLs won't render as media, and instead only clickable links
will be shown.
Setting it to an array of domains means that media will be rendered only for URLs
matching those domains.
Media URLs are those URLs which appear to point to media files as well as URLs
for which `Open Graph Protocol (OGP) <https://modules.prosody.im/mod_ogp.html>`_
data was received (for example via Prosody's `mod_ogp <https://modules.prosody.im/mod_ogp.html>`_).
The OGP metadata must come from the MUC itself, metadata sent from participants
themselves will not be shown.
Based on the OGP metadata Converse will render a URL preview (also known as an
"unfurl").
.. note::
Note, even if this setting is ``false`` (or if the URL domain is not in the
array of allowed domains), a user can still click on the message
dropdown and click to show or hide the media for that particular message.
If you want to disable this ability, you can set the allowed domains for the
media type to an empty array.
See:
* `allowed_audio_domains`_
* `allowed_video_domains`_
* `allowed_image_domains`_
.. note::
This setting, together with the three allowed domain settings above, obsolete
the ``show_images_inline``, ``embed_audio`` and ``embed_videos`` settings.
reuse_scram_keys
----------------
* Default: ``false``
Most XMPP servers enable the Salted Challenge Response Authentication Mechanism
or SCRAM for short. This allows the user and the server to mutually
authenticate *without* the need to transmit the user's password in plaintext.
Assuming the server does not alter the user's password or the
storage parameters, we can authenticate with the same SCRAM key multiple times.
This opens an opportunity: we can store the user's login credentials in the
browser without storing the sensitive plaintext password, or the
need to set up complicated third party backends, like OAuth.
Enabling this option will let Converse save a user's SCRAM keys upon successful
login, and next time Converse is loaded the user will be automatically logged in
with those SCRAM keys.
.. _`roomconfig_whitelist`:
roomconfig_whitelist
@ -1708,6 +1898,7 @@ send_chat_state_notifications
-----------------------------
* Default: ``true``
* Allowed values: ``'active', 'composing', 'gone' 'inactive', 'paused'``
Determines whether chat state notifications (see `XEP-0085 <https://xmpp.org/extensions/xep-0085.html>`_) should be sent out or not.
@ -1721,7 +1912,17 @@ For example:
'send_chat_state_notifications': ['composing']
});
Valid values are ``'active', 'composing', 'gone' 'inactive', 'paused'``
send_chat_markers
-----------------
* Default: ``['received', 'displayed', 'acknowledged']``
Determines which (if any) of the `XEP-0333 <https://xmpp.org/extensions/xep-0333.html>`_ chat markers will be sent out.
It's still up to Converse to decide when to send out the relevant markers, the
purpose of this setting is merely to turn on or off the sending of the
individual markers.
show_chat_state_notifications
@ -1739,6 +1940,16 @@ show_client_info
Specifies whether the info icon is shown on the controlbox which when clicked opens an
"About" modal with more information about the version of Converse being used.
show_connection_url_input
-------------------------
* Default: ``false``
Determines whether the login form should show an input element where the user
can enter the connection URL. If it's a websocket url, then upon form
submission the `websocket_url`_ setting will be updated with this value, and if
it's an HTTP URL then the `bosh_service_url`_ setting will be updated.
show_controlbox_by_default
--------------------------
@ -1793,9 +2004,9 @@ show_images_inline
If set to ``false``, images won't be rendered in chats, instead only their links will be shown.
It also accepts an array strings of whitelisted domain names to only render images that belong to those domains.
Users will however still have the ability to render individual images via the message actions dropdown.
If you want to disallow users from doing so, set the ``allowed_image_domains`` option to an empty array ``[]``.
E.g. ``['imgur.com', 'imgbb.com']``
show_retraction_warning
-----------------------
@ -1826,6 +2037,14 @@ Adds a button to the chat which can be clicked or tapped in order to send the
message.
show_tab_notifications
----------------------
* Default: ``true``
Determines whether an unread messages counter is shown in the tab.
singleton
---------
@ -1851,6 +2070,7 @@ This setting relates to `XEP-0198 <https://xmpp.org/extensions/xep-0198.html>`_
and determines the number of stanzas to be sent before Converse will ask the
server for acknowledgement of those stanzas.
sounds_path
-----------
@ -1863,6 +2083,13 @@ themselves).
In order to support all browsers we need both an MP3 and an Ogg file. Make sure
to name your files ``msg_received.ogg`` and ``msg_received.mp3``.
stanza_timeout
--------------
* Default: ``20000`` (20 seconds)
The time to wait, in milliseconds, for a response stanza (for example to an IQ
request), before a timeout error is thrown and Converse stops waiting.
sticky_controlbox
-----------------
@ -1920,11 +2147,13 @@ If set to ``false``, this feature is disabled.
If set to ``a resource name``, Converse will synchronize only with a client that has that particular resource assigned to it.
.. _`theme`:
theme
-----
* Default: ``default``
* Valid options: ``default``, ``concord``
* Valid options: ``default``, ``concord``, ``dracula``
Let's you set a color theme for Converse.
@ -1954,13 +2183,6 @@ Converse render the emojis with `Twemoji <https://twemoji.twitter.com/>`_.
See also `emoji_image_path`_.
update_title
------------
* Default: ``true``
Determines whether to shows unread messages counter in the page title.
visible_toolbar_buttons
-----------------------
@ -2032,7 +2254,7 @@ The ``view_mode`` setting configures Converse's mode and resulting behavior.
* ``overlayed`` is the original mode, in which the chats appeared as small boxes overlaying a webpage which can contain arbitrary content.
* ``fullscreen`` is for a fullpage and single-page app.
* ``embedded`` is used to embed a single chat into a DOM element in the page. The DOM element must have the id ``#conversejs``.
* ``embedded`` is used to embed Converse into a particular part of the web page. Put the custom element ``<converse-root></converse-root>`` into your page HTML there were you want Converse to appear. See `conversejs.org/demo/embedded.html <https://conversejs.org/demo/embedded.html>`_ for an example of this view mode.
* ``mobile`` is for smaller viewports. Converse is responsive, and the other views will also resize to fit a smaller viewport, but certain behavioural changes won't be made. For example, when using ``overlayed`` in a mobile view, Converse won't know which chat is currently visible and therefore won't be able to properly show notifications for chats that are obscured.
.. note::

View File

@ -1,48 +1,57 @@
.. raw:: html
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/theming.rst">Edit me on GitHub</a></div>
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/dependencies.rst">Edit me on GitHub</a></div>
============
Dependencies
============
.. _`development`:
============================
Setting up a dev environment
============================
Installing the 3rd party dependencies
=====================================
We use development tools which depend on Node.js and npm (the Node package manager).
If you don't have Node.js installed, you can download and install the latest
version `here <https://nodejs.org/download>`_.
Alternatively you can `use your operating system's package manager to install
Node.js <https://nodejs.org/en/download/package-manager/#debian-and-ubuntu-based-linux-distributions>`_.
Also make sure you have ``Git`` installed. `See here <http://git-scm.com/book/en/Getting-Started-Installing-Git>`_.
Now use ``git`` to check out the Converse repository:
To develop and customize Converse, you'll first need to check out Converse's Git
repository:
::
git clone https://github.com/conversejs/converse.js.git
cd converse.js
Now go into the repository checkout and run ``make dev`` in order to set up the
development environment.
We use development tools which depend on Node.js and NPM (the Node package manager).
It's recommended that you use `NVM <https://github.com/nvm-sh/nvm>`_ (the Node version manager)
to make sure you have the right version of Node.
Refer to the `NVM Github page <https://github.com/nvm-sh/nvm#install--update-script>`_ for instructions on how to install it.
Once NVM is installed, you can run the following inside your checkout of the Converse Git repository:
::
nvm install
.. note::
You will always have to first run ``nvm install`` in a new terminal session before working on Converse.
To set up the Converse development environment, you now run ``make dev``.
::
cd converse.js
make dev
If you're using Windows, or don't have GNU Make installed, you can run the
Alternatively, if you're using Windows, or don't have GNU Make installed, you can run the
following:
::
cd converse.js
npm install
npm run lerna
This will install the Node.js development tools and Converse's dependencies.
This will install the Node development tools and Converse's dependencies.
The front-end dependencies are those JavaScript files on which
Converse directly depends and which will be loaded in the browser as part of
@ -64,30 +73,12 @@ the list under the ``devDependencies`` in `package.json <https://github.com/jcbr
where you can log in and be taken directly to the chatroom.
Brief description of Converse's dependencies
===============================================
Converse relies on the following dependencies:
* `DayJS <https://github.com/iamkun/dayjs>`_ provides a better API for handling dates and times.
* `Strophe.js <http://strophe.im/>`_ maintains the XMPP session, is used to
build XMPP stanzas, to send them, and to register handlers for received stanzas.
* `lodash <https://lodash.com/>`_ provides very useful utility functions.
* `Skeletor <https://github.com/skeletorjs/skeletor/>`_, a `Backbone <http://backbonejs.org/>`_ fork
which is used to model the data as Models and Collections and to create Views that render the UI.
* `pluggable.js <https://github.com/jcbrand/pluggable.js>`_ provides the plugin
architecture for Converse. It registers and initializes plugins and
allows existing attributes, functions and objects on Converse to be
overridden inside plugins.
.. _`dependency-libsignal`:
Libsignal
---------
If you want OMEMO encryption, you need to load `libsignal
<https://github.com/signalapp/libsignal-protocol-javascript>`_ separately in
your page.
If you want OMEMO encryption, you need to load `libsignal <https://github.com/signalapp/libsignal-protocol-javascript>`_ separately in your page.
For example::
@ -98,3 +89,51 @@ under the `GPLv3 <https://github.com/signalapp/libsignal-protocol-javascript/blo
which requires all other dependent JavaScript code to also be open sourced under the same
license. You might not be willing to adhere to those terms, which is why you
need to decide for yourself whether you're going to load libsignal or not.
.. _`webserver`:
Setting up a webserver
======================
When making changes to Converse, either development or theming changes,
you'll want to preview them in your browser.
For this, you'll need to serve the development files via a web server,
so that you can see your local changes in the browser.
Manually starting a web server
------------------------------
To both set up the development environment and also start up a web browser to
serve the files for you, you can run::
make serve
.. note::
To run the "make" commands, you'll need `GNUMake <https://www.gnu.org/software/make>`_
installed on your computer. If you use GNU/Linux or \*BSD, it should be installed or
available via your package manager. For Mac, you'll need to install XCode and in
Windows you can use `Chocolatey <https://chocolatey.org/>`_.
After running ``make serve`` you can open http://localhost:8000 in your webbrowser to see the Converse website.
When developing or changing the theme, you'll want to load all the
unminified JS and CSS resources as separate files. To do this, open http://localhost:8000/dev.html instead.
You might want to open `dev.html <https://github.com/conversejs/converse.js/blob/master/dev.html>`_ in your text editor or IDE as well, to see
how ``converse.initialize`` is called and to potentially change any of the
settings.
Starting a web server with live reloading
-----------------------------------------
Alternatively, if you want to have live reloading whenever any of the source files change, you
can run ``make devserver`` (which will use `webpack-dev-server <https://github.com/webpack/webpack-dev-server>`_).
Instead of ``dev.html`` being used, `webpack.html <https://github.com/conversejs/converse.js/blob/master/webpack.html>`_
is now being used as the HTML template, and you'll need to modify that file if
you want to change the settings passed to ``converse.initialize``.
If you're running ``make devserver``, you need to open http://localhost:8080.

View File

@ -2,7 +2,7 @@
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/development.rst">Edit me on GitHub</a></div>
.. _development:
.. _`development`:
===========
Development
@ -23,10 +23,10 @@ to fix a bug or to add new functionality.
.. toctree::
:maxdepth: 2
dependencies
style_guide
setup_dev_environment
plugin_development
api/index
testing
other_frameworks
builds
style_guide

View File

@ -31,10 +31,16 @@ End to end message encryption (`XEP-0384 OMEMO <https://xmpp.org/extensions/xep-
=============================================================================================
.. note::
Converse.js (as of version 4.1.2) does NOT support encryption or decryption
Converse versions older than 8.0.0 do NOT support encryption or decryption
of uploaded files. Files will be uploaded WITHOUT ENCRYPTION, even when
OMEMO is enabled.
.. note::
For end-to-end encryption via OMEMO, you'll need to load `libsignal-protocol.js
<https://github.com/signalapp/libsignal-protocol-javascript>`_ separately in
your page. Take a look at the section on :ref:`libsignal <dependency-libsignal>` and the
:ref:`security considerations around OMEMO <feature-omemo>`.
Converse supports OMEMO encryption based on the
`Signal Protocol <https://github.com/signalapp/libsignal-protocol-javascript>`_.
@ -44,7 +50,9 @@ ever tear down a session once one has been established.
This means that a session needs to be stored permanently after logging out.
Converse stores this session information in the browser's `localStorage <https://developer.mozilla.org/en-US/docs/Web/API/Storage/LocalStorage>`_.
Converse stores this session information in the browser's `IndexedDB <https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API>`_
or `localStorage <https://developer.mozilla.org/en-US/docs/Web/API/Storage/LocalStorage>`_
database, depending on the value provided to :ref:`persistent-store`.
If you've checked the "This is not a trusted device" checkbox when logging in,
then `sessionStorage <https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage>`_
@ -88,10 +96,7 @@ headers.
Due to these reasons, it's NOT a good idea to use encrypted messaging with a
browser-based solution in life-threatening situations.
Security can be increased by using an installable app (like one based on `Electron <https://electronjs.org/>`_)
with a strict Content Security Policy.
Look out for an Electron based version of Converse coming in the following months.
Security can be increased by using an installable app (like `Converse Desktop <https://github.com/conversejs/converse-desktop>`_).
For further reading on the challenges of web-based crypto, take a look at these
articles:

View File

@ -47,8 +47,8 @@ Table of Contents
session
configuration
development
security
theming
security
translations
troubleshooting
documentation

View File

@ -1,6 +1,6 @@
.. raw:: html
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/theming.rst">Edit me on GitHub</a></div>
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/other_frameworks.rst">Edit me on GitHub</a></div>
Integrating converse.js into other frameworks
=============================================

View File

@ -1,6 +1,6 @@
.. raw:: html
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/theming.rst">Edit me on GitHub</a></div>
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/plugin_development.rst">Edit me on GitHub</a></div>
.. _`writing-a-plugin`:
@ -16,7 +16,7 @@ and is itself composed out of plugins.
There are only a few files that are included in the default build of Converse
which aren't plugins.
An important one is `converse-core.js <https://github.com/conversejs/converse.js/blob/master/src/headless/converse-core.js>`_,
An important one is `core.js <https://github.com/conversejs/.js/blob/master/src/headless/core.js>`_,
which is responsible for bootstrapping the plugin architecture,
setting up and maintaining the connection to the XMPP
server and declaring the public (`window.converse </docs/html/api/converse.html>`_) and protected (`_converse.api </docs/html/api/-_converse.api.html>`_) APIs.
@ -167,7 +167,7 @@ Accessing 3rd party libraries
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Immediately inside the module shown above you can access 3rd party libraries (such
dayjs and lodash) via the ``converse.env`` map.
dayjs) via the ``converse.env`` map.
The code for it could look something like this:
@ -175,16 +175,64 @@ The code for it could look something like this:
// Commonly used utilities and variables can be found under the "env"
// namespace of the "converse" global.
const { Promise, Strophe, dayjs, sizzle, _, $build, $iq, $msg, $pres } = converse.env;
const { Promise, Strophe, dayjs, sizzle, $build, $iq, $msg, $pres } = converse.env;
These dependencies are closured so that they don't pollute the global
namespace, that's why you need to access them in such a way inside the module.
Overrides
---------
Overriding templates
--------------------
Converse uses `lit-html <https://lit-html.polymer-project.org/guide>`_
templates and templates are imported as separate files.
It's possible to configure your module bundler (e.g. Webpack) in such as way that a
different file is loaded when a template is imported.
This allows you to create your own templates that are used instead of the ones
that would have originally been imported.
With Webpack (which Converse uses internally), you can specify an
``alias`` for the template you want to override. This alias then points to your
own custom template.
For example, in your webpack config file, you could add the following to the
``config`` object that gets exported:
.. code-block:: javascript
resolve: {
extensions: ['.js'],
modules: [
path.join(__dirname, 'node_modules'),
path.join(__dirname, 'node_modules/converse.js/src')
],
alias: {
'plugins/profile/templates/profile.js$': path.resolve(__dirname, 'templates/custom-profile.js')
}
}
This will override the template that gets imported at the path ``plugins/profile/templates/profile.js``
with your own template at the path ``templates/custom-profile.js`` (relative to your webpack config file).
Object and class Overrides
--------------------------
.. note:: Using the `overrides` feature from pluggable.js is discouraged. It's
much better to use events, promises and `hooks`_ to modify the behaviour of
Converse.
The pluggable.js `overrides` will only work on objects and classes that are
set as attributes on the `_converse` object, which doesn't apply to many
newer classes and objects, such as the web components. For these clasess,
overrides won't work at all.
This section is left here for completeness, because in some special cases
overrides are still used.
Plugins can override core code or code from other plugins. You can specify
overrides in the object passed to ``converse.plugins.add``.
overrides in the object passed to ``converse.plugins.add``.
In an override you can still call the overridden function, by calling
``this.__super__.methodName.apply(this, arguments);`` where ``methodName`` is
@ -242,7 +290,7 @@ monkey patching which pollutes the call stack and can make your code fragile
and prone to bugs when Converse gets updated. Too much use of ``overrides``
is therefore a "code smell" which should ideally be avoided.
A better approach is to listen to the events emitted by Converse, and to add
A better approach is to use the events and `hooks`_ emitted by Converse, and to add
your code in event handlers. This is however not always possible, in which case
the overrides are a powerful tool.
@ -260,63 +308,6 @@ For example:
Object.assign(_converse.ChatBoxView.prototype, { doSomething });
Overriding a template
~~~~~~~~~~~~~~~~~~~~~
Converse uses various templates, loaded with lodash, to generate its HTML.
It's not possible to override a template with the plugin's ``overrides``
feature, instead you should configure a new path to your own template via your
module bundler.
For example, with Webpack (which Converse uses internall), you can specify an
``alias`` for the template you want to override. This alias then points to your
own custom template.
For example, in your webpack config file, you could add the following to the
``config`` object that gets exported:
.. code-block:: javascript
module: {
{
test: /templates\/.*\.(html|svg)$/,
use: [{
loader: 'lodash-template-webpack-loader',
options: {
escape: /\{\{\{([\s\S]+?)\}\}\}/g,
evaluate: /\{\[([\s\S]+?)\]\}/g,
interpolate: /\{\{([\s\S]+?)\}\}/g,
// By default, template places the values from your data in the
// local scope via the with statement. However, you can specify
// a single variable name with the variable setting. This can
// significantly improve the speed at which a template is able
// to render.
variable: 'o',
prependFilenameComment: __dirname
}
}]
}
},
resolve: {
extensions: ['.js'],
modules: [
path.join(__dirname, 'node_modules'),
path.join(__dirname, 'node_modules/converse.js/src')
],
alias: {
'templates/profile_view.html$': path.resolve(__dirname, 'templates/profile_view.html')
}
}
You'll need to install ``lodash-template-webpack-loader``.
Currently Converse uses a fork of `lodash-template-webpack-loader <https://github.com/jcbrand/lodash-template-webpack-loader>`_.
To install it, you can add ``"lodash-template-webpack-loader": "jcbrand/lodash-template-webpack-loader"``
to your package.json's ``devDependencies``.
.. _`dependencies`:
@ -459,8 +450,87 @@ Please refer to the `API documentation </docs/html/api/http://localhost:8008/doc
for an overview of what's available to you. If you need new events or promises, then
`please open an issue or make a pull request on Github <https://github.com/jcbrand/converse.js>`_
A full example plugin
---------------------
Hooks
-----
Converse has the concept of ``hooks``, which are special events that allow you
to modify it's behaviour at runtime.
A hook is similar to an event, but it differs in two meaningful ways:
1. Converse will wait for all handlers of a hook to finish before continuing inside the function from where the hook was triggered.
2. Each hook contains a payload, which the handlers can modify or extend, before returning it (either to the function that triggered the hook or to subsequent handlers).
These two properties of hooks makes it possible for 3rd party plugins to
intercept and update data, allowing them to modify Converse without the need of
resorting to `overrides`_.
A hook is triggered in the following way:
.. code-block:: javascript
async function hookTriggerExample () {
const payload = { foo: 'bar' };
const updated_payload = await api.hook('hookName', this, payload);
return updated_payload;
}
The above could be shortened:
.. code-block:: javascript
async function hookTriggerExample () {
return await api.hook('hookName', this, { foo: 'bar' });
}
The ``async/await`` syntax could also be removed, but then it's less clear to
the reader that this function returns a promise.
Let's assume that in a plugin somewhere a listener is registered for this hook:
.. code-block:: javascript
function hookListenerExample () {
api.listen.on('hookname', (context, payload) => {
return {...payload, 'baz': 'buzz'};
});
}
The ``context`` parameter in our listener is usually the ``this`` of the function
that triggered the hook (as is the case in ``hookTriggerExample``),
but could also be a ``Model`` instance.
The ``payload`` parameter is the same payload that was passed in in
``hookTriggerExample``.
The ``hookListenerExample`` function accepts the payload and returns a new one
which contains the original payload together with a new key and value.
The ``updated_payload`` that is now returned from ``hookTriggerExample`` looks
as follows:
::
{ foo: 'bar', bazz: 'buzz' }
Our plugin was able to add data to the payload without requiring any kind of
knowledge from ``hookTriggerExample`` about ``hookListenerExample`` and
without any kind of coupling betwee the code.
A good example of a real-world hook in Converse, is the
`getMessageActionButtons <https://conversejs.org/docs/html/api/-_converse.html#event:getMessageActionButtons>`_
which allows you to add, modify or delete the actions you can take on a message
in a chat.
The `Actions <https://github.com/conversejs/community-plugins/tree/master/packages/actions>`_
3rd party community plugin makes use of this hook to add extra actions such as
``like`` or ``dislike`` to chat messages.
An example plugin
-----------------
Below follows a documented example of a plugin. This is the same code that gets
generated by `generator-conversejs <https://github.com/jcbrand/generator-conversejs>`_.
@ -534,8 +604,8 @@ generated by `generator-conversejs <https://github.com/jcbrand/generator-convers
* _converse.api.promises.add('myPromise');
*
* Your plugin should then, when appropriate, resolve the
* promise by calling `_converse.api.emit`, which will also
* emit an event with the same name as the promise.
* promise by calling `_converse.api.trigger`, which will also
* trigger an event with the same name as the promise.
* For example:
*
* _converse.api.trigger('operationCompleted');
@ -549,53 +619,22 @@ generated by `generator-conversejs <https://github.com/jcbrand/generator-convers
*
* _converse.api.waitUntil('operationCompleted', function { ... });
*/
},
/* If you want to override some function or a model or
* view defined elsewhere in Converse, then you do that under
* the "overrides" namespace.
*/
overrides: {
/* For example, the private *_converse* object has a
* method "onConnected". You can override that method as follows:
/* In your plugin, you can also listen for hooks.
* Hooks allow you to add or modify data and properties used by
* Converse.
*
* For example, the getToolbarButtons hook allows you to add new buttons to the chat toolbar.
* https://conversejs.org/docs/html/api/-_converse.html#event:getToolbarButtons
*/
onConnected: function () {
// Overrides the onConnected method in Converse
// Top-level functions in "overrides" are bound to the
// inner "_converse" object.
const _converse = this;
// Your custom code can come here ...
// You can access the original function being overridden
// via the __super__ attribute.
// Make sure to pass on the arguments supplied to this
// function and also to apply the proper "this" object.
_converse.__super__.onConnected.apply(this, arguments);
// Your custom code can come here ...
},
/* Override Converse's XMPPStatus model so that we can override the
* function that sends out the presence stanza.
*/
XMPPStatus: {
sendPresence: function (type, status_message, jid) {
// The "_converse" object is available via the __super__
// attribute.
const _converse = this.__super__._converse;
// Custom code can come here ...
// You can call the original overridden method, by
// accessing it via the __super__ attribute.
// When calling it, you need to apply the proper
// context as reference by the "this" variable.
this.__super__.sendPresence.apply(this, arguments);
// Custom code can come here ...
}
}
api.listen.on('getToolbarButtons', (toolbar_el, buttons) => {
buttons.push(html`
<button class="my-button" @click=${alert('hello world!')}>
<converse-icon class="fa fa-eye" size="1em" color="blue"></converse-icon>
</button>
`);
return buttons;
});
}
});

View File

@ -21,8 +21,9 @@ Let your XMPP server serve Converse for you
If you run your own XMPP server, you might first want to check whether it has
a plugin or module for hosting Converse.
* OpenFire has the `inverse <https://www.igniterealtime.org/projects/openfire/plugin-archive.jsp?plugin=inverse>`_ plugin.
* Prosody has `mod_conversejs <https://modules.prosody.im/mod_conversejs.html>`_.
* `Openfire <http://www.igniterealtime.org/projects/openfire/>`_ has the `inverse <https://www.igniterealtime.org/projects/openfire/plugin-archive.jsp?plugin=inverse>`_ plugin.
* `Prosody <https://prosody.im/>`_ has `mod_conversejs <https://modules.prosody.im/mod_conversejs.html>`_.
* `ejabberd <http://www.ejabberd.im/>`_ has `mod_conversejs <https://docs.ejabberd.im/admin/configuration/modules/#mod-conversejs>`_.
Serving Converse yourself
@ -55,16 +56,16 @@ might break when a new backwards-incompatible version of Converse is released.
To load a specific version of Converse you can put the version in the URL:
* https://cdn.conversejs.org/7.0.0/dist/converse.min.js
* https://cdn.conversejs.org/7.0.0/dist/converse.min.css
* https://cdn.conversejs.org/10.1.6/dist/converse.min.js
* https://cdn.conversejs.org/10.1.6/dist/converse.min.css
You can include these two URLs inside the *<head>* element of your website
via the *script* and *link* tags:
.. code-block:: html
<link rel="stylesheet" type="text/css" media="screen" href="https://cdn.conversejs.org/7.0.0/dist/converse.min.css">
<script src="https://cdn.conversejs.org/7.0.0/dist/converse.min.js" charset="utf-8"></script>
<link rel="stylesheet" type="text/css" media="screen" href="https://cdn.conversejs.org/10.1.6/dist/converse.min.css">
<script src="https://cdn.conversejs.org/10.1.6/dist/converse.min.js" charset="utf-8"></script>
Option 2: Download the builds from Github

View File

@ -1,6 +1,6 @@
.. raw:: html
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/theming.rst">Edit me on GitHub</a></div>
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/security.rst">Edit me on GitHub</a></div>
=======================
Security considerations

View File

@ -1,8 +1,6 @@
.. raw:: html
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/setup.rst">Edit me on GitHub</a></div>
.. _what-you-will-need:
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/session.rst">Edit me on GitHub</a></div>
==================
Session Management
@ -204,5 +202,4 @@ Storing the SASL SCRAM-SHA1 hash in IndexedDB
Another suggestion that's been suggested is to store the SCRAM-SHA1 computed
``clientKey`` in localStorage and to use that upon page reload to log the user in again.
We might implement this feature in core Converse.js eventually.
As always, contributions welcome!
This has been implemented since version 10, see documentation on `reuse_scram_keys <https://conversejs.org/docs/html/configuration.html#reuse-scram-keys>`_

View File

@ -0,0 +1,140 @@
.. raw:: html
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/setup_dev_environment.rst">Edit me on GitHub</a></div>
.. _`setup_dev_environment`:
============================
Setting up a dev environment
============================
Installing the 3rd party dependencies
=====================================
To develop and customize Converse, you'll first need to check out Converse's Git
repository:
::
git clone https://github.com/conversejs/converse.js.git
cd converse.js
We use development tools which depend on Node.js and NPM (the Node package manager).
It's recommended that you use `NVM <https://github.com/nvm-sh/nvm>`_ (the Node version manager)
to make sure you have the right version of Node.
Refer to the `NVM Github page <https://github.com/nvm-sh/nvm#install--update-script>`_ for instructions on how to install it.
Once NVM is installed, you can run the following inside your checkout of the Converse Git repository:
::
nvm install
.. note::
You will always have to first run ``nvm install`` in a new terminal session in order to use the
recommended version of Node before working on Converse.
To set up the Converse development environment, you now run ``make dev``.
::
make dev
Alternatively, if you're using Windows, or don't have GNU Make installed, you can run the
following:
::
npm install
npm run lerna
This will install the Node development tools and Converse's dependencies.
The front-end dependencies are those JavaScript files on which
Converse directly depends and which will be loaded in the browser as part of
the bundle in ``dist/converse.js`` (or ``dist/converse.min.js``).
To see the 3rd party dependencies (not just the front-end dependencies, but
also ones necessary for development tasks like making builds), take a look at
the list under the ``devDependencies`` in `package.json <https://github.com/jcbrand/converse.js/blob/master/package.json>`_.
.. note::
After running ```make dev```, you should now have a new *node_modules* directory
which contains all the external dependencies of Converse.
If this directory does NOT exist, something must have gone wrong.
Double-check the output of ```make dev``` to see if there are any errors
listed. For support, you can ask in our chatroom: `dicuss@conference.conversejs.org <xmpp:discuss@conference.conversejs.org>`_.
If you don't have an XMPP client installed, follow this link to
`conversejs.org <https://conversejs.org/fullscreen#converse/room?jid=discuss@conference.conversejs.org>`_
where you can log in and be taken directly to the chatroom.
.. _`dependency-libsignal`:
Libsignal
---------
If you want OMEMO encryption, you need to load `libsignal <https://github.com/signalapp/libsignal-protocol-javascript>`_ separately in your page.
For example::
<script src="3rdparty/libsignal-protocol-javascript/dist/libsignal-protocol.js"></script>
The reason libsignal needs to be loaded separately is because it's released
under the `GPLv3 <https://github.com/signalapp/libsignal-protocol-javascript/blob/master/LICENSE>`_
which requires all other dependent JavaScript code to also be open sourced under the same
license. You might not be willing to adhere to those terms, which is why you
need to decide for yourself whether you're going to load libsignal or not.
.. _`webserver`:
Setting up a webserver
======================
When making changes to Converse, either development or theming changes,
you'll want to preview them in your browser.
For this, you'll need to serve the development files via a web server,
so that you can see your local changes in the browser.
Manually starting a web server
------------------------------
To both set up the development environment and also start up a web browser to
serve the files for you, you can run::
make serve
.. note::
To run the "make" commands, you'll need `GNUMake <https://www.gnu.org/software/make>`_
installed on your computer. If you use GNU/Linux or \*BSD, it should be installed or
available via your package manager. For Mac, you'll need to install XCode and in
Windows you can use `Chocolatey <https://chocolatey.org/>`_.
After running ``make serve`` you can open http://localhost:8000 in your webbrowser to see the Converse website.
When developing or changing the theme, you'll want to load all the
unminified JS and CSS resources as separate files. To do this, open http://localhost:8000/dev.html instead.
You might want to open `dev.html <https://github.com/conversejs/converse.js/blob/master/dev.html>`_ in your text editor or IDE as well, to see
how ``converse.initialize`` is called and to potentially change any of the
settings.
Starting a web server with live reloading
-----------------------------------------
Alternatively, if you want to have live reloading whenever any of the source files change, you
can run ``make devserver`` (which will use `webpack-dev-server <https://github.com/webpack/webpack-dev-server>`_).
Instead of ``dev.html`` being used, `webpack.html <https://github.com/conversejs/converse.js/blob/master/webpack.html>`_
is now being used as the HTML template, and you'll need to modify that file if
you want to change the settings passed to ``converse.initialize``.
If you're running ``make devserver``, you need to open http://localhost:8080.

View File

@ -1,6 +1,6 @@
.. raw:: html
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/theming.rst">Edit me on GitHub</a></div>
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/style_guide.rst">Edit me on GitHub</a></div>
Software Style Guide
====================
@ -11,7 +11,7 @@ Most of the style guide recommendations here come from Douglas Crockford's book
Tabs or spaces?
---------------
We always indent 4 spaces. Proper indentation is important for readability.
We always indent 4 spaces.
Underscores or camelCase?
-------------------------
@ -27,6 +27,12 @@ For example:
...
}
const versus let
----------------
Try to use `const` whenever possible. If a variable won't be reassigned, use
`const`, otherwise use `let`.
Spaces around operators
-----------------------
@ -51,6 +57,19 @@ An exception is when they appear inside for-loop expressions, for example:
Generally though, rather err on the side of adding spaces, since they make the
code much more readable.
destructuring
-------------
When assigning to a variable via destructuring, add spaces between the curly
brackets.
For example:
.. code-block:: javascript
const { foo } = bar;
Global constants are written in ALL_CAPS
----------------------------------------

View File

@ -29,21 +29,17 @@ Automatically run tests on file changes
***************************************
To automatically run the tests whenever you make a change to any of the
Converse source code, you can run ``make watch`` in one terminal, and ``make
tests`` or ``make check`` in another.
Converse source code, you can run ``make watch`` in one terminal, and ``make tests`` in another.
``make watch`` will build development bundles of Converse.js (in
``dist/converse.js`` and ``dist/converse.css``) and automatically rebuild them
whenever a source file is modified.
Similarly, Karma will make sure that the tests are re-executed when the
bundle files are rebuilt.
``make watch`` will build development bundles of Converse (in ``dist/converse.js`` and ``dist/converse.css``)
and automatically rebuild them whenever a source file is modified.
Similarly, Karma will make sure that the tests are re-executed when the bundle files are rebuilt.
Running individual tests
************************
Converse has over 400 tests, and it can take a few minutes to run through all of them.
Converse has over 400 tests, and it can take a while to run through all of them.
When developing on Converse, it's often preferable to have a more rapid
turnaround time between editing a file and checking whether the most relevant

View File

@ -11,61 +11,135 @@ Theming
Setting up your environment
===========================
In order to theme Converse, you first need to set up a :ref:`development` environment.
In order to theme Converse, you first need to follow the steps for :ref:`setup_dev_environment`, including :ref:`webserver`.
You'll also want to preview the changes you make in your browser, for which a
webserver will be useful.
Creating a custom theme
=======================
To both set up the development environment and also start up a web browser to
serve the files for you, simply run::
Converse can be themed via CSS custom properties (aka CSS variables) and it has
some themes available in its source repository.
make serve
A theme is a CSS file with a specific rule that defines the theme's CSS properties.
The rule has a specific selector that must include (and determines) the theme name.
.. note::
To run the "make" commands, you'll need `GNUMake <https://www.gnu.org/software/make>`_
installed on your computer. If you use GNU/Linux or \*BSD, it should be installed or
available via your package manager. For Mac, I think you need to install XCode and in
Windows you can use `Chocolatey <https://chocolatey.org/>`_.
Inside this CSS rule, various CSS variables are assigned values.
The CSS variables mainly refer to the colors that comprise the theme.
If you don't specify a value for a specific CSS variable, then the value from
the ``classic`` theme is used, as defined in `classic.scss <https://github.com/conversejs/converse.js/tree/master/src/shared/styles/themes/classic.scss>`_.
After running ``make serve`` you can open http://localhost:8000 in your webbrowser you'll
see the Converse website.
The native theme files can be found in `shared/styles/themes <https://github.com/conversejs/converse.js/tree/master/src/shared/styles/themes>`_.
However, when developing or changing the theme, you'll want to load all the
unminified JS and CSS resources as separate files. To do this, open http://localhost:8000/dev.html
instead.
Note, the Converse theme files have a ``.scss`` extension because they are compiled
by the Sass compiler into normal CSS files. It's however not necessary to use
Sass, basic CSS files will also suffice.
The theme that Converse uses can be set via the :ref:`theme` configuration
setting (and the :ref:`dark_theme` configuration setting for dark mode).
How are themes applied?
-----------------------
When you set a value for the :ref:`theme` configuration setting, Converse will add
a class ``theme-${api.settings.get('theme')}`` on the ``converse-root`` DOM
element.
So, for example, if you set the ``theme`` setting to ``"dracula"``, then the
``converse-root`` element will get the class ``theme-dracula``.
.. code-block:: javascript
converse.initialize({ theme: "dracula" });
Modifying the HTML templates of Converse
========================================
.. code-block:: html
The HTML markup of Converse is contained in small ``.html`` files in the
``./src/templates`` directory.
<converse-root class="conversejs theme-dracula"></converse-root>
You can modify HTML markup that Converse generates by modifying these files.
The apply a theme, there then needs to be a CSS rule with a selector that matches the
``theme-dracula`` class on the ``converse-root`` element.
If you take a look at the theme file `dracula.scss <https://github.com/conversejs/converse.js/tree/master/src/shared/styles/themes/dracula.scss>`_
you'll see that it defines a CSS rule with the selector
``.conversejs.theme-dracula``.
This selector matches any DOM element with both the classes ``.conversejs`` and
``.theme-dracula``. The ``converse-root`` element will already have the class
``.conversejs`` and it will have the class ``.theme-dracula`` if the ``theme``
(or ``dark_theme`` in dark mode) configuration setting is set to ``"dracula"``.
This is how themes are applied, by defining a CSS selector that matches the
class ``.theme-${name}`` (where ``name`` is a variable containing the name of
the theme), and then setting the ``theme`` (and/or ``dark_theme``) configuration
setting.
To create your own theme, you can create a similar CSS rule that matches
your theme's name and then you set the ``theme`` configuration setting to that
name. This CSS rule can be in any CSS file that is loaded in your website, or
you can even put it in the DOM as an inline style.
Modifying the CSS
=================
The CSS files are generated from `Sass <http://sass-lang.com>`_ files in the ``./sass`` directory.
To create a new theme with different colors, it should be enough to create a
theme file that sets the various CSS variables (as described above).
To generate the CSS you can run::
For other CSS-related changes, you can make a specific
CSS rule with that matches the element you want to change.
Sometimes it might however be neccessary to modify the core CSS files from
Converse, for example if you're developing new features or fixing styling bugs.
The CSS files are generated from `Sass <http://sass-lang.com>`_ files that end in ``.scss`` and
which are distributed throughout the source code.
The CSS that is relevant to a particular plugin
is usually inside the ``./styles`` directory inside the relevant plugin directory.
For example: `src/plugins/controlbox/styles <https://github.com/conversejs/converse.js/tree/master/src/plugins/controlbox/styles>`_.
If you're running ``make watch``, then the CSS will automatically be
regenerated when you've changed any of the ``.scss``.
You can also manually generate the CSS::
make css
Testing your changes
====================
Modifying the HTML templates of Converse
========================================
The recommended way to test your changes is to run the tests that are part of the Converse source code.
By executing ``make test`` you'll run all tests (which live in the ``spec`` folder) which will open a browser window in which tests are processed.
Converse uses `lit-html <https://lit.dev/docs/libraries/standalone-templates/>`_ as HTML
templating library, and the HTML source code is contained in JavaScript ``.js``
files in various ``./template`` directories in the source code.
You can run a single test by changing ``it(`` to ``fit(`` so that only that one test runs. Then you click the "debug" button in the browser when the tests run. After the test has run, the opened chats will still be visible.
Some top-level templates are also in the ``./src/templates`` directory, but
the templates that are relevant to a specific plugin should be inside that plugin's subdirectory.
For example: `src/plugins/chatview/templates <https://github.com/conversejs/converse.js/tree/master/src/plugins/chatview/templates>`_.
Creating dist files
===================
You can modify HTML markup that Converse generates by modifying these files.
Once you've themed Converse, you'll want to create new minified distribution
files of all the JavaScript and CSS.
Use webpack aliases to modify templates without changing the original files
---------------------------------------------------------------------------
Please refer to the :doc:`builds` section for information on how this is done.
Generally what I do when creating a modified version of Converse for a project
or customer, is that I create a new JavaScript package with its own
``package.json`` and I then add ``converse.js`` as a dependency (e.g. via ``npm
install --save converse.js``) to the ``package.json``.
Then I add a Webpack configuration and use `webpack aliases <https://webpack.js.org/configuration/resolve/#resolvealias>`_
to resolve template paths to my own modified files.
For example, in the webpack configuration snippet below, I add two aliases, so
that the ``message-body.js`` and ``message.js`` templates can be replaced with
two of my own custom templates.
.. code-block:: javascript
resolve: {
extensions: ['.js'],
alias: {
'./message-body.js': path.resolve(__dirname, 'path/to/my/custom/message-body.js'),
'./templates/message.js': path.resolve(__dirname, 'path/to/my/custom/chat_message.js'),
}
}

View File

@ -1,6 +1,6 @@
.. raw:: html
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/setup.rst">Edit me on GitHub</a></div>
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/troubleshooting.rst">Edit me on GitHub</a></div>
=============================
Troubleshooting and debugging
@ -114,6 +114,89 @@ what you're using as the HTTP file server.
CORS is enabled by adding an ``Access-Control-Allow-Origin`` header, so you'll
have to configure your file server to add this header.
Users don't stay logged in across page reloads
==============================================
A common complaint in the Converse chat room (`<xmpp:discuss@conference.conversejs.org?join>`_)
is that users are logged out when they reload the page.
The main way in which websites and web apps maintain a user's login session is via
authentication cookies, which are included in every HTTP request sent to the server.
XMPP is however not HTTP, cookies aren't automatically included in traffic to
the XMPP server and XMPP servers don't rely on cookies for authentication.
Instead, an XMPP client is expected to store the user credentials (username and
password, either plaintext or hashed and salted if
`SCRAM <https://en.wikipedia.org/wiki/Salted_Challenge_Response_Authentication_Mechanism>`_
is being used) and to then present those credentials to the XMPP server when authenticating.
This works well for non-web XMPP clients, but Converse has so far avoided
storing user credentials in browser storage, since they can then be accessed by
any scripts running in the browser under the same domain.
So what does Converse do to keep users logged in?
-------------------------------------------------
Use the Web Auth API
********************
Converse supports the `Web Authentication API <https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API>`_
which let's it use the secure credential management of the browser to get the
uesr credentials to automatically log the user in. This however requires that
the user saves his or her username and password in the browser. Often the user
is automatically asked by the browser whether he/she wants to store the
credentials. If that doesn't happen, the user has to do so manually, usually by
clicking the key icon in the address bar. This works well on most modern browsers,
but not on Firefox, which has insufficient support for the Web Authentication API.
What can users do to stay logged in?
------------------------------------
Outsource credential management to something else
*************************************************
The issues mentioned above mostly related to users logging in manually, and not
to integrations where Converse automatically fetches user credentials from the
backend via the :ref:`credentials_url` setting.
Use BOSH instead of websocket
*****************************
`BOSH <https://xmpp.org/extensions/xep-0206.html>`_ can be thought of
XMPP-over-HTTP and because HTTP is stateless, BOSH needs to maintain login
sessions for a certain amount of time (usually 60 seconds) even if there is no
HTTP traffic between the client and server. This means that if you have a BOSH
session running, you can reload the page and you will stay logged in.
Note, Websocket connections are however faster and have less overhead than BOSH.
User a browser with adequate support for the Web Auth API
*********************************************************
Another option is to only use a browser with proper support for the Web Auth
API (which mainly means avoiding Firefox) and then to save your credentials in the browser.
Use Converse Desktop
********************
The `desktop version of Converse <https://github.com/conversejs/converse-desktop>`_
also doesn't have this problem, since the credentials are stored in Electron
and there is no significant risk of other malicious scripts running.
What else can Converse do to keep users logged in?
--------------------------------------------------
This problem could also potentially be fixed by storing the
XMPP credentials securely with web crypto and IndexedDB. This could be done by
generating a private encryption key in non-exportable format, and then using that
to encrypt the credentials before storing them in IndexedDB.
This would protect the credentials from someone who has access to your
computer (or harddrive), but it still won't protect them from malicious scripts
running in the same domain as Converse is being hosted, since they would have the
same level of access as Converse itself (which legitimately needs access to the
credentials).
Common errors
=============

View File

@ -3,6 +3,8 @@
<head>
<title>Converse</title>
<meta charset="utf-8"/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta name="description" content="Converse XMPP/Jabber Chat"/>
<meta name="author" content="JC Brand" />

View File

@ -1,220 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Font Awesome Free 5.13.0 by @fontawesome - https://fontawesome.com
License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
-->
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="icon-address-book" viewBox="0 0 448 512">
<path d="M436 160c6.6 0 12-5.4 12-12v-40c0-6.6-5.4-12-12-12h-20V48c0-26.5-21.5-48-48-48H48C21.5 0 0 21.5 0 48v416c0 26.5 21.5 48 48 48h320c26.5 0 48-21.5 48-48v-48h20c6.6 0 12-5.4 12-12v-40c0-6.6-5.4-12-12-12h-20v-64h20c6.6 0 12-5.4 12-12v-40c0-6.6-5.4-12-12-12h-20v-64h20zm-228-32c35.3 0 64 28.7 64 64s-28.7 64-64 64-64-28.7-64-64 28.7-64 64-64zm112 236.8c0 10.6-10 19.2-22.4 19.2H118.4C106 384 96 375.4 96 364.8v-19.2c0-31.8 30.1-57.6 67.2-57.6h5c12.3 5.1 25.7 8 39.8 8s27.6-2.9 39.8-8h5c37.1 0 67.2 25.8 67.2 57.6v19.2z"></path>
</symbol>
<symbol id="icon-angle-double-down" viewBox="0 0 320 512">
<path d="M143 256.3L7 120.3c-9.4-9.4-9.4-24.6 0-33.9l22.6-22.6c9.4-9.4 24.6-9.4 33.9 0l96.4 96.4 96.4-96.4c9.4-9.4 24.6-9.4 33.9 0L313 86.3c9.4 9.4 9.4 24.6 0 33.9l-136 136c-9.4 9.5-24.6 9.5-34 .1zm34 192l136-136c9.4-9.4 9.4-24.6 0-33.9l-22.6-22.6c-9.4-9.4-24.6-9.4-33.9 0L160 352.1l-96.4-96.4c-9.4-9.4-24.6-9.4-33.9 0L7 278.3c-9.4 9.4-9.4 24.6 0 33.9l136 136c9.4 9.5 24.6 9.5 34 .1z"></path>
</symbol>
<symbol id="icon-angle-double-left" viewBox="0 0 448 512">
<path d="M223.7 239l136-136c9.4-9.4 24.6-9.4 33.9 0l22.6 22.6c9.4 9.4 9.4 24.6 0 33.9L319.9 256l96.4 96.4c9.4 9.4 9.4 24.6 0 33.9L393.7 409c-9.4 9.4-24.6 9.4-33.9 0l-136-136c-9.5-9.4-9.5-24.6-.1-34zm-192 34l136 136c9.4 9.4 24.6 9.4 33.9 0l22.6-22.6c9.4-9.4 9.4-24.6 0-33.9L127.9 256l96.4-96.4c9.4-9.4 9.4-24.6 0-33.9L201.7 103c-9.4-9.4-24.6-9.4-33.9 0l-136 136c-9.5 9.4-9.5 24.6-.1 34z"></path>
</symbol>
<symbol id="icon-angle-double-right" viewBox="0 0 448 512">
<path d="M224.3 273l-136 136c-9.4 9.4-24.6 9.4-33.9 0l-22.6-22.6c-9.4-9.4-9.4-24.6 0-33.9l96.4-96.4-96.4-96.4c-9.4-9.4-9.4-24.6 0-33.9L54.3 103c9.4-9.4 24.6-9.4 33.9 0l136 136c9.5 9.4 9.5 24.6.1 34zm192-34l-136-136c-9.4-9.4-24.6-9.4-33.9 0l-22.6 22.6c-9.4 9.4-9.4 24.6 0 33.9l96.4 96.4-96.4 96.4c-9.4 9.4-9.4 24.6 0 33.9l22.6 22.6c9.4 9.4 24.6 9.4 33.9 0l136-136c9.4-9.2 9.4-24.4 0-33.8z"></path>
</symbol>
<symbol id="icon-angle-double-up" viewBox="0 0 320 512">
<path d="M177 255.7l136 136c9.4 9.4 9.4 24.6 0 33.9l-22.6 22.6c-9.4 9.4-24.6 9.4-33.9 0L160 351.9l-96.4 96.4c-9.4 9.4-24.6 9.4-33.9 0L7 425.7c-9.4-9.4-9.4-24.6 0-33.9l136-136c9.4-9.5 24.6-9.5 34-.1zm-34-192L7 199.7c-9.4 9.4-9.4 24.6 0 33.9l22.6 22.6c9.4 9.4 24.6 9.4 33.9 0l96.4-96.4 96.4 96.4c9.4 9.4 24.6 9.4 33.9 0l22.6-22.6c9.4-9.4 9.4-24.6 0-33.9l-136-136c-9.2-9.4-24.4-9.4-33.8 0z"></path>
</symbol>
<symbol id="icon-angle-down" viewBox="0 0 320 512">
<path d="M143 352.3L7 216.3c-9.4-9.4-9.4-24.6 0-33.9l22.6-22.6c9.4-9.4 24.6-9.4 33.9 0l96.4 96.4 96.4-96.4c9.4-9.4 24.6-9.4 33.9 0l22.6 22.6c9.4 9.4 9.4 24.6 0 33.9l-136 136c-9.2 9.4-24.4 9.4-33.8 0z"></path>
</symbol>
<symbol id="icon-angle-left" viewBox="0 0 256 512">
<path d="M31.7 239l136-136c9.4-9.4 24.6-9.4 33.9 0l22.6 22.6c9.4 9.4 9.4 24.6 0 33.9L127.9 256l96.4 96.4c9.4 9.4 9.4 24.6 0 33.9L201.7 409c-9.4 9.4-24.6 9.4-33.9 0l-136-136c-9.5-9.4-9.5-24.6-.1-34z"></path>
</symbol>
<symbol id="icon-angle-right" viewBox="0 0 256 512">
<path d="M224.3 273l-136 136c-9.4 9.4-24.6 9.4-33.9 0l-22.6-22.6c-9.4-9.4-9.4-24.6 0-33.9l96.4-96.4-96.4-96.4c-9.4-9.4-9.4-24.6 0-33.9L54.3 103c9.4-9.4 24.6-9.4 33.9 0l136 136c9.5 9.4 9.5 24.6.1 34z"></path>
</symbol>
<symbol id="icon-angle-up" viewBox="0 0 320 512">
<path d="M177 159.7l136 136c9.4 9.4 9.4 24.6 0 33.9l-22.6 22.6c-9.4 9.4-24.6 9.4-33.9 0L160 255.9l-96.4 96.4c-9.4 9.4-24.6 9.4-33.9 0L7 329.7c-9.4-9.4-9.4-24.6 0-33.9l136-136c9.4-9.5 24.6-9.5 34-.1z"></path>
</symbol>
<symbol id="icon-arrow-alt-circle-down" viewBox="0 0 512 512">
<path d="M504 256c0 137-111 248-248 248S8 393 8 256 119 8 256 8s248 111 248 248zM212 140v116h-70.9c-10.7 0-16.1 13-8.5 20.5l114.9 114.3c4.7 4.7 12.2 4.7 16.9 0l114.9-114.3c7.6-7.6 2.2-20.5-8.5-20.5H300V140c0-6.6-5.4-12-12-12h-64c-6.6 0-12 5.4-12 12z"></path>
</symbol>
<symbol id="icon-arrow-alt-circle-left" viewBox="0 0 512 512">
<path d="M256 504C119 504 8 393 8 256S119 8 256 8s248 111 248 248-111 248-248 248zm116-292H256v-70.9c0-10.7-13-16.1-20.5-8.5L121.2 247.5c-4.7 4.7-4.7 12.2 0 16.9l114.3 114.9c7.6 7.6 20.5 2.2 20.5-8.5V300h116c6.6 0 12-5.4 12-12v-64c0-6.6-5.4-12-12-12z"></path>
</symbol>
<symbol id="icon-arrow-alt-circle-right" viewBox="0 0 512 512">
<path d="M256 8c137 0 248 111 248 248S393 504 256 504 8 393 8 256 119 8 256 8zM140 300h116v70.9c0 10.7 13 16.1 20.5 8.5l114.3-114.9c4.7-4.7 4.7-12.2 0-16.9l-114.3-115c-7.6-7.6-20.5-2.2-20.5 8.5V212H140c-6.6 0-12 5.4-12 12v64c0 6.6 5.4 12 12 12z"></path>
</symbol>
<symbol id="icon-arrow-alt-circle-up" viewBox="0 0 512 512">
<path d="M8 256C8 119 119 8 256 8s248 111 248 248-111 248-248 248S8 393 8 256zm292 116V256h70.9c10.7 0 16.1-13 8.5-20.5L264.5 121.2c-4.7-4.7-12.2-4.7-16.9 0l-115 114.3c-7.6 7.6-2.2 20.5 8.5 20.5H212v116c0 6.6 5.4 12 12 12h64c6.6 0 12-5.4 12-12z"></path>
</symbol>
<symbol id="icon-arrow-circle-down" viewBox="0 0 512 512">
<path d="M504 256c0 137-111 248-248 248S8 393 8 256 119 8 256 8s248 111 248 248zm-143.6-28.9L288 302.6V120c0-13.3-10.7-24-24-24h-16c-13.3 0-24 10.7-24 24v182.6l-72.4-75.5c-9.3-9.7-24.8-9.9-34.3-.4l-10.9 11c-9.4 9.4-9.4 24.6 0 33.9L239 404.3c9.4 9.4 24.6 9.4 33.9 0l132.7-132.7c9.4-9.4 9.4-24.6 0-33.9l-10.9-11c-9.5-9.5-25-9.3-34.3.4z"></path>
</symbol>
<symbol id="icon-arrow-circle-left" viewBox="0 0 512 512">
<path d="M256 504C119 504 8 393 8 256S119 8 256 8s248 111 248 248-111 248-248 248zm28.9-143.6L209.4 288H392c13.3 0 24-10.7 24-24v-16c0-13.3-10.7-24-24-24H209.4l75.5-72.4c9.7-9.3 9.9-24.8.4-34.3l-11-10.9c-9.4-9.4-24.6-9.4-33.9 0L107.7 239c-9.4 9.4-9.4 24.6 0 33.9l132.7 132.7c9.4 9.4 24.6 9.4 33.9 0l11-10.9c9.5-9.5 9.3-25-.4-34.3z"></path>
</symbol>
<symbol id="icon-arrow-circle-right" viewBox="0 0 512 512">
<path d="M256 8c137 0 248 111 248 248S393 504 256 504 8 393 8 256 119 8 256 8zm-28.9 143.6l75.5 72.4H120c-13.3 0-24 10.7-24 24v16c0 13.3 10.7 24 24 24h182.6l-75.5 72.4c-9.7 9.3-9.9 24.8-.4 34.3l11 10.9c9.4 9.4 24.6 9.4 33.9 0L404.3 273c9.4-9.4 9.4-24.6 0-33.9L271.6 106.3c-9.4-9.4-24.6-9.4-33.9 0l-11 10.9c-9.5 9.6-9.3 25.1.4 34.4z"></path>
</symbol>
<symbol id="icon-arrow-circle-up" viewBox="0 0 512 512">
<path d="M8 256C8 119 119 8 256 8s248 111 248 248-111 248-248 248S8 393 8 256zm143.6 28.9l72.4-75.5V392c0 13.3 10.7 24 24 24h16c13.3 0 24-10.7 24-24V209.4l72.4 75.5c9.3 9.7 24.8 9.9 34.3.4l10.9-11c9.4-9.4 9.4-24.6 0-33.9L273 107.7c-9.4-9.4-24.6-9.4-33.9 0L106.3 240.4c-9.4 9.4-9.4 24.6 0 33.9l10.9 11c9.6 9.5 25.1 9.3 34.4-.4z"></path>
</symbol>
<symbol id="icon-arrow-down" viewBox="0 0 448 512">
<path d="M413.1 222.5l22.2 22.2c9.4 9.4 9.4 24.6 0 33.9L241 473c-9.4 9.4-24.6 9.4-33.9 0L12.7 278.6c-9.4-9.4-9.4-24.6 0-33.9l22.2-22.2c9.5-9.5 25-9.3 34.3.4L184 343.4V56c0-13.3 10.7-24 24-24h32c13.3 0 24 10.7 24 24v287.4l114.8-120.5c9.3-9.8 24.8-10 34.3-.4z"></path>
</symbol>
<symbol id="icon-arrow-left" viewBox="0 0 448 512">
<path d="M257.5 445.1l-22.2 22.2c-9.4 9.4-24.6 9.4-33.9 0L7 273c-9.4-9.4-9.4-24.6 0-33.9L201.4 44.7c9.4-9.4 24.6-9.4 33.9 0l22.2 22.2c9.5 9.5 9.3 25-.4 34.3L136.6 216H424c13.3 0 24 10.7 24 24v32c0 13.3-10.7 24-24 24H136.6l120.5 114.8c9.8 9.3 10 24.8.4 34.3z"></path>
</symbol>
<symbol id="icon-arrow-right" viewBox="0 0 448 512">
<path d="M190.5 66.9l22.2-22.2c9.4-9.4 24.6-9.4 33.9 0L441 239c9.4 9.4 9.4 24.6 0 33.9L246.6 467.3c-9.4 9.4-24.6 9.4-33.9 0l-22.2-22.2c-9.5-9.5-9.3-25 .4-34.3L311.4 296H24c-13.3 0-24-10.7-24-24v-32c0-13.3 10.7-24 24-24h287.4L190.9 101.2c-9.8-9.3-10-24.8-.4-34.3z"></path>
</symbol>
<symbol id="icon-arrow-up" viewBox="0 0 448 512">
<path d="M34.9 289.5l-22.2-22.2c-9.4-9.4-9.4-24.6 0-33.9L207 39c9.4-9.4 24.6-9.4 33.9 0l194.3 194.3c9.4 9.4 9.4 24.6 0 33.9L413 289.4c-9.5 9.5-25 9.3-34.3-.4L264 168.6V456c0 13.3-10.7 24-24 24h-32c-13.3 0-24-10.7-24-24V168.6L69.2 289.1c-9.3 9.8-24.8 10-34.3.4z"></path>
</symbol>
<symbol id="icon-arrows-alt" viewBox="0 0 512 512">
<path d="M352.201 425.775l-79.196 79.196c-9.373 9.373-24.568 9.373-33.941 0l-79.196-79.196c-15.119-15.119-4.411-40.971 16.971-40.97h51.162L228 284H127.196v51.162c0 21.382-25.851 32.09-40.971 16.971L7.029 272.937c-9.373-9.373-9.373-24.569 0-33.941L86.225 159.8c15.119-15.119 40.971-4.411 40.971 16.971V228H228V127.196h-51.23c-21.382 0-32.09-25.851-16.971-40.971l79.196-79.196c9.373-9.373 24.568-9.373 33.941 0l79.196 79.196c15.119 15.119 4.411 40.971-16.971 40.971h-51.162V228h100.804v-51.162c0-21.382 25.851-32.09 40.97-16.971l79.196 79.196c9.373 9.373 9.373 24.569 0 33.941L425.773 352.2c-15.119 15.119-40.971 4.411-40.97-16.971V284H284v100.804h51.23c21.382 0 32.09 25.851 16.971 40.971z"></path>
</symbol>
<symbol id="icon-arrows-alt-h" viewBox="0 0 512 512">
<path d="M377.941 169.941V216H134.059v-46.059c0-21.382-25.851-32.09-40.971-16.971L7.029 239.029c-9.373 9.373-9.373 24.568 0 33.941l86.059 86.059c15.119 15.119 40.971 4.411 40.971-16.971V296h243.882v46.059c0 21.382 25.851 32.09 40.971 16.971l86.059-86.059c9.373-9.373 9.373-24.568 0-33.941l-86.059-86.059c-15.119-15.12-40.971-4.412-40.971 16.97z"></path>
</symbol>
<symbol id="icon-arrows-alt-v" viewBox="0 0 256 512">
<path d="M214.059 377.941H168V134.059h46.059c21.382 0 32.09-25.851 16.971-40.971L144.971 7.029c-9.373-9.373-24.568-9.373-33.941 0L24.971 93.088c-15.119 15.119-4.411 40.971 16.971 40.971H88v243.882H41.941c-21.382 0-32.09 25.851-16.971 40.971l86.059 86.059c9.373 9.373 24.568 9.373 33.941 0l86.059-86.059c15.12-15.119 4.412-40.971-16.97-40.971z"></path>
</symbol>
<symbol id="icon-bars" viewBox="0 0 448 512">
<path d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"></path>
</symbol>
<symbol id="icon-bookmark" viewBox="0 0 384 512">
<path d="M0 512V48C0 21.49 21.49 0 48 0h288c26.51 0 48 21.49 48 48v464L192 400 0 512z"></path>
</symbol>
<symbol id="icon-caret-down" viewBox="0 0 320 512">
<path d="M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z"></path>
</symbol>
<symbol id="icon-caret-right" viewBox="0 0 192 512">
<path d="M0 384.662V127.338c0-17.818 21.543-26.741 34.142-14.142l128.662 128.662c7.81 7.81 7.81 20.474 0 28.284L34.142 398.804C21.543 411.404 0 402.48 0 384.662z"></path>
</symbol>
<symbol id="icon-check" viewBox="0 0 512 512">
<path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"></path>
</symbol>
<symbol id="icon-circle" viewBox="0 0 512 512">
<path d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8z"></path>
</symbol>
<symbol id="icon-cog" viewBox="0 0 512 512">
<path d="M487.4 315.7l-42.6-24.6c4.3-23.2 4.3-47 0-70.2l42.6-24.6c4.9-2.8 7.1-8.6 5.5-14-11.1-35.6-30-67.8-54.7-94.6-3.8-4.1-10-5.1-14.8-2.3L380.8 110c-17.9-15.4-38.5-27.3-60.8-35.1V25.8c0-5.6-3.9-10.5-9.4-11.7-36.7-8.2-74.3-7.8-109.2 0-5.5 1.2-9.4 6.1-9.4 11.7V75c-22.2 7.9-42.8 19.8-60.8 35.1L88.7 85.5c-4.9-2.8-11-1.9-14.8 2.3-24.7 26.7-43.6 58.9-54.7 94.6-1.7 5.4.6 11.2 5.5 14L67.3 221c-4.3 23.2-4.3 47 0 70.2l-42.6 24.6c-4.9 2.8-7.1 8.6-5.5 14 11.1 35.6 30 67.8 54.7 94.6 3.8 4.1 10 5.1 14.8 2.3l42.6-24.6c17.9 15.4 38.5 27.3 60.8 35.1v49.2c0 5.6 3.9 10.5 9.4 11.7 36.7 8.2 74.3 7.8 109.2 0 5.5-1.2 9.4-6.1 9.4-11.7v-49.2c22.2-7.9 42.8-19.8 60.8-35.1l42.6 24.6c4.9 2.8 11 1.9 14.8-2.3 24.7-26.7 43.6-58.9 54.7-94.6 1.5-5.5-.7-11.3-5.6-14.1zM256 336c-44.1 0-80-35.9-80-80s35.9-80 80-80 80 35.9 80 80-35.9 80-80 80z"></path>
</symbol>
<symbol id="icon-database" viewBox="0 0 448 512">
<path d="M448 73.143v45.714C448 159.143 347.667 192 224 192S0 159.143 0 118.857V73.143C0 32.857 100.333 0 224 0s224 32.857 224 73.143zM448 176v102.857C448 319.143 347.667 352 224 352S0 319.143 0 278.857V176c48.125 33.143 136.208 48.572 224 48.572S399.874 209.143 448 176zm0 160v102.857C448 479.143 347.667 512 224 512S0 479.143 0 438.857V336c48.125 33.143 136.208 48.572 224 48.572S399.874 369.143 448 336z"></path>
</symbol>
<symbol id="icon-edit" viewBox="0 0 576 512">
<path d="M402.6 83.2l90.2 90.2c3.8 3.8 3.8 10 0 13.8L274.4 405.6l-92.8 10.3c-12.4 1.4-22.9-9.1-21.5-21.5l10.3-92.8L388.8 83.2c3.8-3.8 10-3.8 13.8 0zm162-22.9l-48.8-48.8c-15.2-15.2-39.9-15.2-55.2 0l-35.4 35.4c-3.8 3.8-3.8 10 0 13.8l90.2 90.2c3.8 3.8 10 3.8 13.8 0l35.4-35.4c15.2-15.3 15.2-40 0-55.2zM384 346.2V448H64V128h229.8c3.2 0 6.2-1.3 8.5-3.5l40-40c7.6-7.6 2.2-20.5-8.5-20.5H48C21.5 64 0 85.5 0 112v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V306.2c0-10.7-12.9-16-20.5-8.5l-40 40c-2.2 2.3-3.5 5.3-3.5 8.5z"></path>
</symbol>
<symbol id="icon-eye" viewBox="0 0 576 512">
<path d="M572.52 241.4C518.29 135.59 410.93 64 288 64S57.68 135.64 3.48 241.41a32.35 32.35 0 0 0 0 29.19C57.71 376.41 165.07 448 288 448s230.32-71.64 284.52-177.41a32.35 32.35 0 0 0 0-29.19zM288 400a144 144 0 1 1 144-144 143.93 143.93 0 0 1-144 144zm0-240a95.31 95.31 0 0 0-25.31 3.79 47.85 47.85 0 0 1-66.9 66.9A95.78 95.78 0 1 0 288 160z"></path>
</symbol>
<symbol id="icon-eye-slash" viewBox="0 0 640 512">
<path d="M320 400c-75.85 0-137.25-58.71-142.9-133.11L72.2 185.82c-13.79 17.3-26.48 35.59-36.72 55.59a32.35 32.35 0 0 0 0 29.19C89.71 376.41 197.07 448 320 448c26.91 0 52.87-4 77.89-10.46L346 397.39a144.13 144.13 0 0 1-26 2.61zm313.82 58.1l-110.55-85.44a331.25 331.25 0 0 0 81.25-102.07 32.35 32.35 0 0 0 0-29.19C550.29 135.59 442.93 64 320 64a308.15 308.15 0 0 0-147.32 37.7L45.46 3.37A16 16 0 0 0 23 6.18L3.37 31.45A16 16 0 0 0 6.18 53.9l588.36 454.73a16 16 0 0 0 22.46-2.81l19.64-25.27a16 16 0 0 0-2.82-22.45zm-183.72-142l-39.3-30.38A94.75 94.75 0 0 0 416 256a94.76 94.76 0 0 0-121.31-92.21A47.65 47.65 0 0 1 304 192a46.64 46.64 0 0 1-1.54 10l-73.61-56.89A142.31 142.31 0 0 1 320 112a143.92 143.92 0 0 1 144 144c0 21.63-5.29 41.79-13.9 60.11z"></path>
</symbol>
<symbol id="icon-gavel" viewBox="0 0 512 512">
<path d="M504.971 199.362l-22.627-22.627c-9.373-9.373-24.569-9.373-33.941 0l-5.657 5.657L329.608 69.255l5.657-5.657c9.373-9.373 9.373-24.569 0-33.941L312.638 7.029c-9.373-9.373-24.569-9.373-33.941 0L154.246 131.48c-9.373 9.373-9.373 24.569 0 33.941l22.627 22.627c9.373 9.373 24.569 9.373 33.941 0l5.657-5.657 39.598 39.598-81.04 81.04-5.657-5.657c-12.497-12.497-32.758-12.497-45.255 0L9.373 412.118c-12.497 12.497-12.497 32.758 0 45.255l45.255 45.255c12.497 12.497 32.758 12.497 45.255 0l114.745-114.745c12.497-12.497 12.497-32.758 0-45.255l-5.657-5.657 81.04-81.04 39.598 39.598-5.657 5.657c-9.373 9.373-9.373 24.569 0 33.941l22.627 22.627c9.373 9.373 24.569 9.373 33.941 0l124.451-124.451c9.372-9.372 9.372-24.568 0-33.941z"></path>
</symbol>
<symbol id="icon-globe" viewBox="0 0 496 512">
<path d="M336.5 160C322 70.7 287.8 8 248 8s-74 62.7-88.5 152h177zM152 256c0 22.2 1.2 43.5 3.3 64h185.3c2.1-20.5 3.3-41.8 3.3-64s-1.2-43.5-3.3-64H155.3c-2.1 20.5-3.3 41.8-3.3 64zm324.7-96c-28.6-67.9-86.5-120.4-158-141.6 24.4 33.8 41.2 84.7 50 141.6h108zM177.2 18.4C105.8 39.6 47.8 92.1 19.3 160h108c8.7-56.9 25.5-107.8 49.9-141.6zM487.4 192H372.7c2.1 21 3.3 42.5 3.3 64s-1.2 43-3.3 64h114.6c5.5-20.5 8.6-41.8 8.6-64s-3.1-43.5-8.5-64zM120 256c0-21.5 1.2-43 3.3-64H8.6C3.2 212.5 0 233.8 0 256s3.2 43.5 8.6 64h114.6c-2-21-3.2-42.5-3.2-64zm39.5 96c14.5 89.3 48.7 152 88.5 152s74-62.7 88.5-152h-177zm159.3 141.6c71.4-21.2 129.4-73.7 158-141.6h-108c-8.8 56.9-25.6 107.8-50 141.6zM19.3 352c28.6 67.9 86.5 120.4 158 141.6-24.4-33.8-41.2-84.7-50-141.6h-108z"></path>
</symbol>
<symbol id="icon-id-card" viewBox="0 0 576 512">
<path d="M528 32H48C21.5 32 0 53.5 0 80v16h576V80c0-26.5-21.5-48-48-48zM0 432c0 26.5 21.5 48 48 48h480c26.5 0 48-21.5 48-48V128H0v304zm352-232c0-4.4 3.6-8 8-8h144c4.4 0 8 3.6 8 8v16c0 4.4-3.6 8-8 8H360c-4.4 0-8-3.6-8-8v-16zm0 64c0-4.4 3.6-8 8-8h144c4.4 0 8 3.6 8 8v16c0 4.4-3.6 8-8 8H360c-4.4 0-8-3.6-8-8v-16zm0 64c0-4.4 3.6-8 8-8h144c4.4 0 8 3.6 8 8v16c0 4.4-3.6 8-8 8H360c-4.4 0-8-3.6-8-8v-16zM176 192c35.3 0 64 28.7 64 64s-28.7 64-64 64-64-28.7-64-64 28.7-64 64-64zM67.1 396.2C75.5 370.5 99.6 352 128 352h8.2c12.3 5.1 25.7 8 39.8 8s27.6-2.9 39.8-8h8.2c28.4 0 52.5 18.5 60.9 44.2 3.2 9.9-5.2 19.8-15.6 19.8H82.7c-10.4 0-18.8-10-15.6-19.8z"></path>
</symbol>
<symbol id="icon-id-card-alt" viewBox="0 0 576 512">
<path d="M528 64H384v96H192V64H48C21.5 64 0 85.5 0 112v352c0 26.5 21.5 48 48 48h480c26.5 0 48-21.5 48-48V112c0-26.5-21.5-48-48-48zM288 224c35.3 0 64 28.7 64 64s-28.7 64-64 64-64-28.7-64-64 28.7-64 64-64zm93.3 224H194.7c-10.4 0-18.8-10-15.6-19.8 8.3-25.6 32.4-44.2 60.9-44.2h8.2c12.3 5.1 25.7 8 39.8 8s27.6-2.9 39.8-8h8.2c28.4 0 52.5 18.5 60.9 44.2 3.2 9.8-5.2 19.8-15.6 19.8zM352 32c0-17.7-14.3-32-32-32h-64c-17.7 0-32 14.3-32 32v96h128V32z"></path>
</symbol>
<symbol id="icon-info" viewBox="0 0 192 512">
<path d="M20 424.229h20V279.771H20c-11.046 0-20-8.954-20-20V212c0-11.046 8.954-20 20-20h112c11.046 0 20 8.954 20 20v212.229h20c11.046 0 20 8.954 20 20V492c0 11.046-8.954 20-20 20H20c-11.046 0-20-8.954-20-20v-47.771c0-11.046 8.954-20 20-20zM96 0C56.235 0 24 32.235 24 72s32.235 72 72 72 72-32.235 72-72S135.764 0 96 0z"></path>
</symbol>
<symbol id="icon-info-circle" viewBox="0 0 512 512">
<path d="M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 110c23.196 0 42 18.804 42 42s-18.804 42-42 42-42-18.804-42-42 18.804-42 42-42zm56 254c0 6.627-5.373 12-12 12h-88c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h12v-64h-12c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h64c6.627 0 12 5.373 12 12v100h12c6.627 0 12 5.373 12 12v24z"></path>
</symbol>
<symbol id="icon-list-ul" viewBox="0 0 512 512">
<path d="M48 48a48 48 0 1 0 48 48 48 48 0 0 0-48-48zm0 160a48 48 0 1 0 48 48 48 48 0 0 0-48-48zm0 160a48 48 0 1 0 48 48 48 48 0 0 0-48-48zm448 16H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16z"></path>
</symbol>
<symbol id="icon-lock" viewBox="0 0 448 512">
<path d="M400 224h-24v-72C376 68.2 307.8 0 224 0S72 68.2 72 152v72H48c-26.5 0-48 21.5-48 48v192c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V272c0-26.5-21.5-48-48-48zm-104 0H152v-72c0-39.7 32.3-72 72-72s72 32.3 72 72v72z"></path>
</symbol>
<symbol id="icon-lock-open" viewBox="0 0 576 512">
<path d="M423.5 0C339.5.3 272 69.5 272 153.5V224H48c-26.5 0-48 21.5-48 48v192c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V272c0-26.5-21.5-48-48-48h-48v-71.1c0-39.6 31.7-72.5 71.3-72.9 40-.4 72.7 32.1 72.7 72v80c0 13.3 10.7 24 24 24h32c13.3 0 24-10.7 24-24v-80C576 68 507.5-.3 423.5 0z"></path>
</symbol>
<symbol id="icon-minus" viewBox="0 0 448 512">
<path d="M416 208H32c-17.67 0-32 14.33-32 32v32c0 17.67 14.33 32 32 32h384c17.67 0 32-14.33 32-32v-32c0-17.67-14.33-32-32-32z"></path>
</symbol>
<symbol id="icon-minus-circle" viewBox="0 0 512 512">
<path d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zM124 296c-6.6 0-12-5.4-12-12v-56c0-6.6 5.4-12 12-12h264c6.6 0 12 5.4 12 12v56c0 6.6-5.4 12-12 12H124z"></path>
</symbol>
<symbol id="icon-minus-square" viewBox="0 0 448 512">
<path d="M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zM92 296c-6.6 0-12-5.4-12-12v-56c0-6.6 5.4-12 12-12h264c6.6 0 12 5.4 12 12v56c0 6.6-5.4 12-12 12H92z"></path>
</symbol>
<symbol id="icon-paper-plane" viewBox="0 0 512 512">
<path d="M476 3.2L12.5 270.6c-18.1 10.4-15.8 35.6 2.2 43.2L121 358.4l287.3-253.2c5.5-4.9 13.3 2.6 8.6 8.3L176 407v80.5c0 23.6 28.5 32.9 42.5 15.8L282 426l124.6 52.2c14.2 6 30.4-2.9 33-18.2l72-432C515 7.8 493.3-6.8 476 3.2z"></path>
</symbol>
<symbol id="icon-paperclip" viewBox="0 0 448 512">
<path d="M43.246 466.142c-58.43-60.289-57.341-157.511 1.386-217.581L254.392 34c44.316-45.332 116.351-45.336 160.671 0 43.89 44.894 43.943 117.329 0 162.276L232.214 383.128c-29.855 30.537-78.633 30.111-107.982-.998-28.275-29.97-27.368-77.473 1.452-106.953l143.743-146.835c6.182-6.314 16.312-6.422 22.626-.241l22.861 22.379c6.315 6.182 6.422 16.312.241 22.626L171.427 319.927c-4.932 5.045-5.236 13.428-.648 18.292 4.372 4.634 11.245 4.711 15.688.165l182.849-186.851c19.613-20.062 19.613-52.725-.011-72.798-19.189-19.627-49.957-19.637-69.154 0L90.39 293.295c-34.763 35.56-35.299 93.12-1.191 128.313 34.01 35.093 88.985 35.137 123.058.286l172.06-175.999c6.177-6.319 16.307-6.433 22.626-.256l22.877 22.364c6.319 6.177 6.434 16.307.256 22.626l-172.06 175.998c-59.576 60.938-155.943 60.216-214.77-.485z"></path>
</symbol>
<symbol id="icon-pencil-alt" viewBox="0 0 512 512">
<path d="M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z"></path>
</symbol>
<symbol id="icon-phone" viewBox="0 0 512 512">
<path d="M493.4 24.6l-104-24c-11.3-2.6-22.9 3.3-27.5 13.9l-48 112c-4.2 9.8-1.4 21.3 6.9 28l60.6 49.6c-36 76.7-98.9 140.5-177.2 177.2l-49.6-60.6c-6.8-8.3-18.2-11.1-28-6.9l-112 48C3.9 366.5-2 378.1.6 389.4l24 104C27.1 504.2 36.7 512 48 512c256.1 0 464-207.5 464-464 0-11.2-7.7-20.9-18.6-23.4z"></path>
</symbol>
<symbol id="icon-plus" viewBox="0 0 448 512">
<path d="M416 208H272V64c0-17.67-14.33-32-32-32h-32c-17.67 0-32 14.33-32 32v144H32c-17.67 0-32 14.33-32 32v32c0 17.67 14.33 32 32 32h144v144c0 17.67 14.33 32 32 32h32c17.67 0 32-14.33 32-32V304h144c17.67 0 32-14.33 32-32v-32c0-17.67-14.33-32-32-32z"></path>
</symbol>
<symbol id="icon-plus-circle" viewBox="0 0 512 512">
<path d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm144 276c0 6.6-5.4 12-12 12h-92v92c0 6.6-5.4 12-12 12h-56c-6.6 0-12-5.4-12-12v-92h-92c-6.6 0-12-5.4-12-12v-56c0-6.6 5.4-12 12-12h92v-92c0-6.6 5.4-12 12-12h56c6.6 0 12 5.4 12 12v92h92c6.6 0 12 5.4 12 12v56z"></path>
</symbol>
<symbol id="icon-plus-square" viewBox="0 0 448 512">
<path d="M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zm-32 252c0 6.6-5.4 12-12 12h-92v92c0 6.6-5.4 12-12 12h-56c-6.6 0-12-5.4-12-12v-92H92c-6.6 0-12-5.4-12-12v-56c0-6.6 5.4-12 12-12h92v-92c0-6.6 5.4-12 12-12h56c6.6 0 12 5.4 12 12v92h92c6.6 0 12 5.4 12 12v56z"></path>
</symbol>
<symbol id="icon-save" viewBox="0 0 448 512">
<path d="M433.941 129.941l-83.882-83.882A48 48 0 0 0 316.118 32H48C21.49 32 0 53.49 0 80v352c0 26.51 21.49 48 48 48h352c26.51 0 48-21.49 48-48V163.882a48 48 0 0 0-14.059-33.941zM224 416c-35.346 0-64-28.654-64-64 0-35.346 28.654-64 64-64s64 28.654 64 64c0 35.346-28.654 64-64 64zm96-304.52V212c0 6.627-5.373 12-12 12H76c-6.627 0-12-5.373-12-12V108c0-6.627 5.373-12 12-12h228.52c3.183 0 6.235 1.264 8.485 3.515l3.48 3.48A11.996 11.996 0 0 1 320 111.48z"></path>
</symbol>
<symbol id="icon-sign-out-alt" viewBox="0 0 512 512">
<path d="M497 273L329 441c-15 15-41 4.5-41-17v-96H152c-13.3 0-24-10.7-24-24v-96c0-13.3 10.7-24 24-24h136V88c0-21.4 25.9-32 41-17l168 168c9.3 9.4 9.3 24.6 0 34zM192 436v-40c0-6.6-5.4-12-12-12H96c-17.7 0-32-14.3-32-32V160c0-17.7 14.3-32 32-32h84c6.6 0 12-5.4 12-12V76c0-6.6-5.4-12-12-12H96c-53 0-96 43-96 96v192c0 53 43 96 96 96h84c6.6 0 12-5.4 12-12z"></path>
</symbol>
<symbol id="icon-smile" viewBox="0 0 496 512">
<path d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm80 168c17.7 0 32 14.3 32 32s-14.3 32-32 32-32-14.3-32-32 14.3-32 32-32zm-160 0c17.7 0 32 14.3 32 32s-14.3 32-32 32-32-14.3-32-32 14.3-32 32-32zm194.8 170.2C334.3 380.4 292.5 400 248 400s-86.3-19.6-114.8-53.8c-13.6-16.3 11-36.7 24.6-20.5 22.4 26.9 55.2 42.2 90.2 42.2s67.8-15.4 90.2-42.2c13.4-16.2 38.1 4.2 24.6 20.5z"></path>
</symbol>
<symbol id="icon-snowflake" viewBox="0 0 448 512">
<path d="M440.3 345.2l-33.8-19.5 26-7c8.2-2.2 13.1-10.7 10.9-18.9l-4-14.9c-2.2-8.2-10.7-13.1-18.9-10.9l-70.8 19-63.9-37 63.8-36.9 70.8 19c8.2 2.2 16.7-2.7 18.9-10.9l4-14.9c2.2-8.2-2.7-16.7-10.9-18.9l-26-7 33.8-19.5c7.4-4.3 9.9-13.7 5.7-21.1L430.4 119c-4.3-7.4-13.7-9.9-21.1-5.7l-33.8 19.5 7-26c2.2-8.2-2.7-16.7-10.9-18.9l-14.9-4c-8.2-2.2-16.7 2.7-18.9 10.9l-19 70.8-62.8 36.2v-77.5l53.7-53.7c6.2-6.2 6.2-16.4 0-22.6l-11.3-11.3c-6.2-6.2-16.4-6.2-22.6 0L256 56.4V16c0-8.8-7.2-16-16-16h-32c-8.8 0-16 7.2-16 16v40.4l-19.7-19.7c-6.2-6.2-16.4-6.2-22.6 0L138.3 48c-6.3 6.2-6.3 16.4 0 22.6l53.7 53.7v77.5l-62.8-36.2-19-70.8c-2.2-8.2-10.7-13.1-18.9-10.9l-14.9 4c-8.2 2.2-13.1 10.7-10.9 18.9l7 26-33.8-19.5c-7.4-4.3-16.8-1.7-21.1 5.7L2.1 145.7c-4.3 7.4-1.7 16.8 5.7 21.1l33.8 19.5-26 7c-8.3 2.2-13.2 10.7-11 19l4 14.9c2.2 8.2 10.7 13.1 18.9 10.9l70.8-19 63.8 36.9-63.8 36.9-70.8-19c-8.2-2.2-16.7 2.7-18.9 10.9l-4 14.9c-2.2 8.2 2.7 16.7 10.9 18.9l26 7-33.8 19.6c-7.4 4.3-9.9 13.7-5.7 21.1l15.5 26.8c4.3 7.4 13.7 9.9 21.1 5.7l33.8-19.5-7 26c-2.2 8.2 2.7 16.7 10.9 18.9l14.9 4c8.2 2.2 16.7-2.7 18.9-10.9l19-70.8 62.8-36.2v77.5l-53.7 53.7c-6.3 6.2-6.3 16.4 0 22.6l11.3 11.3c6.2 6.2 16.4 6.2 22.6 0l19.7-19.7V496c0 8.8 7.2 16 16 16h32c8.8 0 16-7.2 16-16v-40.4l19.7 19.7c6.2 6.2 16.4 6.2 22.6 0l11.3-11.3c6.2-6.2 6.2-16.4 0-22.6L256 387.7v-77.5l62.8 36.2 19 70.8c2.2 8.2 10.7 13.1 18.9 10.9l14.9-4c8.2-2.2 13.1-10.7 10.9-18.9l-7-26 33.8 19.5c7.4 4.3 16.8 1.7 21.1-5.7l15.5-26.8c4.3-7.3 1.8-16.8-5.6-21z"></path>
</symbol>
<symbol id="icon-spinner" viewBox="0 0 512 512">
<path d="M304 48c0 26.51-21.49 48-48 48s-48-21.49-48-48 21.49-48 48-48 48 21.49 48 48zm-48 368c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48zm208-208c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48zM96 256c0-26.51-21.49-48-48-48S0 229.49 0 256s21.49 48 48 48 48-21.49 48-48zm12.922 99.078c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48c0-26.509-21.491-48-48-48zm294.156 0c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48c0-26.509-21.49-48-48-48zM108.922 60.922c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.491-48-48-48z"></path>
</symbol>
<symbol id="icon-sync" viewBox="0 0 512 512">
<path d="M440.65 12.57l4 82.77A247.16 247.16 0 0 0 255.83 8C134.73 8 33.91 94.92 12.29 209.82A12 12 0 0 0 24.09 224h49.05a12 12 0 0 0 11.67-9.26 175.91 175.91 0 0 1 317-56.94l-101.46-4.86a12 12 0 0 0-12.57 12v47.41a12 12 0 0 0 12 12H500a12 12 0 0 0 12-12V12a12 12 0 0 0-12-12h-47.37a12 12 0 0 0-11.98 12.57zM255.83 432a175.61 175.61 0 0 1-146-77.8l101.8 4.87a12 12 0 0 0 12.57-12v-47.4a12 12 0 0 0-12-12H12a12 12 0 0 0-12 12V500a12 12 0 0 0 12 12h47.35a12 12 0 0 0 12-12.6l-4.15-82.57A247.17 247.17 0 0 0 255.83 504c121.11 0 221.93-86.92 243.55-201.82a12 12 0 0 0-11.8-14.18h-49.05a12 12 0 0 0-11.67 9.26A175.86 175.86 0 0 1 255.83 432z"></path>
</symbol>
<symbol id="icon-times" viewBox="0 0 352 512">
<path d="M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z"></path>
</symbol>
<symbol id="icon-times-circle" viewBox="0 0 512 512">
<path d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm121.6 313.1c4.7 4.7 4.7 12.3 0 17L338 377.6c-4.7 4.7-12.3 4.7-17 0L256 312l-65.1 65.6c-4.7 4.7-12.3 4.7-17 0L134.4 338c-4.7-4.7-4.7-12.3 0-17l65.6-65-65.6-65.1c-4.7-4.7-4.7-12.3 0-17l39.6-39.6c4.7-4.7 12.3-4.7 17 0l65 65.7 65.1-65.6c4.7-4.7 12.3-4.7 17 0l39.6 39.6c4.7 4.7 4.7 12.3 0 17L312 256l65.6 65.1z"></path>
</symbol>
<symbol id="icon-trash" viewBox="0 0 448 512">
<path d="M432 32H312l-9.4-18.7A24 24 0 0 0 281.1 0H166.8a23.72 23.72 0 0 0-21.4 13.3L136 32H16A16 16 0 0 0 0 48v32a16 16 0 0 0 16 16h416a16 16 0 0 0 16-16V48a16 16 0 0 0-16-16zM53.2 467a48 48 0 0 0 47.9 45h245.8a48 48 0 0 0 47.9-45L416 128H32z"></path>
</symbol>
<symbol id="icon-trash-alt" viewBox="0 0 448 512">
<path d="M32 464a48 48 0 0 0 48 48h288a48 48 0 0 0 48-48V128H32zm272-256a16 16 0 0 1 32 0v224a16 16 0 0 1-32 0zm-96 0a16 16 0 0 1 32 0v224a16 16 0 0 1-32 0zm-96 0a16 16 0 0 1 32 0v224a16 16 0 0 1-32 0zM432 32H312l-9.4-18.7A24 24 0 0 0 281.1 0H166.8a23.72 23.72 0 0 0-21.4 13.3L136 32H16A16 16 0 0 0 0 48v32a16 16 0 0 0 16 16h416a16 16 0 0 0 16-16V48a16 16 0 0 0-16-16z"></path>
</symbol>
<symbol id="icon-unlock" viewBox="0 0 448 512">
<path d="M400 256H152V152.9c0-39.6 31.7-72.5 71.3-72.9 40-.4 72.7 32.1 72.7 72v16c0 13.3 10.7 24 24 24h32c13.3 0 24-10.7 24-24v-16C376 68 307.5-.3 223.5 0 139.5.3 72 69.5 72 153.5V256H48c-26.5 0-48 21.5-48 48v160c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V304c0-26.5-21.5-48-48-48z"></path>
</symbol>
<symbol id="icon-user" viewBox="0 0 448 512">
<path d="M224 256c70.7 0 128-57.3 128-128S294.7 0 224 0 96 57.3 96 128s57.3 128 128 128zm89.6 32h-16.7c-22.2 10.2-46.9 16-72.9 16s-50.6-5.8-72.9-16h-16.7C60.2 288 0 348.2 0 422.4V464c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48v-41.6c0-74.2-60.2-134.4-134.4-134.4z"></path>
</symbol>
<symbol id="icon-user-cog" viewBox="0 0 640 512">
<path d="M610.5 373.3c2.6-14.1 2.6-28.5 0-42.6l25.8-14.9c3-1.7 4.3-5.2 3.3-8.5-6.7-21.6-18.2-41.2-33.2-57.4-2.3-2.5-6-3.1-9-1.4l-25.8 14.9c-10.9-9.3-23.4-16.5-36.9-21.3v-29.8c0-3.4-2.4-6.4-5.7-7.1-22.3-5-45-4.8-66.2 0-3.3.7-5.7 3.7-5.7 7.1v29.8c-13.5 4.8-26 12-36.9 21.3l-25.8-14.9c-2.9-1.7-6.7-1.1-9 1.4-15 16.2-26.5 35.8-33.2 57.4-1 3.3.4 6.8 3.3 8.5l25.8 14.9c-2.6 14.1-2.6 28.5 0 42.6l-25.8 14.9c-3 1.7-4.3 5.2-3.3 8.5 6.7 21.6 18.2 41.1 33.2 57.4 2.3 2.5 6 3.1 9 1.4l25.8-14.9c10.9 9.3 23.4 16.5 36.9 21.3v29.8c0 3.4 2.4 6.4 5.7 7.1 22.3 5 45 4.8 66.2 0 3.3-.7 5.7-3.7 5.7-7.1v-29.8c13.5-4.8 26-12 36.9-21.3l25.8 14.9c2.9 1.7 6.7 1.1 9-1.4 15-16.2 26.5-35.8 33.2-57.4 1-3.3-.4-6.8-3.3-8.5l-25.8-14.9zM496 400.5c-26.8 0-48.5-21.8-48.5-48.5s21.8-48.5 48.5-48.5 48.5 21.8 48.5 48.5-21.7 48.5-48.5 48.5zM224 256c70.7 0 128-57.3 128-128S294.7 0 224 0 96 57.3 96 128s57.3 128 128 128zm201.2 226.5c-2.3-1.2-4.6-2.6-6.8-3.9l-7.9 4.6c-6 3.4-12.8 5.3-19.6 5.3-10.9 0-21.4-4.6-28.9-12.6-18.3-19.8-32.3-43.9-40.2-69.6-5.5-17.7 1.9-36.4 17.9-45.7l7.9-4.6c-.1-2.6-.1-5.2 0-7.8l-7.9-4.6c-16-9.2-23.4-28-17.9-45.7.9-2.9 2.2-5.8 3.2-8.7-3.8-.3-7.5-1.2-11.4-1.2h-16.7c-22.2 10.2-46.9 16-72.9 16s-50.6-5.8-72.9-16h-16.7C60.2 288 0 348.2 0 422.4V464c0 26.5 21.5 48 48 48h352c10.1 0 19.5-3.2 27.2-8.5-1.2-3.8-2-7.7-2-11.8v-9.2z"></path>
</symbol>
<symbol id="icon-user-plus" viewBox="0 0 640 512">
<path d="M624 208h-64v-64c0-8.8-7.2-16-16-16h-32c-8.8 0-16 7.2-16 16v64h-64c-8.8 0-16 7.2-16 16v32c0 8.8 7.2 16 16 16h64v64c0 8.8 7.2 16 16 16h32c8.8 0 16-7.2 16-16v-64h64c8.8 0 16-7.2 16-16v-32c0-8.8-7.2-16-16-16zm-400 48c70.7 0 128-57.3 128-128S294.7 0 224 0 96 57.3 96 128s57.3 128 128 128zm89.6 32h-16.7c-22.2 10.2-46.9 16-72.9 16s-50.6-5.8-72.9-16h-16.7C60.2 288 0 348.2 0 422.4V464c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48v-41.6c0-74.2-60.2-134.4-134.4-134.4z"></path>
</symbol>
<symbol id="icon-user-secret" viewBox="0 0 448 512">
<path d="M383.9 308.3l23.9-62.6c4-10.5-3.7-21.7-15-21.7h-58.5c11-18.9 17.8-40.6 17.8-64v-.3c39.2-7.8 64-19.1 64-31.7 0-13.3-27.3-25.1-70.1-33-9.2-32.8-27-65.8-40.6-82.8-9.5-11.9-25.9-15.6-39.5-8.8l-27.6 13.8c-9 4.5-19.6 4.5-28.6 0L182.1 3.4c-13.6-6.8-30-3.1-39.5 8.8-13.5 17-31.4 50-40.6 82.8-42.7 7.9-70 19.7-70 33 0 12.6 24.8 23.9 64 31.7v.3c0 23.4 6.8 45.1 17.8 64H56.3c-11.5 0-19.2 11.7-14.7 22.3l25.8 60.2C27.3 329.8 0 372.7 0 422.4v44.8C0 491.9 20.1 512 44.8 512h358.4c24.7 0 44.8-20.1 44.8-44.8v-44.8c0-48.4-25.8-90.4-64.1-114.1zM176 480l-41.6-192 49.6 32 24 40-32 120zm96 0l-32-120 24-40 49.6-32L272 480zm41.7-298.5c-3.9 11.9-7 24.6-16.5 33.4-10.1 9.3-48 22.4-64-25-2.8-8.4-15.4-8.4-18.3 0-17 50.2-56 32.4-64 25-9.5-8.8-12.7-21.5-16.5-33.4-.8-2.5-6.3-5.7-6.3-5.8v-10.8c28.3 3.6 61 5.8 96 5.8s67.7-2.1 96-5.8v10.8c-.1.1-5.6 3.2-6.4 5.8z"></path>
</symbol>
<symbol id="icon-users" viewBox="0 0 640 512">
<path d="M96 224c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm448 0c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm32 32h-64c-17.6 0-33.5 7.1-45.1 18.6 40.3 22.1 68.9 62 75.1 109.4h66c17.7 0 32-14.3 32-32v-32c0-35.3-28.7-64-64-64zm-256 0c61.9 0 112-50.1 112-112S381.9 32 320 32 208 82.1 208 144s50.1 112 112 112zm76.8 32h-8.3c-20.8 10-43.9 16-68.5 16s-47.6-6-68.5-16h-8.3C179.6 288 128 339.6 128 403.2V432c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48v-28.8c0-63.6-51.6-115.2-115.2-115.2zm-223.7-13.4C161.5 263.1 145.6 256 128 256H64c-35.3 0-64 28.7-64 64v32c0 17.7 14.3 32 32 32h65.9c6.3-47.4 34.9-87.3 75.2-109.4z"></path>
</symbol>
<symbol id="icon-wrench" viewBox="0 0 512 512">
<path d="M507.73 109.1c-2.24-9.03-13.54-12.09-20.12-5.51l-74.36 74.36-67.88-11.31-11.31-67.88 74.36-74.36c6.62-6.62 3.43-17.9-5.66-20.16-47.38-11.74-99.55.91-136.58 37.93-39.64 39.64-50.55 97.1-34.05 147.2L18.74 402.76c-24.99 24.99-24.99 65.51 0 90.5 24.99 24.99 65.51 24.99 90.5 0l213.21-213.21c50.12 16.71 107.47 5.68 147.37-34.22 37.07-37.07 49.7-89.32 37.91-136.73zM64 472c-13.25 0-24-10.75-24-24 0-13.26 10.75-24 24-24s24 10.74 24 24c0 13.25-10.75 24-24 24z"></path>
</symbol>
</svg>

Before

Width:  |  Height:  |  Size: 33 KiB

View File

@ -4,6 +4,7 @@
<title>Converse</title>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Converse XMPP/Jabber Chat"/>
<meta name="author" content="JC Brand" />
@ -53,6 +54,9 @@
<li class="nav-item page-scroll">
<a class="nav-link" href="#hosting">Hosting</a>
</li>
<li class="nav-item">
<a class="nav-link" href="https://github.com/conversejs/converse.js" target="_blank" rel="noopener">Github&nbsp;<i class="fa fa-external-link-alt"></i></a>
</li>
<li class="nav-item">
<a class="nav-link" href="/docs/html/index.html">Documentation&nbsp;<i class="fa fa-external-link-alt"></i></a>
</li>
@ -96,22 +100,13 @@
<p class="intro-text">Try the <a href="/fullscreen.html">fullpage</a> and <a href="https://github.com/conversejs/converse-desktop/releases" target="_blank" rel="noopener">desktop</a> versions<p>
<p style="padding-top: 1.5em">
<a href="https://inverse.chat/#converse/room?jid=discuss@conference.conversejs.org"
target="_blank" rel="noopener"><img src="https://inverse.chat/badge.svg?room=discuss@conference.conversejs.org"/></a>
target="_blank" rel="noopener"><img src="https://conference.conversejs.org/muc_badge/discuss@conference.conversejs.org"/></a>
</p>
<div class="page-scroll">
<a href="#about" class="btn btn-default btn-lg"><span class="btn-text">Learn More</span></a>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12 col-md-offset-2 banner-social-buttons">
<ul class="list-inline">
<li class="list-inline-item"><a href="https://twitter.com/jcopkode" class="btn btn-circle btn-lg" title="Twitter" target="_blank" rel="noopener"><i class="fab fa-twitter"></i></a></li>
<li class="list-inline-item"><a href="https://mastodon.xyz/@jcbrand" class="btn btn-lg" title="Mastodon" target="_blank" rel="noopener"><img class="mastodon" src="/logo/mastodon.svg"/></a></li>
<li class="list-inline-item"><a href="https://github.com/jcbrand/converse.js" class="btn btn-circle btn-lg" title="GitHub" target="_blank" rel="noopener"><i class="fab fa-github"></i></a></li>
</ul>
</div>
</div>
</section>
<section id="about" class="container content-section text-center">
@ -149,6 +144,7 @@
<li style="list-style: none">XMPP Servers</li>
<li><a href="https://www.igniterealtime.org/projects/openfire/plugins.jsp" target="_blank" rel="noopener">Openfire</a></li>
<li><a href="https://modules.prosody.im/mod_conversejs.html" target="_blank" rel="noopener">Prosody</a></li>
<li><a href="https://docs.ejabberd.im/admin/configuration/modules/#mod-conversejs" target="_blank" rel="noopener">Ejabberd</a></li>
</ul>
<ul class="integration">
<li style="list-style: none">Frameworks</li>
@ -185,6 +181,7 @@
<li>A <a href="https://conversejs.org/docs/html/plugin_development.html" target="_blank" rel="noopener">plugin architecture</a> based on <a href="https://conversejs.github.io/pluggable.js/" target="_blank" rel="noopener">pluggable.js</a></li>
<li>Chat statuses (online, busy, away, offline)</li>
<li>Desktop notifications</li>
<li>URL Previews (requires server support, for example <a href="https://modules.prosody.im/mod_ogp.html" target="_blank" rel="noopener">mod_ogp</a></li>
<li>Multi-user chatrooms (<a href="https://xmpp.org/extensions/xep-0045.html" target="_blank" rel="noopener">XEP 45</a>)</li>
<li>Chatroom bookmarks (<a href="https://xmpp.org/extensions/xep-0048.html" target="_blank" rel="noopener">XEP 48</a>)</li>
<li>Direct invitations to chat rooms (<a href="https://xmpp.org/extensions/xep-0249.html" target="_blank" rel="noopener">XEP 249</a>)</li>
@ -197,6 +194,7 @@
<li>Hidden messages (aka Spoilers) (<a href="https://xmpp.org/extensions/xep-0382.html" target="_blank" rel="noopener">XEP 382</a>)</li>
<li>Client state indication (<a href="https://xmpp.org/extensions/xep-0352.html" target="_blank" rel="noopener">XEP 352</a>)</li>
<li>OMEMO encrypted messaging (<a href="https://xmpp.org/extensions/xep-0384.html" target="_blank" rel="noopener">XEP 384</a>)</li>
<li>Message Styling (<a href="https://xmpp.org/extensions/xep-0384.html" target="_blank" rel="noopener">XEP 393</a>)</li>
<li>Anonymous logins, see the <a href="/demo/anonymous.html" target="_blank" rel="noopener">anonymous login demo</a></li>
<li>Message corrections, retractions and moderation</li>
<li>Translated into over 30 languages</li>
@ -212,8 +210,7 @@
<div class="col-lg-12 col-lg-offset-2">
<h2>Contact</h2>
<ul class="contact">
<li>Follow on <a href="https://twitter.com/jcopkode" target="_blank" rel="noopener">Twitter</a>
or <a href="https://mastodon.xyz/@jcbrand" target="_blank" rel="noopener">Mastodon</a>
<li>Follow on <a href="https://mastodon.xyz/@jcbrand" target="_blank" rel="noopener">the fediverse</a>
<li>Chat via XMPP at <a href="xmpp:jc@opkode.com" class="xmpp JSnocheck" title="XMPP/Jabber">jc@opkode.com</a></li>
<li>For technical support, you can ask on <a href="https://stackoverflow.com/questions/tagged/converse.js">Stack Overflow</a>
<li>The Converse XMPP chatroom: <a href="xmpp:discuss@conference.conversejs.org?join" class="xmpp JSnocheck chatroom-name" title="Converse chat room">discuss@conference.conversejs.org</a></li>
@ -243,10 +240,11 @@
<div class="sponsors">
<h2>Converse is supported by:</h2>
<ul >
<li><a href="https://bairesdev.com/sponsoring-open-source-projects/?utm_source=conversejs" target="_blank" rel="noopener"><img style="width: 13em" src="/media/logos/bairesdev-primary.png" alt="BairesDev"></a></li>
<li><a href="https://blokt.com?utm_source=conversejs" target="_blank" rel="noopener"><img style="width: 12em" src="/logo/blokt.png" alt="Blokt Crypto & Privacy"></a></li>
<li><a href="https://primesound.org/?utm_source=conversejs" target="_blank" rel="noopener"><img style="width: 10em" src="/media/logos/primesound.png" alt="Prime Sound"></a></li>
<li><a href="https://www.keycdn.com?utm_source=conversejs" target="_blank" rel="noopener"><img style="height: 3em" src="/logo/keycdn.svg" alt="KeyCDN"></a></li>
<li><a href="https://weblate.org?utm_source=conversejs" target="_blank" rel="noopener"><img style="height: 2.6em" src="/logo/weblate-button.svg" alt="Weblate"></a></li>
<li><a href="https://www.codefirst.co.uk?utm_source=conversejs" target="_blank" rel="noopener"><img style="width: 12em; padding-top: 0.5em" src="/logo/codefirst.png" alt="Codefirst"></a></li>
<li><a href="https://blokt.com?utm_source=conversejs" target="_blank" rel="noopener"><img style="width: 12em" src="/logo/blokt.png" alt="Blokt Crypto & Privacy"></a></li>
</ul>
</div>

View File

@ -11,17 +11,17 @@
<!-- These files are NOT needed when using converse.js in your own project. -->
<link rel="shortcut icon" type="image/ico" href="images/favicon.ico"/>
<link type="text/css" rel="stylesheet" media="screen" href="https://cdn.conversejs.org/7.0.0/css/font-awesome.min.css" />
<link type="text/css" rel="stylesheet" media="screen" href="https://cdn.conversejs.org/7.0.0/css/website.min.css" />
<link type="text/css" rel="stylesheet" media="screen" href="https://cdn.conversejs.org/10.1.6/css/font-awesome.min.css" />
<link type="text/css" rel="stylesheet" media="screen" href="https://cdn.conversejs.org/10.1.6/css/website.min.css" />
<noscript><p><img src="//stats.opkode.com/piwik.php?idsite=1" style="border:0;" alt="" /></p></noscript>
<script type="text/javascript" src="/src/website.js"></script>
<script type="text/javascript" src="analytics.js"></script>
<!-- *********************************************************************** -->
<![if gte IE 11]>
<link type="text/css" rel="stylesheet" media="screen" href="https://cdn.conversejs.org/7.0.0/css/converse.min.css" />
<link type="text/css" rel="stylesheet" media="screen" href="https://cdn.conversejs.org/10.1.6/css/converse.min.css" />
<script src="https://cdn.conversejs.org/3rdparty/libsignal-protocol.min.js"></script>
<script src="https://cdn.conversejs.org/7.0.0/dist/converse.min.js"></script>
<script src="https://cdn.conversejs.org/10.1.6/dist/converse.min.js"></script>
<![endif]>
</head>
@ -66,7 +66,7 @@
<table id="jslicense-labels1" style="width: 100%">
<tr>
<td>
<a href="https://cdn.conversejs.org/7.0.0/dist/converse.min.js">converse.min.js</a>
<a href="https://cdn.conversejs.org/10.1.6/dist/converse.min.js">converse.min.js</a>
</td>
<td>
<a href="https://www.mozilla.org/en-US/MPL/2.0/">MPL-2.0</a>

View File

@ -3,14 +3,16 @@ const path = require('path');
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
frameworks: ['jasmine'],
files: [
{ pattern: 'dist/*.js.map', included: false },
{ pattern: 'dist/*.css.map', included: false },
{ pattern: "dist/icons.js", served: true },
{ pattern: "dist/emojis.js", served: true },
"src/shared/tests/tests.css",
"node_modules/lodash/lodash.min.js",
"dist/converse.js",
"dist/converse.css",
{ pattern: "dist/images/**/*.*", included: false },
@ -21,47 +23,100 @@ module.exports = function(config) {
served: true,
nocache: false
},
{ pattern: "node_modules/sinon/pkg/sinon.js", type: 'module' },
{ pattern: "spec/mock.js", type: 'module' },
{ pattern: "src/shared/tests/mock.js", type: 'module' },
{ pattern: "spec/spoilers.js", type: 'module' },
{ pattern: "spec/emojis.js", type: 'module' },
{ pattern: "spec/muclist.js", type: 'module' },
{ pattern: "spec/utils.js", type: 'module' },
{ pattern: "spec/converse.js", type: 'module' },
{ pattern: "spec/bookmarks.js", type: 'module' },
{ pattern: "spec/headline.js", type: 'module' },
{ pattern: "spec/disco.js", type: 'module' },
{ pattern: "spec/protocol.js", type: 'module' },
{ pattern: "spec/presence.js", type: 'module' },
{ pattern: "spec/eventemitter.js", type: 'module' },
{ pattern: "spec/smacks.js", type: 'module' },
{ pattern: "spec/ping.js", type: 'module' },
{ pattern: "spec/push.js", type: 'module' },
{ pattern: "spec/xmppstatus.js", type: 'module' },
{ pattern: "spec/mam.js", type: 'module' },
{ pattern: "spec/omemo.js", type: 'module' },
{ pattern: "spec/controlbox.js", type: 'module' },
{ pattern: "spec/roster.js", type: 'module' },
{ pattern: "spec/chatbox.js", type: 'module' },
{ pattern: "spec/user-details-modal.js", type: 'module' },
{ pattern: "spec/messages.js", type: 'module' },
{ pattern: "spec/corrections.js", type: 'module' },
{ pattern: "spec/receipts.js", type: 'module' },
{ pattern: "spec/muc_messages.js", type: 'module' },
{ pattern: "spec/mentions.js", type: 'module' },
{ pattern: "spec/retractions.js", type: 'module' },
{ pattern: "spec/muc.js", type: 'module' },
{ pattern: "spec/modtools.js", type: 'module' },
{ pattern: "spec/room_registration.js", type: 'module' },
{ pattern: "spec/autocomplete.js", type: 'module' },
{ pattern: "spec/minchats.js", type: 'module' },
{ pattern: "spec/notification.js", type: 'module' },
{ pattern: "spec/login.js", type: 'module' },
{ pattern: "spec/register.js", type: 'module' },
{ pattern: "spec/hats.js", type: 'module' },
{ pattern: "spec/http-file-upload.js", type: 'module' },
{ pattern: "spec/xss.js", type: 'module' }
{ pattern: "src/headless/plugins/caps/tests/caps.js", type: 'module' },
{ pattern: "src/headless/plugins/chat/tests/api.js", type: 'module' },
{ pattern: "src/headless/plugins/disco/tests/disco.js", type: 'module' },
{ pattern: "src/headless/plugins/muc/tests/affiliations.js", type: 'module' },
{ pattern: "src/headless/plugins/muc/tests/messages.js", type: 'module' },
{ pattern: "src/headless/plugins/muc/tests/muc.js", type: 'module' },
{ pattern: "src/headless/plugins/muc/tests/occupants.js", type: 'module' },
{ pattern: "src/headless/plugins/muc/tests/pruning.js", type: 'module' },
{ pattern: "src/headless/plugins/muc/tests/registration.js", type: 'module' },
{ pattern: "src/headless/plugins/ping/tests/ping.js", type: 'module' },
{ pattern: "src/headless/plugins/roster/tests/presence.js", type: 'module' },
{ pattern: "src/headless/plugins/smacks/tests/smacks.js", type: 'module' },
{ pattern: "src/headless/plugins/status/tests/status.js", type: 'module' },
{ pattern: "src/headless/shared/settings/tests/settings.js", type: 'module' },
{ pattern: "src/headless/tests/converse.js", type: 'module' },
{ pattern: "src/headless/tests/eventemitter.js", type: 'module' },
{ pattern: "src/modals/tests/user-details-modal.js", type: 'module' },
{ pattern: "src/plugins/adhoc-views/tests/adhoc.js", type: 'module' },
{ pattern: "src/plugins/bookmark-views/tests/bookmarks-list.js", type: 'module' },
{ pattern: "src/plugins/bookmark-views/tests/bookmarks.js", type: 'module' },
{ pattern: "src/plugins/chatview/tests/chatbox.js", type: 'module' },
{ pattern: "src/plugins/chatview/tests/corrections.js", type: 'module' },
{ pattern: "src/plugins/chatview/tests/emojis.js", type: 'module' },
{ pattern: "src/plugins/chatview/tests/http-file-upload.js", type: 'module' },
{ pattern: "src/plugins/chatview/tests/markers.js", type: 'module' },
{ pattern: "src/plugins/chatview/tests/me-messages.js", type: 'module' },
{ pattern: "src/plugins/chatview/tests/message-audio.js", type: 'module' },
{ pattern: "src/plugins/chatview/tests/message-gifs.js", type: 'module' },
{ pattern: "src/plugins/chatview/tests/message-images.js", type: 'module' },
{ pattern: "src/plugins/chatview/tests/message-videos.js", type: 'module' },
{ pattern: "src/plugins/chatview/tests/messages.js", type: 'module' },
{ pattern: "src/plugins/chatview/tests/oob.js", type: 'module' },
{ pattern: "src/plugins/chatview/tests/receipts.js", type: 'module' },
{ pattern: "src/plugins/chatview/tests/spoilers.js", type: 'module' },
{ pattern: "src/plugins/chatview/tests/styling.js", type: 'module' },
{ pattern: "src/plugins/chatview/tests/unreads.js", type: 'module' },
{ pattern: "src/plugins/chatview/tests/xss.js", type: 'module' },
{ pattern: "src/plugins/controlbox/tests/controlbox.js", type: 'module' },
{ pattern: "src/plugins/controlbox/tests/login.js", type: 'module' },
{ pattern: "src/plugins/headlines-view/tests/headline.js", type: 'module' },
{ pattern: "src/plugins/mam-views/tests/mam.js", type: 'module' },
{ pattern: "src/plugins/mam-views/tests/placeholder.js", type: 'module' },
{ pattern: "src/plugins/minimize/tests/minchats.js", type: 'module' },
{ pattern: "src/plugins/muc-views/tests/autocomplete.js", type: 'module' },
{ pattern: "src/plugins/muc-views/tests/component.js", type: 'module' },
{ pattern: "src/plugins/muc-views/tests/corrections.js", type: 'module' },
{ pattern: "src/plugins/muc-views/tests/disco.js", type: 'module' },
{ pattern: "src/plugins/muc-views/tests/emojis.js", type: 'module' },
{ pattern: "src/plugins/muc-views/tests/hats.js", type: 'module' },
{ pattern: "src/plugins/muc-views/tests/http-file-upload.js", type: 'module' },
{ pattern: "src/plugins/muc-views/tests/info-messages.js", type: 'module' },
{ pattern: "src/plugins/muc-views/tests/mam.js", type: 'module' },
{ pattern: "src/plugins/muc-views/tests/markers.js", type: 'module' },
{ pattern: "src/plugins/muc-views/tests/me-messages.js", type: 'module' },
{ pattern: "src/plugins/muc-views/tests/member-lists.js", type: 'module' },
{ pattern: "src/plugins/muc-views/tests/mentions.js", type: 'module' },
{ pattern: "src/plugins/muc-views/tests/mep.js", type: 'module' },
{ pattern: "src/plugins/muc-views/tests/modtools.js", type: 'module' },
{ pattern: "src/plugins/muc-views/tests/muc-add-modal.js", type: 'module' },
{ pattern: "src/plugins/muc-views/tests/muc-api.js", type: 'module' },
{ pattern: "src/plugins/muc-views/tests/muc-list-modal.js", type: 'module' },
{ pattern: "src/plugins/muc-views/tests/muc-mentions.js", type: 'module' },
{ pattern: "src/plugins/muc-views/tests/muc-messages.js", type: 'module' },
{ pattern: "src/plugins/muc-views/tests/muc-registration.js", type: 'module' },
{ pattern: "src/plugins/muc-views/tests/muc.js", type: 'module' },
{ pattern: "src/plugins/muc-views/tests/nickname.js", type: 'module' },
{ pattern: "src/plugins/muc-views/tests/occupants.js", type: 'module' },
{ pattern: "src/plugins/muc-views/tests/rai.js", type: 'module' },
{ pattern: "src/plugins/muc-views/tests/retractions.js", type: 'module' },
{ pattern: "src/plugins/muc-views/tests/styling.js", type: 'module' },
{ pattern: "src/plugins/muc-views/tests/toolbar.js", type: 'module' },
{ pattern: "src/plugins/muc-views/tests/unfurls.js", type: 'module' },
{ pattern: "src/plugins/muc-views/tests/xss.js", type: 'module' },
{ pattern: "src/plugins/notifications/tests/notification.js", type: 'module' },
{ pattern: "src/plugins/omemo/tests/corrections.js", type: 'module' },
{ pattern: "src/plugins/omemo/tests/media-sharing.js", type: 'module' },
{ pattern: "src/plugins/omemo/tests/muc.js", type: 'module' },
{ pattern: "src/plugins/omemo/tests/omemo.js", type: 'module' },
{ pattern: "src/plugins/profile/tests/password-reset.js", type: 'module' },
{ pattern: "src/plugins/profile/tests/profile.js", type: 'module' },
{ pattern: "src/plugins/profile/tests/status.js", type: 'module' },
{ pattern: "src/plugins/push/tests/push.js", type: 'module' },
{ pattern: "src/plugins/register/tests/register.js", type: 'module' },
{ pattern: "src/plugins/roomslist/tests/roomslist.js", type: 'module' },
{ pattern: "src/plugins/rootview/tests/root.js", type: 'module' },
{ pattern: "src/plugins/rosterview/tests/add-contact-modal.js", type: 'module' },
{ pattern: "src/plugins/rosterview/tests/presence.js", type: 'module' },
{ pattern: "src/plugins/rosterview/tests/protocol.js", type: 'module' },
{ pattern: "src/plugins/rosterview/tests/roster.js", type: 'module' },
// For some reason this test causes issues when its run earlier
{ pattern: "src/headless/tests/persistence.js", type: 'module' },
],
proxies: {

View File

@ -1,7 +0,0 @@
{
"packages": [
".",
"src/*"
],
"version": "4.0.3"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@ -1,19 +1,34 @@
<svg class="converse-svg-logo"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 364 364">
<title>Converse</title>
<g class="cls-1" id="g904">
<g data-name="Layer 2">
<g data-name="Layer 7">
<path
class="cls-3"
d="M221.46,103.71c0,18.83-29.36,18.83-29.12,0C192.1,84.88,221.46,84.88,221.46,103.71Z" />
<path
class="cls-4"
d="M179.9,4.15A175.48,175.48,0,1,0,355.38,179.63,175.48,175.48,0,0,0,179.9,4.15Zm-40.79,264.5c-.23-17.82,27.58-17.82,27.58,0S138.88,286.48,139.11,268.65ZM218.6,168.24A79.65,79.65,0,0,1,205.15,174a12.76,12.76,0,0,0-6.29,4.65L167.54,222a1.36,1.36,0,0,1-2.46-.8v-35.8a2.58,2.58,0,0,0-3.06-2.53c-15.43,3-30.23,7.7-42.73,19.94-38.8,38-29.42,105.69,16.09,133.16a162.25,162.25,0,0,1-91.47-67.27C-3.86,182.26,34.5,47.25,138.37,25.66c46.89-9.75,118.25,5.16,123.73,62.83C265.15,120.64,246.56,152.89,218.6,168.24Z" />
</g>
</g>
</g>
</svg>
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" id="svg108" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;"
xml:space="preserve" version="1.1"
viewBox="0 0 376 311" height="20%" width="10rem"
sodipodi:docname="chapril-logo.svg" inkscape:version="0.92.1 r15371">
<sodipodi:namedview pagecolor="#ffffff" bordercolor="#666666" borderopacity="1" objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:window-width="640" inkscape:window-height="480" id="namedview16" showgrid="false" inkscape:zoom="0.75884244" inkscape:cx="188" inkscape:cy="155.5" inkscape:window-x="0" inkscape:window-y="24" inkscape:window-maximized="0" inkscape:current-layer="svg108"/>
<metadata id="metadata114">
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:title/>
<cc:license rdf:resource="GFDL version 1.3 ou ultérieure, Creative Commons By Sa version 2.0 ou ultérieure, Licence Art Libre version 1.3 ou ultérieure"/>
<dc:creator>
<cc:Agent>
<dc:title>Antoine BARDELLI</dc:title>
</cc:Agent>
</dc:creator>
</cc:Work>
</rdf:RDF>
</metadata>
<defs id="defs112"/>
<g id="g250" style="clip-rule:evenodd;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41420996" transform="translate(4.6079614e-7,-4.4571451e-6)">
<path id="path124" style="clip-rule:evenodd;fill:#005184;fill-rule:nonzero;stroke-linejoin:round;stroke-miterlimit:1.41420996" d="m 96.70711,209.69029 c -2.742,1.114 -5.399,1.8 -7.885,2.057 -0.771,0.085 -1.629,0.171 -2.4,0.171 -2.571,0 -5.314,-0.428 -8.228,-1.286 -2.486,-0.857 -4.628,-2.314 -6.514,-4.371 -1.886,-1.8 -3.343,-3.942 -4.371,-6.428 -0.943,-2.486 -1.457,-5.057 -1.543,-7.714 0,-0.086 0,-0.257 0,-0.343 0,-2.485 0.514,-4.971 1.543,-7.371 1.028,-2.314 2.485,-4.457 4.371,-6.428 1.886,-2.057 4.028,-3.514 6.514,-4.371 2.828,-1.029 5.571,-1.543 8.142,-1.543 0.257,0 0.6,0 0.857,0 3.686,0.171 6.857,1.028 9.686,2.657 -0.086,1.457 -0.343,3.514 -0.6,6.343 -2.743,-1.372 -5.4,-2.143 -7.971,-2.315 -1.972,-0.171 -3.943,0.086 -6,0.772 -1.629,0.514 -3.171,1.457 -4.457,2.914 -1.286,1.371 -2.228,2.828 -2.914,4.457 -0.772,1.628 -1.114,3.342 -1.114,5.142 0.085,1.886 0.428,3.6 1.114,5.229 0.686,1.714 1.628,3.171 2.914,4.457 1.286,1.285 2.828,2.228 4.457,2.914 2.486,0.685 4.543,1.028 6.343,1.028 3.342,-0.343 5.999,-1.2 8.056,-2.657 0,1.457 0,3.686 0,6.686 z"/>
<path id="path126" style="clip-rule:evenodd;fill:#005184;fill-rule:nonzero;stroke-linejoin:round;stroke-miterlimit:1.41420996" d="m 137.33411,184.91929 c 0,1.8 0,3.515 0,5.314 0,2.657 0,5.4 -0.086,8.057 0,4.457 0,8.743 0,12.771 -1.714,0 -4.285,0 -7.799,0 0,-3.857 0,-11.571 0.085,-23.142 0.086,-1.114 -0.171,-2.228 -0.6,-3.257 -0.428,-1.028 -1.028,-1.971 -1.8,-2.742 -0.942,-0.943 -2.142,-1.715 -3.599,-2.143 -1.029,-0.257 -2.229,-0.429 -3.6,-0.343 -1.115,0.086 -2.229,0.343 -3.257,0.686 -1.029,0.428 -2.143,1.028 -3.343,1.8 -0.6,0.6 -1.029,1.2 -1.457,1.8 v 27.341 h -8.057 v -62.997 h 8.057 v 29.313 c 0.943,-1.114 1.8,-1.971 2.571,-2.486 1.629,-0.942 3,-1.542 4.2,-1.885 1.971,-0.429 3.771,-0.6 5.571,-0.6 2.143,0.085 3.943,0.343 5.4,0.943 1.543,0.6 2.914,1.542 4.028,2.742 2.4,2.572 3.6,5.486 3.686,8.828 z"/>
<path id="path128" style="clip-rule:evenodd;fill-rule:nonzero;stroke-linejoin:round;stroke-miterlimit:1.41420996" d="m 169.38911,146.86429 c 4.714,10.714 14.228,32.056 28.37,64.111 -1.371,0 -4.114,0 -8.313,0 -1.286,-2.657 -3.772,-7.971 -7.543,-15.942 -4.028,0 -12.085,0 -24.17,0 -1.114,2.657 -3.514,7.971 -7.028,15.942 -1.457,0 -4.2,0 -8.4,0 4.543,-10.713 13.542,-32.055 27.084,-64.111 z m 9.171,40.884 c -1.457,-3.686 -4.542,-10.885 -9.085,-21.77 -1.457,3.599 -4.285,10.885 -8.571,21.77 3,0 8.828,0 17.656,0 z"/>
<path id="path130" style="clip-rule:evenodd;fill-rule:nonzero;stroke-linejoin:round;stroke-miterlimit:1.41420996" d="m 212.15911,199.83329 c 0.257,0.429 0.6,0.771 0.857,1.114 1.114,1.457 2.657,2.743 4.457,3.686 1.457,0.685 3.085,1.028 4.8,1.028 0.085,0 0.257,0 0.428,0 1.8,0.086 3.514,-0.257 5.143,-1.028 1.628,-0.6 3.171,-1.629 4.457,-2.914 1.285,-1.286 2.228,-2.743 2.914,-4.457 0.685,-1.543 1.028,-3.343 1.028,-5.314 0.086,-1.715 -0.257,-3.429 -1.028,-5.057 -0.6,-1.629 -1.629,-3.171 -2.914,-4.457 -1.286,-1.286 -2.743,-2.229 -4.457,-2.914 -1.115,-0.515 -2.572,-0.772 -4.2,-0.772 -0.172,0 -0.343,0 -0.429,0 -2.657,0.086 -4.714,0.429 -5.999,1.2 -3.429,1.8 -5.143,3.857 -5.143,6.171 0,3 0,7.629 0.086,13.714 z m 0,8.314 c -0.086,3.343 -0.086,10.028 -0.086,20.056 -1.286,0 -4.028,0 -8.057,0 v -54.769 c 2.657,0 5.4,0 8.057,0 0.086,1.286 0.086,2.4 0.086,3.257 0.857,-1.114 2.314,-2.142 4.457,-3.085 2.4,-1.029 4.971,-1.543 7.714,-1.543 2.657,0 5.228,0.514 7.628,1.543 2.485,1.028 4.714,2.485 6.514,4.371 1.971,1.886 3.428,4.028 4.371,6.428 1.028,2.486 1.543,4.971 1.543,7.543 0,0.085 0,0.085 0,0.171 0,2.657 -0.515,5.228 -1.543,7.714 -1.029,2.486 -2.486,4.628 -4.371,6.428 -1.886,1.972 -4.029,3.429 -6.514,4.371 -2.486,1.029 -5.057,1.543 -7.628,1.543 -2.657,-0.085 -5.229,-0.6 -7.714,-1.543 -1.372,-0.514 -2.829,-1.371 -4.457,-2.485 z"/>
<path id="path132" style="clip-rule:evenodd;fill-rule:nonzero;stroke-linejoin:round;stroke-miterlimit:1.41420996" d="m 271.04211,180.46329 c 0,-0.086 -0.686,-0.172 -2.143,-0.429 -2.743,-0.086 -5.228,0.857 -7.371,2.828 -0.857,0.772 -1.543,1.886 -2.057,3.343 -0.343,1.371 -0.515,2.829 -0.6,4.457 0,4.543 0,11.399 0,20.399 -1.286,0 -3.943,0 -7.971,0 0,-6.257 0,-18.856 -0.086,-37.627 1.286,0 3.943,0 7.8,0 0.085,0.772 0.085,2.4 0.085,4.8 0,0.514 0,1.543 -0.085,3.171 1.028,-4.199 3.085,-6.856 6.085,-7.971 1.2,-0.343 2.4,-0.514 3.686,-0.514 0.857,-0.086 1.714,0 2.657,0.171 0,1.629 0,4.115 0,7.372 z"/>
<path id="path134" style="clip-rule:evenodd;fill:#005184;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41420996" d="m 277.47011,163.23529 c 0,-1.372 0.514,-2.4 1.457,-3.171 0.943,-0.772 1.971,-1.2 3.085,-1.2 0.086,0 0.172,0 0.258,0 1.114,0 2.057,0.342 2.999,1.028 0.943,0.771 1.372,1.8 1.372,3.257 0,1.457 -0.429,2.571 -1.372,3.428 -0.942,0.858 -2.057,1.286 -3.257,1.286 -1.114,0 -2.142,-0.428 -3.085,-1.2 -0.943,-0.771 -1.457,-1.971 -1.457,-3.428 z"/>
<path style="clip-rule:evenodd;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41420996" id="path136" d="m 278.15611,173.34929 c 1.371,0 4.028,0 8.056,0 0,6.342 0,18.942 0,37.883 -1.285,0 -3.942,0 -7.885,0 0,-6.256 -0.086,-18.941 -0.171,-37.883 z"/>
<path id="path138" style="clip-rule:evenodd;fill-rule:nonzero;stroke-linejoin:round;stroke-miterlimit:1.41420996" d="m 295.55511,146.26429 v 64.797 c 1.285,0 3.942,0 7.885,0 0,-10.799 0,-32.398 0,-64.797 -1.286,0 -3.943,0 -7.885,0 z"/>
<path id="path144" style="clip-rule:evenodd;fill:#005184;fill-rule:nonzero;stroke-linejoin:round;stroke-miterlimit:1.41420996" d="m 79.90511,45.008286 c 0.902,0.305 0.903,0.306 1.74,0.76 0,0 2.36,1.6 3.541,2.399 16.192,11.056 46.905,36.807 46.905,36.807 l -0.62,0.933 c 0,0 -30.962,-17.269 -47.812,-25.837 -0.154,2.104 -0.309,4.208 -0.465,6.312 l -0.126,1.689 c -0.635,7.993 -1.295,15.97 -2,23.945 l -0.096,1.076 c -0.824,8.583004 -1.124,17.369004 -3.069,25.573004 -1.802,7.601 -10.27,13.477 -15.485,20.114 -10.856,13.816 -19.361,29.582 -21.64,47.603 -2.579,20.389 5.773,40.853 21.062,55.815 5.92,5.794 12.534,10.853 19.323,15.617 l -3.768,5.852 c -20.581,-12.139 -40.182,-28.618 -47.181,-51.981 -6.615,-22.081 -1.608,-47.917 10.144,-67.278 6.689,-11.02 14.834,-21.098 23.413,-30.201 0,0 0.585,-2.521 0.874,-4.27 3.14,-19.016004 5.383,-38.057004 7.92,-57.227004 l 0.274,-2.074 0.28,-1.686 c 0.307,-0.8 0.337,-1.033 0.841,-1.737 1.119,-1.562 2.062,-2.818 5.945,-2.204 z"/>
<path id="path146" style="clip-rule:evenodd;fill:#005184;fill-rule:nonzero;stroke-linejoin:round;stroke-miterlimit:1.41420996" d="m 300.65411,44.858286 c 2.74,0.486 2.778,0.936 3.448,1.587 2.555,2.484 2.191,7.238 2.75,11.471 2.467,18.612 4.172,37.353 7.871,55.935004 0,0 3.607,4.013 6.264,7.099 11.064,12.849 21.019,26.411 26.284,43.975 6.27,20.92 3.585,41.82 -7.633,60.315 -9.349,15.414 -24.268,26.668 -39.964,35.962 l -0.593,-1.853 c 17.279,-12.08 34.133,-26.972 39.318,-48.24 3.677,-15.083 -0.809,-32.515 -6.571,-47.292 -5.094,-13.065 -14.589,-24.209 -23.233,-34.394 -1.789,-2.107 -3.603,-4.192 -5.472,-6.229 0,0 -2.204,-3.069 -2.806,-6.739 -2.582,-15.749 -3.416,-31.540004 -4.699,-47.326004 0,0 -0.34,-4.424 -0.589,-7.754 l -0.098,-1.322 -30.582,18.428 -15.221,9.11 -0.801,0.477 -3.955,-6.151 0.767,-0.531 14.605,-10.067 37.28,-25.534 c 0,0 1.172,-0.939 3.63,-0.927 z m 14.362,70.312004 c 0.178,0.639 -0.049,-0.186 0,0 z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 8.9 KiB

View File

@ -0,0 +1,19 @@
<svg class="converse-svg-logo"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 364 364">
<title>Converse</title>
<g class="cls-1" id="g904">
<g data-name="Layer 2">
<g data-name="Layer 7">
<path
class="cls-3"
d="M221.46,103.71c0,18.83-29.36,18.83-29.12,0C192.1,84.88,221.46,84.88,221.46,103.71Z" />
<path
class="cls-4"
d="M179.9,4.15A175.48,175.48,0,1,0,355.38,179.63,175.48,175.48,0,0,0,179.9,4.15Zm-40.79,264.5c-.23-17.82,27.58-17.82,27.58,0S138.88,286.48,139.11,268.65ZM218.6,168.24A79.65,79.65,0,0,1,205.15,174a12.76,12.76,0,0,0-6.29,4.65L167.54,222a1.36,1.36,0,0,1-2.46-.8v-35.8a2.58,2.58,0,0,0-3.06-2.53c-15.43,3-30.23,7.7-42.73,19.94-38.8,38-29.42,105.69,16.09,133.16a162.25,162.25,0,0,1-91.47-67.27C-3.86,182.26,34.5,47.25,138.37,25.66c46.89-9.75,118.25,5.16,123.73,62.83C265.15,120.64,246.56,152.89,218.6,168.24Z" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -1,108 +1,46 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
class="converse-svg-logo"
viewBox="0 0 364 364"
version="1.1"
id="svg13"
sodipodi:docname="conversejs-with-byline.svg"
inkscape:version="0.92.2 5c3e80d, 2017-08-06">
<metadata
id="metadata19">
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="chapril-logo"
style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;"
class="converse-svg-logo"
xml:space="preserve" version="1.1"
viewBox="0 0 376 311" height="20%" width="6rem"
sodipodi:docname="chapril-logo.svg" inkscape:version="0.92.1 r15371">
<sodipodi:namedview pagecolor="#ffffff" bordercolor="#666666" borderopacity="1" objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:window-width="640" inkscape:window-height="480" id="namedview16" showgrid="false" inkscape:zoom="0.75884244" inkscape:cx="188" inkscape:cy="155.5" inkscape:window-x="0" inkscape:window-y="24" inkscape:window-maximized="0" inkscape:current-layer="svg108"/>
<metadata id="metadata114">
<rdf:RDF>
<cc:Work
rdf:about="">
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Converse</dc:title>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:title/>
<cc:license rdf:resource="GFDL version 1.3 ou ultérieure, Creative Commons By Sa version 2.0 ou ultérieure, Licence Art Libre version 1.3 ou ultérieure"/>
<dc:creator>
<cc:Agent>
<dc:title>Antoine BARDELLI</dc:title>
</cc:Agent>
</dc:creator>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs17">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 182 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="364 : 182 : 1"
inkscape:persp3d-origin="182 : 121.33333 : 1"
id="perspective2147" />
</defs>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1434"
inkscape:window-height="951"
id="namedview15"
showgrid="false"
inkscape:zoom="1.8338154"
inkscape:cx="225.17086"
inkscape:cy="243.79827"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg13" />
<title
id="title2">Converse</title>
<g
class="cls-1"
id="g904"
transform="matrix(0.2441072,0,0,0.2441072,12.20969,55.55023)">
<g
data-name="Layer 2"
id="g10">
<g
data-name="Layer 7"
id="g8">
<path
class="cls-3"
d="m 221.46,103.71 c 0,18.83 -29.36,18.83 -29.12,0 -0.24,-18.83 29.12,-18.83 29.12,0 z"
id="path4"
inkscape:connector-curvature="0" />
<path
class="cls-4"
d="M 179.9,4.15 C 108.92504,4.15 44.938239,46.904566 17.778836,112.4757 -9.3805118,178.0467 5.6365472,253.52014 55.823205,303.70679 106.00986,353.89345 181.4833,368.91051 247.0543,341.75116 312.62543,314.59176 355.38,250.60496 355.38,179.63 355.38,82.715072 276.81493,4.15 179.9,4.15 Z m -40.79,264.5 c -0.23,-17.82 27.58,-17.82 27.58,0 0,17.82 -27.81,17.83 -27.58,0 z M 218.6,168.24 c -4.29711,2.32859 -8.79944,4.25673 -13.45,5.76 -2.53177,0.85328 -12.23498,3.26952 -13.79313,5.4398 C 180.90809,189.252 165.08,221.2 165.08,221.2 v -35.8 c -0.003,-1.6153 -1.4729,-2.83052 -3.06,-2.53 -15.43,3 -30.23,7.7 -42.73,19.94 -38.8,38 -29.025098,103.71549 16.4849,131.18549 C 98.17801,323.32071 65.725789,295.74404 44.332966,263.03587 -3.4370336,176.59587 35.058475,51.159326 138.92848,29.569326 185.81848,19.819326 256.62,30.82 262.1,88.49 c 3.05,32.15 -15.54,64.4 -43.5,79.75 z"
id="path6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sssssscsccccccccccccc" />
</g>
</g>
<defs id="defs112"/>
<g id="g250" style="clip-rule:evenodd;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41420996" transform="translate(4.6079614e-7,-4.4571451e-6)">
<path id="path124" style="clip-rule:evenodd;fill:#005184;fill-rule:nonzero;stroke-linejoin:round;stroke-miterlimit:1.41420996" d="m 96.70711,209.69029 c -2.742,1.114 -5.399,1.8 -7.885,2.057 -0.771,0.085 -1.629,0.171 -2.4,0.171 -2.571,0 -5.314,-0.428 -8.228,-1.286 -2.486,-0.857 -4.628,-2.314 -6.514,-4.371 -1.886,-1.8 -3.343,-3.942 -4.371,-6.428 -0.943,-2.486 -1.457,-5.057 -1.543,-7.714 0,-0.086 0,-0.257 0,-0.343 0,-2.485 0.514,-4.971 1.543,-7.371 1.028,-2.314 2.485,-4.457 4.371,-6.428 1.886,-2.057 4.028,-3.514 6.514,-4.371 2.828,-1.029 5.571,-1.543 8.142,-1.543 0.257,0 0.6,0 0.857,0 3.686,0.171 6.857,1.028 9.686,2.657 -0.086,1.457 -0.343,3.514 -0.6,6.343 -2.743,-1.372 -5.4,-2.143 -7.971,-2.315 -1.972,-0.171 -3.943,0.086 -6,0.772 -1.629,0.514 -3.171,1.457 -4.457,2.914 -1.286,1.371 -2.228,2.828 -2.914,4.457 -0.772,1.628 -1.114,3.342 -1.114,5.142 0.085,1.886 0.428,3.6 1.114,5.229 0.686,1.714 1.628,3.171 2.914,4.457 1.286,1.285 2.828,2.228 4.457,2.914 2.486,0.685 4.543,1.028 6.343,1.028 3.342,-0.343 5.999,-1.2 8.056,-2.657 0,1.457 0,3.686 0,6.686 z"/>
<path id="path126" style="clip-rule:evenodd;fill:#005184;fill-rule:nonzero;stroke-linejoin:round;stroke-miterlimit:1.41420996" d="m 137.33411,184.91929 c 0,1.8 0,3.515 0,5.314 0,2.657 0,5.4 -0.086,8.057 0,4.457 0,8.743 0,12.771 -1.714,0 -4.285,0 -7.799,0 0,-3.857 0,-11.571 0.085,-23.142 0.086,-1.114 -0.171,-2.228 -0.6,-3.257 -0.428,-1.028 -1.028,-1.971 -1.8,-2.742 -0.942,-0.943 -2.142,-1.715 -3.599,-2.143 -1.029,-0.257 -2.229,-0.429 -3.6,-0.343 -1.115,0.086 -2.229,0.343 -3.257,0.686 -1.029,0.428 -2.143,1.028 -3.343,1.8 -0.6,0.6 -1.029,1.2 -1.457,1.8 v 27.341 h -8.057 v -62.997 h 8.057 v 29.313 c 0.943,-1.114 1.8,-1.971 2.571,-2.486 1.629,-0.942 3,-1.542 4.2,-1.885 1.971,-0.429 3.771,-0.6 5.571,-0.6 2.143,0.085 3.943,0.343 5.4,0.943 1.543,0.6 2.914,1.542 4.028,2.742 2.4,2.572 3.6,5.486 3.686,8.828 z"/>
<path id="path128" style="clip-rule:evenodd;fill-rule:nonzero;stroke-linejoin:round;stroke-miterlimit:1.41420996" d="m 169.38911,146.86429 c 4.714,10.714 14.228,32.056 28.37,64.111 -1.371,0 -4.114,0 -8.313,0 -1.286,-2.657 -3.772,-7.971 -7.543,-15.942 -4.028,0 -12.085,0 -24.17,0 -1.114,2.657 -3.514,7.971 -7.028,15.942 -1.457,0 -4.2,0 -8.4,0 4.543,-10.713 13.542,-32.055 27.084,-64.111 z m 9.171,40.884 c -1.457,-3.686 -4.542,-10.885 -9.085,-21.77 -1.457,3.599 -4.285,10.885 -8.571,21.77 3,0 8.828,0 17.656,0 z"/>
<path id="path130" style="clip-rule:evenodd;fill-rule:nonzero;stroke-linejoin:round;stroke-miterlimit:1.41420996" d="m 212.15911,199.83329 c 0.257,0.429 0.6,0.771 0.857,1.114 1.114,1.457 2.657,2.743 4.457,3.686 1.457,0.685 3.085,1.028 4.8,1.028 0.085,0 0.257,0 0.428,0 1.8,0.086 3.514,-0.257 5.143,-1.028 1.628,-0.6 3.171,-1.629 4.457,-2.914 1.285,-1.286 2.228,-2.743 2.914,-4.457 0.685,-1.543 1.028,-3.343 1.028,-5.314 0.086,-1.715 -0.257,-3.429 -1.028,-5.057 -0.6,-1.629 -1.629,-3.171 -2.914,-4.457 -1.286,-1.286 -2.743,-2.229 -4.457,-2.914 -1.115,-0.515 -2.572,-0.772 -4.2,-0.772 -0.172,0 -0.343,0 -0.429,0 -2.657,0.086 -4.714,0.429 -5.999,1.2 -3.429,1.8 -5.143,3.857 -5.143,6.171 0,3 0,7.629 0.086,13.714 z m 0,8.314 c -0.086,3.343 -0.086,10.028 -0.086,20.056 -1.286,0 -4.028,0 -8.057,0 v -54.769 c 2.657,0 5.4,0 8.057,0 0.086,1.286 0.086,2.4 0.086,3.257 0.857,-1.114 2.314,-2.142 4.457,-3.085 2.4,-1.029 4.971,-1.543 7.714,-1.543 2.657,0 5.228,0.514 7.628,1.543 2.485,1.028 4.714,2.485 6.514,4.371 1.971,1.886 3.428,4.028 4.371,6.428 1.028,2.486 1.543,4.971 1.543,7.543 0,0.085 0,0.085 0,0.171 0,2.657 -0.515,5.228 -1.543,7.714 -1.029,2.486 -2.486,4.628 -4.371,6.428 -1.886,1.972 -4.029,3.429 -6.514,4.371 -2.486,1.029 -5.057,1.543 -7.628,1.543 -2.657,-0.085 -5.229,-0.6 -7.714,-1.543 -1.372,-0.514 -2.829,-1.371 -4.457,-2.485 z"/>
<path id="path132" style="clip-rule:evenodd;fill-rule:nonzero;stroke-linejoin:round;stroke-miterlimit:1.41420996" d="m 271.04211,180.46329 c 0,-0.086 -0.686,-0.172 -2.143,-0.429 -2.743,-0.086 -5.228,0.857 -7.371,2.828 -0.857,0.772 -1.543,1.886 -2.057,3.343 -0.343,1.371 -0.515,2.829 -0.6,4.457 0,4.543 0,11.399 0,20.399 -1.286,0 -3.943,0 -7.971,0 0,-6.257 0,-18.856 -0.086,-37.627 1.286,0 3.943,0 7.8,0 0.085,0.772 0.085,2.4 0.085,4.8 0,0.514 0,1.543 -0.085,3.171 1.028,-4.199 3.085,-6.856 6.085,-7.971 1.2,-0.343 2.4,-0.514 3.686,-0.514 0.857,-0.086 1.714,0 2.657,0.171 0,1.629 0,4.115 0,7.372 z"/>
<path id="path134" style="clip-rule:evenodd;fill:#005184;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41420996" d="m 277.47011,163.23529 c 0,-1.372 0.514,-2.4 1.457,-3.171 0.943,-0.772 1.971,-1.2 3.085,-1.2 0.086,0 0.172,0 0.258,0 1.114,0 2.057,0.342 2.999,1.028 0.943,0.771 1.372,1.8 1.372,3.257 0,1.457 -0.429,2.571 -1.372,3.428 -0.942,0.858 -2.057,1.286 -3.257,1.286 -1.114,0 -2.142,-0.428 -3.085,-1.2 -0.943,-0.771 -1.457,-1.971 -1.457,-3.428 z"/>
<path style="clip-rule:evenodd;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41420996" id="path136" d="m 278.15611,173.34929 c 1.371,0 4.028,0 8.056,0 0,6.342 0,18.942 0,37.883 -1.285,0 -3.942,0 -7.885,0 0,-6.256 -0.086,-18.941 -0.171,-37.883 z"/>
<path id="path138" style="clip-rule:evenodd;fill-rule:nonzero;stroke-linejoin:round;stroke-miterlimit:1.41420996" d="m 295.55511,146.26429 v 64.797 c 1.285,0 3.942,0 7.885,0 0,-10.799 0,-32.398 0,-64.797 -1.286,0 -3.943,0 -7.885,0 z"/>
<path id="path144" style="clip-rule:evenodd;fill:#005184;fill-rule:nonzero;stroke-linejoin:round;stroke-miterlimit:1.41420996" d="m 79.90511,45.008286 c 0.902,0.305 0.903,0.306 1.74,0.76 0,0 2.36,1.6 3.541,2.399 16.192,11.056 46.905,36.807 46.905,36.807 l -0.62,0.933 c 0,0 -30.962,-17.269 -47.812,-25.837 -0.154,2.104 -0.309,4.208 -0.465,6.312 l -0.126,1.689 c -0.635,7.993 -1.295,15.97 -2,23.945 l -0.096,1.076 c -0.824,8.583004 -1.124,17.369004 -3.069,25.573004 -1.802,7.601 -10.27,13.477 -15.485,20.114 -10.856,13.816 -19.361,29.582 -21.64,47.603 -2.579,20.389 5.773,40.853 21.062,55.815 5.92,5.794 12.534,10.853 19.323,15.617 l -3.768,5.852 c -20.581,-12.139 -40.182,-28.618 -47.181,-51.981 -6.615,-22.081 -1.608,-47.917 10.144,-67.278 6.689,-11.02 14.834,-21.098 23.413,-30.201 0,0 0.585,-2.521 0.874,-4.27 3.14,-19.016004 5.383,-38.057004 7.92,-57.227004 l 0.274,-2.074 0.28,-1.686 c 0.307,-0.8 0.337,-1.033 0.841,-1.737 1.119,-1.562 2.062,-2.818 5.945,-2.204 z"/>
<path id="path146" style="clip-rule:evenodd;fill:#005184;fill-rule:nonzero;stroke-linejoin:round;stroke-miterlimit:1.41420996" d="m 300.65411,44.858286 c 2.74,0.486 2.778,0.936 3.448,1.587 2.555,2.484 2.191,7.238 2.75,11.471 2.467,18.612 4.172,37.353 7.871,55.935004 0,0 3.607,4.013 6.264,7.099 11.064,12.849 21.019,26.411 26.284,43.975 6.27,20.92 3.585,41.82 -7.633,60.315 -9.349,15.414 -24.268,26.668 -39.964,35.962 l -0.593,-1.853 c 17.279,-12.08 34.133,-26.972 39.318,-48.24 3.677,-15.083 -0.809,-32.515 -6.571,-47.292 -5.094,-13.065 -14.589,-24.209 -23.233,-34.394 -1.789,-2.107 -3.603,-4.192 -5.472,-6.229 0,0 -2.204,-3.069 -2.806,-6.739 -2.582,-15.749 -3.416,-31.540004 -4.699,-47.326004 0,0 -0.34,-4.424 -0.589,-7.754 l -0.098,-1.322 -30.582,18.428 -15.221,9.11 -0.801,0.477 -3.955,-6.151 0.767,-0.531 14.605,-10.067 37.28,-25.534 c 0,0 1.172,-0.939 3.63,-0.927 z m 14.362,70.312004 c 0.178,0.639 -0.049,-0.186 0,0 z"/>
</g>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:50.63063431px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.10960984px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="110.04511"
y="98.826035"
id="text861"><tspan
sodipodi:role="line"
id="tspan859"
x="110.04511"
y="98.826035"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:50.63063431px;font-family:Baumans;-inkscape-font-specification:'Baumans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:2.10960984px">converse<tspan
style="fill:#a2a2a2;fill-opacity:1;stroke-width:2.10960984px"
id="tspan867">.js</tspan></tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:18.49652481px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.77068853px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="124.58434"
y="128.44286"
id="text865"><tspan
sodipodi:role="line"
id="tspan863"
x="124.58434"
y="128.44286"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:18.49652481px;font-family:Muli;-inkscape-font-specification:'Muli, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#484848;fill-opacity:1;stroke-width:0.77068853px">messaging freedom</tspan></text>
</svg>

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

65
logo/mailbox.svg Normal file
View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.0.2, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="150px" height="94px" viewBox="0 0 150 94" enable-background="new 0 0 150 94" xml:space="preserve">
<defs>
</defs>
<g>
<defs>
<rect id="SVGID_1_" width="150" height="94.337"/>
</defs>
<clipPath id="SVGID_2_">
<use xlink:href="#SVGID_1_" overflow="visible"/>
</clipPath>
<path clip-path="url(#SVGID_2_)" fill="#76BC21" d="M126.282,74.147v13.759c0,0.299,0.148,0.448,0.448,0.448h2.572
c0.299,0,0.448-0.149,0.448-0.448V76.003c0.569-0.24,1.556-0.419,2.632-0.419c0.809,0,1.675,0,2.423,0.12
c0.3,0.059,0.479-0.09,0.479-0.359V73.19c0-0.238-0.119-0.419-0.388-0.447c-1.138-0.181-2.124-0.24-3.052-0.24
c-1.825,0-3.709,0.389-5.233,1.137C126.372,73.729,126.282,73.909,126.282,74.147 M112.913,78.664c0-1.975,1.166-3.05,3.32-3.05
c2.123,0,3.319,1.075,3.319,3.05v4.008c0,1.914-1.196,2.931-3.319,2.931c-2.154,0-3.32-1.017-3.32-2.931V78.664z M109.414,78.664
v4.008c0,3.709,2.691,6.042,6.819,6.042c4.127,0,6.818-2.333,6.818-6.042v-4.008c0-3.769-2.691-6.161-6.818-6.161
C112.105,72.503,109.414,74.896,109.414,78.664 M103.684,85.287v2.588c0,0,0,0.439,0.441,0.439h2.587c0,0,0.441,0,0.441-0.439
v-2.588c0,0,0-0.441-0.441-0.441h-2.587C104.125,84.846,103.684,84.846,103.684,85.287 M87.422,87.816
c-0.179,0.329-0.059,0.538,0.299,0.538h3.142c0.238,0,0.419-0.09,0.538-0.299l2.99-5.085l2.991,5.085
c0.12,0.209,0.299,0.299,0.538,0.299h3.171c0.329,0,0.448-0.209,0.27-0.538l-4.815-7.237l4.546-7.208
c0.179-0.271,0.03-0.51-0.299-0.51h-3.021c-0.239,0-0.42,0.12-0.539,0.3l-2.842,4.995l-2.841-4.995c-0.12-0.18-0.299-0.3-0.539-0.3
h-3.02c-0.329,0-0.479,0.239-0.299,0.51l4.546,7.208L87.422,87.816z M47.375,67.419v15.493c0,3.647,1.764,5.802,4.995,5.802
c0.598,0,1.196-0.03,1.704-0.09c0.24-0.03,0.329-0.239,0.329-0.479v-2.214c0-0.299-0.149-0.448-0.448-0.448
c-0.389,0.03-0.778,0.061-1.137,0.061c-1.346,0-1.974-0.778-1.974-2.752V67.419c0-0.299-0.149-0.449-0.448-0.449h-2.573
C47.524,66.97,47.375,67.12,47.375,67.419 M40.227,73.281v14.625c0,0.299,0.179,0.448,0.449,0.448h2.602
c0.269,0,0.418-0.149,0.418-0.448V73.281c0-0.27-0.149-0.42-0.418-0.42h-2.602C40.406,72.861,40.227,73.012,40.227,73.281
M40.226,67.408v2.588c0,0,0,0.439,0.44,0.439h2.588c0,0,0.441,0,0.441-0.439v-2.588c0,0,0-0.44-0.441-0.44h-2.588
C40.666,66.968,40.226,66.968,40.226,67.408 M27.127,83.688c0-1.226,0.897-1.974,3.141-1.974c0.927,0,2.093,0.12,2.901,0.239v3.38
c-0.748,0.18-1.885,0.358-2.871,0.358C28.473,85.692,27.127,85.095,27.127,83.688 M23.628,83.719c0,3.739,3.2,4.995,6.67,4.995
c2.213,0,4.456-0.419,6.011-0.897c0.21-0.09,0.329-0.27,0.329-0.509v-8.732c0-4.218-2.512-6.072-6.221-6.072
c-2.423,0-4.426,0.598-5.862,1.585c-0.15,0.12-0.15,0.27,0,0.509l1.196,1.824c0.15,0.24,0.389,0.269,0.599,0.12
c0.957-0.568,2.332-0.957,3.828-0.957c2.213,0,2.991,0.896,2.991,3.021v0.568c-0.898-0.12-2.004-0.239-2.991-0.239
C26.35,78.934,23.628,80.459,23.628,83.719 M0,74.208v13.698c0,0.299,0.15,0.448,0.449,0.448h2.572
c0.299,0,0.448-0.149,0.448-0.448V75.942c0.599-0.18,1.376-0.328,2.393-0.328c1.944,0,2.961,0.957,2.961,3.14v9.152
c0,0.299,0.18,0.448,0.449,0.448h2.572c0.299,0,0.449-0.149,0.449-0.448v-9.093c0-0.896-0.15-1.705-0.389-2.423
c0.777-0.508,1.645-0.747,2.632-0.747c2.153,0,3.08,1.166,3.08,3.11v9.152c0,0.299,0.15,0.448,0.419,0.448h2.602
c0.269,0,0.419-0.149,0.419-0.448v-9.032c0-4.188-2.692-6.371-6.43-6.371c-1.735,0-3.021,0.449-4.517,1.376
c-1.106-0.867-2.572-1.376-4.337-1.376c-1.884,0-3.768,0.449-5.413,1.167C0.09,73.789,0,73.969,0,74.208 M38.766,32.55
l24.153-16.543V0H5.841C5.841,0,0,0,0,5.84V6L38.766,32.55z M5.841,56.86h57.078V24.5l-22.62,15.422
c-1.609,1.096-3.212-0.007-3.212-0.007L0,14.399v36.622C0,51.021,0,56.86,5.841,56.86 M66.217,82.164
c0,2.542-1.286,3.438-3.439,3.438c-1.017,0-2.094-0.119-2.812-0.418V76.36c0.748-0.478,1.735-0.776,2.872-0.776
c2.153,0,3.379,0.987,3.379,3.26V82.164z M69.747,82.134v-3.29c0-3.888-2.782-6.341-6.551-6.341c-1.196,0-2.303,0.269-3.23,0.658
v-5.742c0-0.299-0.149-0.449-0.448-0.449h-2.572c-0.3,0-0.449,0.15-0.449,0.449v19.71c0,0.269,0.09,0.418,0.359,0.508
c1.764,0.658,4.067,1.077,6.011,1.077C66.815,88.714,69.747,86.68,69.747,82.134 M79.287,75.614c2.124,0,3.32,1.075,3.32,3.05
v4.008c0,1.914-1.196,2.931-3.32,2.931c-2.153,0-3.32-1.017-3.32-2.931v-4.008C75.967,76.689,77.134,75.614,79.287,75.614
M79.287,72.503c-4.127,0-6.819,2.393-6.819,6.161v4.008c0,3.709,2.692,6.042,6.819,6.042c4.128,0,6.819-2.333,6.819-6.042v-4.008
C86.106,74.896,83.415,72.503,79.287,72.503 M136.852,56.86H150V20.354C150,4.709,141.719,0,129.337,0
c-6.5,0-12.005,1.437-16.081,3.066C111.163,1.763,107.924,0,100.212,0c-6.853,0-17.63,2.3-21.29,5.095V56.86h12.997V12.372
c3.037-0.74,5.101-1.31,8.449-1.285c5.256,0.039,7.397,2.31,7.554,9.618V56.86h12.966l-0.078-36.959
c0-5.215-1.013-7.529-1.013-7.529c2.688-0.895,5.255-1.285,9.034-1.285c5.918,0,7.826,2.453,8.059,9.773L136.852,56.86z
M146.531,84.107c-0.569,0.479-1.825,0.748-2.961,0.748c-1.825,0-3.29-0.777-3.29-3.141v-2.811c0-2.572,1.404-3.29,3.469-3.29
c0.897,0,2.153,0.118,2.782,0.328V84.107z M150,87.368v-13.19c0-0.239-0.09-0.419-0.329-0.508
c-1.615-0.688-3.769-1.167-5.981-1.167c-3.799,0-6.909,1.705-6.909,6.401v2.811c0,4.217,2.931,6.191,6.461,6.191
c1.076,0,2.361-0.239,3.318-0.658c0.091,3.021-0.986,4.008-3.229,4.008c-1.555,0-2.931-0.538-4.037-1.346
c-0.24-0.18-0.449-0.119-0.599,0.12l-1.257,1.854c-0.148,0.269-0.148,0.449,0.091,0.598c1.585,1.228,3.38,1.855,5.832,1.855
C148.086,94.337,150,91.795,150,87.368"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

@ -2,7 +2,7 @@
"short_name": "Converse",
"name": "Converse Chat",
"description": "Messaging Freedom",
"version": "7.0.0",
"version": "10.1.6",
"categories": ["social"],
"icons": [
{

View File

@ -4,6 +4,7 @@
<title>Converse.js | Mobile</title>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Converse: An XMPP chat client which can be integrated into any website" />
<meta name="author" content="JC Brand" />
@ -18,9 +19,9 @@
<script type="text/javascript" src="analytics.js"></script>
<!-- *********************************************************************** -->
<link type="text/css" rel="stylesheet" media="screen" href="https://cdn.conversejs.org/7.0.0/dist/converse.min.css" />
<link type="text/css" rel="stylesheet" media="screen" href="https://cdn.conversejs.org/10.1.6/dist/converse.min.css" />
<script src="https://cdn.conversejs.org/3rdparty/libsignal-protocol.min.js"></script>
<script src="https://cdn.conversejs.org/7.0.0/dist/converse.min.js"></script>
<script src="https://cdn.conversejs.org/10.1.6/dist/converse.min.js"></script>
</head>
<body id="page-top" data-spy="scroll" class="converse-website">
@ -240,11 +241,9 @@
<h2>Converse is supported by:</h2>
<ul >
<li><a href="https://www.keycdn.com?utm_source=conversejs" target="_blank" rel="noopener"><img style="height: 3em" src="/logo/keycdn.svg" alt="KeyCDN"></a></li>
<li><a href="https://wikisuite.org/?utm_source=conversejs" target="_blank" rel="noopener"><img style="height: 4em" src="/logo/wikisuite-white.png" alt="WikiSuite"></a></li>
<li><a href="https://weblate.org?utm_source=conversejs" target="_blank" rel="noopener"><img style="height: 2.6em" src="/logo/weblate-button.svg" alt="Weblate"></a></li>
<li><a href="https://www.codefirst.co.uk?utm_source=conversejs" target="_blank" rel="noopener"><img style="width: 12em; padding-top: 0.5em" src="/logo/codefirst.png" alt="Codefirst"></a></li>
<li><a href="https://www.b1-systems.de?utm_source=conversejs" target="_blank" rel="noopener"><img style="height: 5em" src="/logo/b1-systems.svg" alt="B1 Systems"></a></li>
<li><a href="https://blokt.com?utm_source=conversejs" target="_blank" rel="noopener"><img style="width: 12em" src="/logo/blokt.png" alt="Blokt Crypto & Privacy"></a></li>
<li><a href="https://primesound.org/?utm_source=conversejs" target="_blank" rel="noopener"><img style="width: 10em" src="/media/logos/primesound.png" alt="Prime Sound"></a></li>
</ul>
</div>

35947
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,35 +1,46 @@
{
"name": "converse.js",
"version": "7.0.0",
"version": "10.1.6",
"description": "Browser based XMPP chat client",
"browser": "dist/converse.js",
"module": "src/converse.js",
"module": "src/index.js",
"workspaces": [
"src/headless"
],
"files": [
"CHANGES.md",
"LICENSE.txt",
"README.md",
"COPYRIGHT",
"dist/",
"locale/",
"sass/",
"sounds/",
"src/*.js",
"src/utils/*.js",
"src/templates/*.html",
"src/templates/*.svg",
"src/headless/"
"docs/**/*.md",
"docs/**/*.rst",
"sass/**/*.scss",
"src/**/*.html",
"src/**/*.js",
"src/**/*.json",
"src/**/*.md",
"src/**/*.po",
"src/**/*.pot",
"src/**/*.scss",
"src/**/*.svg",
"src/**/*.txt",
"3rdparty/*.js"
],
"scripts": {
"serve": "webpack-dev-server --config webpack.serve.js",
"build": "webpack --config webpack/webpack.build.js",
"lint": "eslint src/**/*.js",
"test": "karma start karma.conf",
"cdn": "ASSET_PATH=https://cdn.conversejs.org/dist/ npm run build",
"clean": "rm -rf node_modules dist *.zip src/headless/dist src/headless/node_modules",
"headless": "webpack --config webpack.headless.js",
"nodeps": "webpack --config webpack.nodeps.js",
"cdn": "ASSET_PATH=https://cdn.conversejs.org/dist/ npm run dev && ASSET_PATH=https://cdn.conversejs.org/dist/ npm run build",
"prod": "webpack --config webpack.prod.js",
"build": "npm run dev && npm run prod",
"dev": "webpack --config webpack.dev.js",
"watch": "webpack --watch --config webpack.dev.js",
"lerna": "lerna bootstrap --hoist --ignore-scripts",
"prepare": "npm run lerna && npm run build"
"dev": "webpack --config webpack/webpack.build.js --mode=development",
"headless": "webpack --config webpack/webpack.headless.js",
"headless-dev": "webpack --config webpack/webpack.headless.js --mode=development",
"nodeps": "webpack --config webpack/webpack.nodeps.js",
"serve": "webpack serve --config webpack/webpack.serve.js",
"watch": "webpack --watch --config webpack/webpack.build.js --mode=development",
"types": "tsc --declaration --emitDeclarationOnly --allowJs",
"check:types": "tsc --noEmit"
},
"repository": {
"type": "git",
@ -56,68 +67,70 @@
"browser": "*"
},
"devDependencies": {
"@babel/cli": "^7.10.3",
"@babel/core": "^7.10.5",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.1",
"@babel/plugin-proposal-optional-chaining": "^7.12.1",
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/preset-env": "^7.10.2",
"@babel/cli": "^7.17.10",
"@babel/core": "^7.18.5",
"@babel/preset-env": "^7.18.2",
"@converse/headless": "file:src/headless",
"@fortawesome/fontawesome-free": "5.14.0",
"autoprefixer": "^9.8.4",
"babel-eslint": "^10.1.0",
"babel-loader": "^8.1.0",
"bootstrap": "^4.3.1",
"bootstrap.native": "^2.0.27",
"@typescript-eslint/eslint-plugin": "^5.48.0",
"autoprefixer": "^10.4.5",
"babel-loader": "^9.1.0",
"bootstrap.native-loader": "2.0.0",
"clean-css-cli": "^4.3.0",
"copy-webpack-plugin": "^6.0.2",
"css-loader": "^3.5.3",
"dayjs": "1.8.30",
"eslint": "^7.3.0",
"eslint-plugin-lodash": "^7.1.0",
"exports-loader": "^0.7.0",
"fast-text-encoding": "^1.0.2",
"favico.js-slevomat": "^0.3.11",
"file-loader": "^6.0.0",
"haunted": "^4.7.0",
"html-webpack-plugin": "^4.3.0",
"http-server": "^0.12.3",
"imports-loader": "^0.8.0",
"clean-css-cli": "^5.6.2",
"copy-webpack-plugin": "^11.0.0",
"css-loader": "^6.7.1",
"eslint": "^8.21.0",
"fast-text-encoding": "^1.0.3",
"html-webpack-plugin": "^5.3.2",
"http-server": "^14.1.0",
"imports-loader": "^4.0.0",
"install": "^0.13.0",
"jasmine": "^3.5.0",
"jed": "1.1.1",
"jsdoc": "^3.6.4",
"karma": "^5.1.0",
"karma-chrome-launcher": "^3.1.0",
"jsdoc": "^4.0.0",
"karma": "^6.3.19",
"karma-chrome-launcher": "^3.1.1",
"karma-cli": "^2.0.0",
"karma-jasmine": "^3.1.1",
"karma-jasmine-html-reporter": "^1.5.4",
"karma-webpack": "^4.0.2",
"lerna": "^3.22.1",
"lit-element": "^2.3.1",
"lit-html": "^1.2.1",
"lodash-template-webpack-loader": "jcbrand/lodash-template-webpack-loader",
"mini-css-extract-plugin": "^0.9.0",
"minimist": "^1.2.3",
"node-sass": "^4.14.1",
"npm": "^6.14.6",
"po-loader": "^0.5.0",
"po2json": "^1.0.0-beta",
"postcss-clean": "^1.1.0",
"postcss-loader": "^3.0.0",
"prettierx": "^0.12.1",
"run-headless-chromium": "^0.1.1",
"sass-loader": "^8.0.2",
"sinon": "^9.0.2",
"sizzle": "^2.3.5",
"style-loader": "^0.23.1",
"urijs": "^1.19.2",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.12",
"webpack-dev-server": "^3.11.0",
"webpack-merge": "^5.0.9",
"xss": "^1.0.7"
"karma-jasmine": "^5.0.0",
"karma-jasmine-html-reporter": "^2.0.0",
"karma-webpack": "^5.0.0",
"mini-css-extract-plugin": "^2.6.0",
"minimist": "^1.2.6",
"po-loader": "0.7.0",
"po2json": "^1.0.0-beta-3",
"postcss": "^8.4.16",
"postcss-loader": "^7.0.1",
"prettierx": "^0.19.0",
"sass": "^1.51.0",
"sass-loader": "^13.1.0",
"style-loader": "^3.1.0",
"tsc": "^2.0.4",
"typescript": "^4.9.5",
"typescript-eslint-parser": "^22.0.0",
"uglify-js": "^3.17.4",
"webpack": "^5.86.0",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.8.1",
"webpack-merge": "^5.8.0"
},
"dependencies": {}
"dependencies": {
"@converse/openpromise": "^0.0.1",
"@converse/skeletor": "^0.0.8",
"bootstrap": "^4.6.0",
"bootstrap.native": "^2.0.27",
"client-compress": "^2.2.2",
"dayjs": "^1.11.8",
"dompurify": "^2.3.1",
"favico.js-slevomat": "^0.3.11",
"gifuct-js": "^2.1.2",
"jed": "1.1.1",
"lit": "^2.4.0",
"localforage-webextensionstorage-driver": "^3.0.0",
"lodash-es": "^4.17.21",
"pluggable.js": "^3.0.1",
"sizzle": "^2.3.5",
"sprintf-js": "^1.1.2",
"strophe.js": "^1.6.2",
"urijs": "^1.19.10"
},
"resolutions": {
"autoprefixer": "10.4.5"
}
}

View File

@ -2,6 +2,5 @@
module.exports = {
plugins: [
require('autoprefixer'),
require('postcss-clean')
]
}

View File

@ -1 +1,3 @@
zc.buildout==2.13.2
Sphinx==4.5.0
docutils==0.17.1
sphinx-bootstrap-theme==0.8.1

View File

@ -1,633 +0,0 @@
#conversejs {
.chatbox-navback {
display: none;
}
.flyout {
position: absolute;
@media screen and (max-height: $mobile-landscape-height) {
border-radius: 0;
}
@media screen and (max-width: $mobile-portrait-length) {
border-radius: 0;
}
@media screen and (max-height: $mobile-landscape-height) {
bottom: 0;
}
@media screen and (max-width: $mobile-portrait-length) {
bottom: 0;
}
}
.chatbox-btn {
border-radius: 25%;
border: none;
cursor: pointer;
font-size: var(--chatbox-button-size);
margin: 0 0.2em;
padding: 0 0 0 0.5em;
text-decoration: none;
&:active {
position: relative;
top: 1px;
}
}
.chat-head {
display: flex;
flex-direction: row;
color: #ffffff;
font-size: 100%;
margin: 0;
padding: 0;
position: relative;
&.chat-head-chatbox {
background-color: var(--chat-head-color);
}
.avatar {
margin-right: 0.5em;
}
.chat-head__desc {
color: var(--chat-head-color-lighten-50-percent);
font-size: var(--font-size-small);
margin: 0;
overflow: hidden;
padding: 0.5rem 1rem 0.5rem 1rem;
text-overflow: ellipsis;
width: 100%;
max-height: 5em;
}
.chatbox-title {
padding: 0.75rem 1rem 0 1rem;
display: flex;
flex-direction: row;
justify-content: space-between;
width: 100%;
}
.chatbox-title--no-desc {
padding: 0.75rem 1rem;
}
.chatbox-title--row {
display: flex;
flex-direction: row;
overflow: hidden;
}
.chatbox-title__text {
overflow: hidden;
text-overflow: ellipsis;
}
.chatbox-title__buttons {
display: flex;
flex-direction: row-reverse;
flex-wrap: nowrap;
padding: 0;
}
a, a:visited, a:hover, a:not([href]):not([tabindex]) {
&.chatbox-btn {
&.fa,
&.fas,
&.far {
color: white;
&.button-on:before {
padding: 0.2em;
background-color: var(--chat-head-text-color);
color: var(--chat-head-color);
}
}
}
}
.chatbox-btn {
color: white;
&.fa, &.far, &.fas {
color: white;
}
&:active {
position: relative;
top: 1px;
}
&.button-on:before {
border-radius: 5%;
background-color: var(--chat-head-text-color);
color: var(--chat-head-color);
}
}
}
.chatbox {
text-align: left;
margin: 0 var(--chat-gutter);
@media screen and (max-height: $mobile-landscape-height) {
margin: 0;
width: var(--mobile-chat-width);
}
@media screen and (max-width: $mobile-portrait-length) {
margin: 0;
width: var(--mobile-chat-width);
}
.box-flyout {
display: flex;
flex-direction: column;
justify-content: space-between;
box-shadow: 1px 3px 5px 3px rgba(0, 0, 0, 0.4);
z-index: 2;
overflow: hidden;
width: 100%;
@media screen and (max-height: $mobile-landscape-height) {
height: var(--mobile-chat-height);
width: var(--mobile-chat-width);
height: var(--fullpage-chat-height);
}
@media screen and (max-width: $mobile-portrait-length) {
height: var(--mobile-chat-height);
width: var(--mobile-chat-width);
height: var(--fullpage-chat-height);
}
}
.chat-title {
display: var(--heading-display);
font-family: var(--heading-font);
color: var(--heading-color);
display: block;
line-height: var(--line-height-large);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
&.groupchat {
padding-right: var(--chatroom-head-title-padding-right);
}
a {
color: var(--chat-head-text-color);
width: 100%;
}
}
.chat-body {
display: flex;
flex-direction: column;
justify-content: space-between;
background-color: var(--chat-head-color);
border-bottom-left-radius: var(--chatbox-border-radius);
border-bottom-right-radius: var(--chatbox-border-radius);
@media screen and (max-height: $mobile-landscape-height) {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
@media screen and (max-width: $mobile-portrait-length) {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
border-top: 0;
p {
color: var(--text-color);
font-size: var(--message-font-size);
margin: 0;
padding: 5px;
}
}
.new-msgs-indicator {
position: relative;
width: 100%;
cursor: pointer;
background-color: var(--chat-head-color);
color: var(--light-background-color);
padding: 0.5em;
font-size: 0.9em;
text-align: center;
z-index: 20;
white-space: nowrap;
margin-bottom: 0.25em;
}
.chat-content {
background-color: var(--chat-content-background-color);
border: 0;
color: var(--text-color);
font-size: var(--message-font-size);
height: 100%;
line-height: 1.3em;
overflow: hidden;
padding: 0;
display: flex;
flex-direction: column;
justify-content: space-between;
converse-chat-content {
display: flex;
flex-direction: column;
height: 100%;
justify-content: space-between;
}
converse-chat-message {
.spinner {
width: 100%;
overflow-y: hidden;
}
}
.chat-content__help {
border-top: 1px solid var(--chat-head-color);
max-height: 100%;
.close-chat-help {
svg {
fill: var(--chat-head-color);
}
}
converse-chat-help {
height: 100%;
overflow-y: auto;
display: block;
padding: 0.5em 0;
}
.close-chat-help {
float: right;
padding-right: 1em;
cursor: pointer;
color: var(--chat-content-background-color);
}
}
.chat-content__messages {
overflow-x: hidden;
overflow-y: auto;
height: 100%;
}
.chat-content__notifications {
height: 1.7em;
white-space: pre;
background-color: var(--chat-content-background-color);
color: var(--subdued-color);
font-size: 90%;
font-style: italic;
line-height: var(--line-height-small);
padding: 0 1em 0.3em;
&:before {
content: " ";
}
}
video {
width: 100%
}
progress {
margin: 0.5em 0;
width: 100%
}
}
.chat-content-sendbutton {
height: calc(100% - (var(--chat-textarea-height) + var(--send-button-height) + 2 * var(--send-button-margin)));
}
.dropdown { /* status dropdown styles */
background-color: var(--light-background-color);
dd {
margin: 0;
padding: 0;
position: relative;
}
}
.sendXMPPMessage {
-moz-background-clip: padding;
-webkit-background-clip: padding-box;
border-bottom-radius: var(--chatbox-border-radius);
background-clip: padding-box;
background-color: white;
border: 0;
margin: 0;
padding: 0;
@media screen and (max-height: $mobile-landscape-height) {
width: 100%;
}
@media screen and (max-width: $mobile-portrait-length) {
width: 100%;
}
.suggestion-box__results {
&:after {
display: none;
}
}
.spoiler-hint {
width: 100%;
}
.chat-textarea, input {
&:active, &:focus{
outline-color: var(--chat-head-color);
}
&.correcting {
background-color: var(--chat-correcting-color);
}
}
.chat-textarea {
color: var(--chat-textarea-color);
background-color: var(--chat-textarea-background-color);
border-top-left-radius: 0;
border-top-right-radius: 0;
border-bottom-radius: var(--chatbox-border-radius);
padding-left: 0.5em;
padding-right: 4.5em;
padding-top: 0.5em;
padding-bottom:0.5em;
width: 100%;
border: none;
min-height: var(--chat-textarea-height);
margin-bottom: -4px; // Not clear why this is necessar :(
resize: none;
&.spoiler {
height: 42px;
}
}
}
.dragresize {
background: transparent;
border: 0;
margin: 0;
position: absolute;
top: 0;
z-index: 20;
&-top {
cursor: n-resize;
height: 5px;
width: 100%;
}
&-left,
&-occupants-left {
cursor: w-resize;
width: 5px;
height: 100%;
left: 0;
}
&-topleft {
cursor: nw-resize;
width: 15px;
height: 15px;
top: 0;
left: 0;
}
}
}
}
/* ******************* Overlay and embedded styles *************************** */
#conversejs.converse-embedded,
#conversejs.converse-overlayed {
.controlbox-head {
padding: 0.5em;
}
.chat-head {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
.chatbox {
min-width: var(--overlayed-chat-width) !important;
width: var(--overlayed-chat-width);
.box-flyout {
min-width: var(--overlayed-chat-width) !important;
width: var(--overlayed-chat-width);
}
}
}
#conversejs.converse-overlayed {
.chat-head, .box-flyout {
border-top-left-radius: var(--chatbox-border-radius);
border-top-right-radius: var(--chatbox-border-radius);
@media screen and (max-height: $mobile-landscape-height) {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
@media screen and (max-width: $mobile-portrait-length) {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
}
.flyout {
bottom: var(--overlayed-chatbox-hover-height);
}
.box-flyout {
height: var(--overlayed-chat-height);
min-height: calc(var(--overlayed-chat-height) / 2);
}
.chat-head {
min-height: var(--overlayed-chat-head-height);
}
.minimized-chats-flyout .chat-head {
cursor: default;
}
.chat-textarea {
max-height: var(--overlayed-max-chat-textarea-height);
}
.chatbox {
.chat-body {
height: calc(100% - var(--overlayed-chat-head-height));
}
.chatbox-title {
padding: 0.5rem 0.75rem 0 0.75rem;
}
.chatbox-title--no-desc {
padding: 0.5rem 0.75rem;
}
converse-dropdown {
.btn--standalone {
padding: 0 0.2em;
margin: 0 0 0 0.5em;
}
}
}
}
@include media-breakpoint-down(sm) {
#conversejs.converse-overlayed {
> .row {
flex-direction: column;
&.no-gutters {
margin: -1em;
}
}
}
}
#conversejs.converse-embedded,
#conversejs.converse-fullscreen {
.flyout {
border-radius: 0;
border:none;
bottom: 0;
}
.chatbox {
margin: 0;
.box-flyout {
box-shadow: none;
overflow: hidden;
}
@include make-col-ready();
@include media-breakpoint-up(md) {
@include make-col(8);
}
@include media-breakpoint-up(lg) {
@include make-col(9);
}
@include media-breakpoint-up(xl) {
@include make-col(10);
}
}
&.converse-singleton {
.flyout {
border: none !important;
}
.chat-head {
padding: 0.5em;
}
.chatbox {
margin: 0;
@include make-col-ready();
@include media-breakpoint-up(md) {
@include make-col(12);
}
@include media-breakpoint-up(lg) {
@include make-col(12);
}
@include media-breakpoint-up(xl) {
@include make-col(12);
}
}
}
}
#conversejs.converse-embedded {
.chat-head {
font-size: var(--font-size-huge);
}
.converse-chatboxes {
z-index: 1031; // One more than bootstrap navbar
position: inherit;
flex-wrap: nowrap;
bottom: auto;
height: 100%;
width: 100%;
margin-left: -15px;
}
.chatbox {
.box-flyout {
bottom: 0;
height: 100%;
min-width: auto;
width: 100%;
}
}
.chat-textarea {
max-height: var(--fullpage-max-chat-textarea-height);
}
}
/* ******************* Fullpage styles *************************** */
#conversejs.converse-fullscreen {
.chatbox-btn {
font-size: var(--fullpage-chatbox-button-size);
margin: 0 0.3em;
}
.chat-head {
font-size: var(--font-size-huge);
}
.chat-textarea {
max-height: var(--fullpage-max-chat-textarea-height);
}
.chatbox {
.box-flyout {
box-shadow: none;
height: var(--fullpage-chat-height);
min-height: calc(var(--fullpage-chat-height) / 2);
width: var(--fullpage-chat-width);
overflow: hidden;
}
.chat-body {
height: inherit;
overflow: hidden;
background-color: var(--chat-head-color);
}
.chat-title {
font-size: var(--font-size-huge);
line-height: var(--line-height-huge);
}
.sendXMPPMessage {
ul {
width: 100%;
}
}
}
}
@include media-breakpoint-down(sm) {
#conversejs:not(.converse-embedded) {
> .row {
flex-direction: row-reverse;
}
#converse-login-panel {
.converse-form {
padding: 3em 2em 3em;
}
}
.chatbox {
width: calc(100% - 50px);
.row {
.box-flyout {
left: 50px;
bottom: 0;
height: var(--fullpage-chat-height);
box-shadow: none;
}
}
}
}
#conversejs.converse-mobile,
#conversejs.converse-overlayed,
#conversejs.converse-fullscreen {
.chatbox {
.box-flyout {
.chatbox-navback {
margin: auto 0;
margin-right: 1em;
display: flex;
.fa-arrow-left {
&:before {
color: white;
}
}
}
}
}
}
}

View File

@ -1,545 +0,0 @@
#conversejs.converse-embedded,
#conversejs {
.badge--muc {
background-color: var(--groupchats-header-color);
}
.add-chatroom {
input[type="submit"],
input[type="button"] {
margin: 0.3em 0;
}
}
#room-details-modal {
.features-list {
margin-left: 1em;
}
}
.chatroom-features {
width: 100%;
.features-list {
padding-top: 0;
.feature {
width: 100%;
margin-right: 0.5em;
padding-right: 0;
font-size: 1em;
cursor: help;
.fa {
margin-right: 0.5em;
color: var(--text-color);
}
}
}
}
.chat-head-chatroom {
color: var(--chatroom-head-color);
background-color: var(--chatroom-head-bg-color);
border-bottom: var(--chatroom-head-border-bottom);
.chat-head__desc {
color: var(--chatroom-head-color);
display: var(--chatroom-head-description-display);
a {
color: var(--chatroom-head-description-link-color);
}
&:hover {
button {
display: inline-block;
}
}
}
.chatbox-title {
.btn--transparent {
i {
color: var(--chatroom-head-color);
}
}
.chatbox-title__text--bookmarked {
margin-left: 0.5em;
color: var(--chatroom-head-color);
}
}
.chatbox-title__buttons {
background-color: var(--chatroom-head-bg-color);
}
a, a:visited, a:hover, a:not([href]):not([tabindex]) {
&.chatbox-btn {
&.fa {
color: var(--chat-head-text-color);
&.button-on:before {
color: var(--chatroom-head-button-color);
}
}
}
}
.chatbox-btn {
&.button-on:before {
color: var(--chatroom-head-button-color);
}
}
.chatbox-title__text {
display: var(--heading-display);
font-weight: var(--chatroom-head-title-font-weight);
margin: auto 0;
padding-right: var(--chatroom-head-title-padding-right);
white-space: nowrap;
.chatroom-jid {
font-size: var(--font-size-small);
}
}
}
.empty-history-feedback {
position: relative;
span {
width: 100%;
text-align: center;
position: absolute;
margin-top: 50%;
}
}
.chatroom {
width: var(--chatroom-width);
@media screen and (max-height: $mobile-landscape-height){
width: var(--mobile-chat-width);
}
@media screen and (max-width: $mobile-portrait-length) {
width: var(--mobile-chat-width);
}
.box-flyout {
overflow-y: hidden;
background-color: var(--chatroom-head-bg-color);
width: 100%;
@media screen and (max-height: $mobile-landscape-height) {
height: var(--mobile-chat-height);
width: var(--mobile-chat-width);
height: var(--fullpage-chat-height);
}
@media screen and (max-width: $mobile-portrait-length) {
height: var(--mobile-chat-height);
width: var(--mobile-chat-width);
height: var(--fullpage-chat-height);
}
.chatroom-body {
flex-direction: row;
flex-flow: nowrap;
background-color: white;
border-top: 0;
width: 100%;
overflow: hidden;
.row {
flex-direction: row;
}
.chat-topic {
font-weight: bold;
color: var(--chatroom-head-bg-color);
}
.chat-info {
color: var(--chat-info-color);
line-height: normal;
&.badge {
color: var(--chat-head-text-color);
}
&.chat-msg--retracted {
color: var(--subdued-color);
}
}
.disconnect-container {
margin: 1em;
width: 100%;
h3.disconnect-msg {
padding-bottom: 1em;
}
}
.chat-area {
display: flex;
flex-direction: column;
flex: 0 1 100%;
justify-content: flex-end;
min-width: 25%;
word-wrap: break-word;
.new-msgs-indicator {
background-color: var(--chatroom-head-bg-color);
}
.chat-content {
height: 100%;
}
.chat-content__help {
border-top: 1px solid var(--chatroom-head-bg-color);
.close-chat-help {
svg {
fill: var(--chatroom-head-bg-color);
}
}
}
}
.occupants {
display: flex;
flex-direction: column;
justify-content: space-between;
overflow-x: hidden;
overflow-y: hidden;
vertical-align: top;
background-color: var(--occupants-background-color);
border-left: var(--occupants-border-left);
padding: 0.5em;
max-width: 75%;
min-width: 20%;
flex: 0 0 25%;
.occupants-header {
display: flex;
flex-direction: column;
.hide-occupants {
align-self: flex-end;
cursor: pointer;
font-size: var(--font-size-small);
}
}
.occupants-header--title {
margin-top: 0.5em;
margin-bottom: 0.5em;
display: flex;
flex-direction: row;
}
.fa-user-plus {
margin-right: 0.25em;
}
.occupants-heading {
font-family: var(--heading-font);
color: var(--groupchats-header-color-dark);
padding-left: 0;
margin-right: 1em;
}
.suggestion-box{
ul {
padding: 0;
li {
padding: 0.5em;
}
}
}
ul {
padding: 0;
margin-bottom: 0.5em;
overflow-x: hidden;
overflow-y: auto;
list-style: none;
&.occupant-list {
overflow-y: auto;
flex-basis: 0;
flex-grow: 1;
}
li {
cursor: default;
display: block;
font-size: var(--font-size-small);
overflow: hidden;
padding: 0.25em 0.25em 0.25em 0;
text-overflow: ellipsis;
.fa {
margin-right: 0.5em;
}
&.feature {
font-size: var(--font-size-tiny);
}
&.occupant {
cursor: pointer;
.occupant-nick-badge {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
.occupant-badges {
display: flex;
justify-content: flex-end;
flex-wrap: wrap;
flex-direction: row;
span {
margin-right: 0.25rem;
}
}
}
div.row.no-gutters {
flex-wrap: nowrap;
min-height: 1.5em;
}
.badge {
margin-bottom: 0.125rem;
}
.occupant-status {
display: inline-block;
margin: 0 0.5em 0.125em 0;
width: 0.5em;
height: 0.5em;
&.occupant-online,
&.occupant-chat {
background-color: #1A9707;
}
&.occupant-dnd {
background-color: red;
}
&.occupant-away {
background-color: darkorange;
}
&.occupant-xa {
background-color: orange;
}
&.occupant-offline {
background-color: darkgrey;
}
}
}
}
}
}
.chatroom-form-container {
background-color: white;
border: 0;
color: var(--text-color);
font-size: var(--font-size);
height: 100%;
width: 100%;
overflow-y: auto;
.validation-message {
font-size: 90%;
color: var(--error-color);
}
input[type=button],
input[type=submit] {
margin: 0 0.5em;
}
.button-primary {
background-color: var(--chatroom-head-button-color);
}
}
.chatroom-form {
display: flex;
flex-direction: column;
justify-content: center;
padding: 2em;
}
}
}
.muc-bottom-panel {
height: 3em;
padding: 0.5em;
text-align: center;
font-size: var(--font-size-small);
background-color: var(--chatroom-head-bg-color);
color: white;
&.muc-bottom-panel--nickname {
padding: 0;
height: 16em;
.chatroom-form-container {
.chatroom-form {
padding-top: 2em;
padding-bottom: 0;
}
}
}
}
.sendXMPPMessage {
.suggestion-box__results--above {
bottom: 4.5em;
}
.chat-textarea, input {
&:active, &:focus{
outline-color: var(--chatroom-head-bg-color);
}
&.correcting {
background-color: var(--chatroom-correcting-color);
}
}
.chat-textarea {
border-bottom-right-radius: 0;
}
}
.room-invite {
.invited-contact {
margin: -1px 0 0 -1px;
width: 100%;
border: 1px solid #999;
}
}
}
}
/* ******************* Overlay styles *************************** */
#conversejs.converse-overlayed {
.chatbox {
&.chatroom {
min-width: var(--chatroom-width) !important;
width: var(--chatroom-width);
.box-flyout {
min-width: var(--chatroom-width) !important;
width: var(--chatroom-width);
}
.chatbox-title__text {
@include make-col(7);
}
.chatbox-title__buttons {
@include make-col(5);
}
.chat-head__desc {
font-size: 80%;
margin-bottom: 1em;
}
.chatroom-body {
.occupants {
.occupants-heading {
padding: 0;
}
.occupant-list {
border-bottom: none;
}
ul {
.occupant {
.occupant-nick-badge {
.occupant-badges {
display: none;
}
}
.occupant-status {
margin-top: 6px;
}
}
}
}
.chat-area {
min-width: var(--overlayed-chat-width);
}
}
}
}
}
#conversejs.converse-embedded,
#conversejs.converse-fullscreen,
#conversejs.converse-mobile {
.chatroom {
.box-flyout {
width: 100%;
.chatroom-body {
.chat-area {
&.full {
.new-msgs-indicator {
max-width: 100%;
}
}
}
.occupants {
padding: var(--occupants-padding);
.occupants-heading {
font-size: var(--font-size-large);
}
ul {
&.occupant-list {
li {
font-size: var(--font-size-small);
}
}
}
}
}
}
.room-invite {
span {
.invited-contact {
margin: 0 0 0.5em -1px;
}
}
}
}
}
#conversejs.converse-embedded {
.chatroom {
margin: 0;
width: 100%;
.box-flyout {
.occupants-heading {
font-size: 120%;
}
.chat-content {
.chat-message {
margin: 0.5em;
font-size: 120%;
}
}
.sendXMPPMessage {
.chat-textarea {
padding: 0.5em;
font-size: 110%;
}
}
.chatroom-body {
height: 100%;
.chatroom-form-container {
height: 100%;
position: relative;
}
}
.occupants {
.occupant-list {
padding-left: 0.3em;
}
}
}
}
}
@include media-breakpoint-down(sm) {
#conversejs.converse-mobile,
#conversejs.converse-overlayed,
#conversejs.converse-fullscreen {
.chatbox {
.box-flyout {
.chat-head-chatroom {
.chatbox-navback {
margin-right: 0 !important;
.fa-arrow-left {
&:before {
color: var(--chatroom-head-color);
}
}
}
}
}
}
}
}

View File

@ -1,41 +0,0 @@
#conversejs {
.chat-head-headline {
background-color: var(--headline-head-color);
}
.chatbox.headlines {
.chat-head {
&.chat-head-chatbox {
background-color: var(--headline-head-color);
}
}
.chat-body {
background-color: var(--headline-head-color);
border-radius: var(--chatbox-border-radius);
.chat-message {
color: var(--headline-message-color);
}
}
.chat-content {
height: 100%;
}
}
}
#conversejs.converse-fullscreen {
.chatbox.headlines {
.box-flyout {
background-color: var(--headline-head-color);
}
.chat-head {
&.chat-head-chatbox {
background-color: var(--headline-head-color);
}
}
.flyout {
border: var(--flyout-padding) solid var(--headline-head-color);
border-top: 0.8em solid var(--headline-head-color);
}
}
}

View File

@ -1,90 +0,0 @@
#conversejs.converse-overlayed {
#minimized-chats {
order: 100;
width: var(--minimized-chats-width);
margin-bottom: 0;
border-top-left-radius: var(--chatbox-border-radius);
border-top-right-radius: var(--chatbox-border-radius);
color: var(--inverse-link-color);
margin-right: var(--chat-gutter);
padding: 0;
.badge {
bottom: 8px;
border: 1px solid var(--overlayed-badge-color);
}
#toggle-minimized-chats {
border-top-left-radius: var(--chatbox-border-radius);
border-top-right-radius: var(--chatbox-border-radius);
background-color: var(--link-color);
padding: 1em 0 0 0;
text-align: center;
color: white;
white-space: nowrap;
overflow-y: hidden;
text-overflow: ellipsis;
display: block;
height: 45px;
width: 9em;
}
a.restore-chat {
cursor: pointer;
padding: 1px 0 1px 5px;
color: var(--chat-head-text-color);
line-height: 15px;
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
&:hover {
text-decoration: none;
}
}
a.restore-chat:visited {
color: var(--chat-head-text-color);
}
.minimized-chats-flyout {
flex-direction: column-reverse;
bottom: 45px;
width: var(--minimized-chats-width);
.chat-head {
min-height: 0;
padding: 0.3em;
border-radius: var(--chatbox-border-radius);
height: 35px;
margin-bottom: 0.2em;
width: 100%;
max-width: 9em;
flex-wrap: nowrap;
}
&.minimized {
height: auto;
}
}
.unread-message-count {
font-weight: bold;
background-color: white;
border: 1px solid;
text-shadow: 1px 1px 0 var(--text-shadow-color);
color: var(--warning-color);
border-radius: 5px;
padding: 2px 4px;
font-size: 16px;
text-align: center;
position: absolute;
right: 116px;
bottom: 10px;
}
.unread-message-count-hidden,
.chat-head-message-count-hidden {
display: none;
}
}
}

View File

@ -1,185 +0,0 @@
#conversejs #converse-roster {
text-align: left;
width: 100%;
position: relative;
margin: 0;
height: var(--roster-height);
padding: 0;
overflow: hidden;
// XXX: FIXME
height: calc(100% - 70px);
/* Custom addition for CSP */
#online-count {
display: none;
}
.search-xmpp {
ul {
li.chat-info {
padding-left: 10px;
}
}
}
.roster-filter-form {
width: 100%;
.button-group {
padding: 0.2em;
}
span {
padding: 0.3em;
cursor: pointer;
min-width: 25px;
text-align: center;
}
.roster-filter {
width: 100%;
margin: 0.2em;
font-size: calc(var(--font-size) - 2px);
}
.state-type {
font-size: calc(var(--font-size) - 2px);
width: 100%;
}
}
.roster-contacts {
padding: 0;
margin: 0 0 0.2em 0;
height: 100%;
overflow-x: hidden;
overflow-y: auto;
.roster-group {
border: none;
color: var(--text-color);
font-weight: normal;
text-shadow: 0 1px 0 var(--text-shadow-color);
margin: 0.75em 0 0.75em 0;
.group-toggle {
font-family: var(--heading-font);
display: block;
width: 100%;
padding-top: 0;
padding-bottom: 0.3rem;
}
.group-toggle, .group-toggle .fa {
color: var(--chat-head-color-dark) !important;
&:hover {
color: var(--chat-head-color-darker) !important;
}
}
.current-xmpp-contact {
margin: 0.25em 0;
.chat-status {
vertical-align: middle;
font-size: 0.6em;
margin-right: 0;
margin-left: -0.7em;
margin-bottom: -1.5em;
border-radius: 50%;
border: 2px solid var(--occupants-background-color);
}
.chat-status--offline {
margin-right: 0.8em;
}
.chat-status--online {
color: var(--chat-status-online);
}
.chat-status--busy {
color: var(--chat-status-busy);
}
.chat-status--away {
color: var(--chat-status-away);
}
.chat-status--offline {
display: none;
}
.far.fa-circle,
.fa-times-circle {
color: var(--subdued-color);
}
}
li {
&.requesting-xmpp-contact {
a {
line-height: var(--line-height);
}
.req-contact-name {
padding: 0 0.2em 0 0;
}
}
.open-chat {
margin: 0;
padding: 0;
&.unread-msgs {
font-weight: bold;
.contact-name {
width: 70%;
}
}
.msgs-indicator {
color: white;
background-color: var(--chat-head-color);
opacity: 1;
border-radius: 10%;
padding: 0.2em 0.4em;
font-size: var(--font-size-small);
}
.contact-name {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
padding: 0;
margin: 0;
max-width: 85%;
float: none;
height: 100%;
&.unread-msgs {
max-width: 60%;
}
&.contact-name--offline {
margin-left: 0.7em;
}
}
}
&.odd {
background-color: #DCEAC5;
/* Make this difference */
}
a, span {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.span {
display: inline-block;
}
.decline-xmpp-request {
margin-left: 5px;
}
&:hover {
background-color: var(controlbox-pane-bg-hover-color);
}
}
}
}
span {
&.pending-contact-name {
line-height: var(--line-height);
width: 100%;
}
}
}

View File

@ -1,257 +0,0 @@
$mobile_landscape_height: 450px !default;
$mobile_portrait_length: 480px !default;
#conversejs, #conversejs-bg, .converse-fullscreen {
--subdued-color: #A8ABA1;
--green: #3AA569;
--redder-orange: #E77051;
--orange: #E7A151;
--light-blue: #578EA9;
--lighter-blue: #85B47B;
--chat-status-online: var(--green);
--chat-status-busy: var(--redder-orange);
--chat-status-away: var(--orange);
--brand-heading-color: #387592; // $blue
--completion-light-color: #FFB9A7; // $lightest-red
--completion-normal-color: var(--redder-orange);
--completion-dark-color: #D24E2B; // $dark-red
--link-color: var(--light-blue);
--link-hover-color: #345566;
--link-color-lighten-10-percent: #79a5ba; // lighten($light-blue, 10%)
--dark-link-color: #206485; // $dark-blue
--global-background-color: #397491; // dark blue
--inverse-link-color: white;
--text-shadow-color: #FAFAFA;
--text-color: #666;
--controlbox-text-color: #666;
--text-color-lighten-15-percent: #8c8c8c; // lighten(#666, 15%)
--message-text-color: #555;
--message-receipt-color: var(--green);
--save-button-color: var(--green);
--message-avatar-width: 36px;
--message-avatar-height: 36px;
--chat-textarea-color: #666;
--chat-textarea-background-color: white;
--chat-textarea-height: 60px;
--send-button-height: 27px;
--send-button-margin: 3px;
--inline-action-margin: 0.75em;
--roster-height: 194px;
--flyout-padding: 0.5em;
--chat-correcting-color: var(--chat-head-color-lighten-50-percent);
--chat-head-color-dark: #1E9652;
--chat-head-color-darker: #0E763B;
--chat-head-color-lighten-50-percent: #e7f7ee; // lighten($green, 50%)
--chat-head-color: var(--green);
--chat-head-text-color: white;
--chat-toolbar-btn-color: var(--green);
--chat-toolbar-btn-disabled-color: gray;
--chat-content-background-color: white;
--chat-info-color: var(--chatroom-head-bg-color);
--highlight-color: #DCF9F6;
--highlight-color-darker: #B0E8E2;
--primary-color: var(--light-blue);
--primary-color-dark: #397491;
--secondary-color: #818479; // gray
--secondary-color-dark: #585B51;
--warning-color: var(--orange);
--warning-color-dark: #D2842B;
--danger-color: #D24E2B; // dark-red
--danger-color-dark: #A93415; // darker red
--light-background-color: #FCFDFD;
--error-color: #D24E2B; // dark-red
--info-color: #1E9652; // $dark-green
--button-border-radius: 5px;
--chatbox-border-radius: 4px;
--groupchats-header-color: var(--chatroom-head-bg-color);
--groupchats-header-color-dark: var(--chatroom-head-bg-color-dark);
--controlbox-width: 250px;
--controlbox-head-color: var(--light-blue);
--controlbox-heading-color: inherit;
--controlbox-heading-font-weight: bold;
--controlbox-heading-top-margin: 0.75em;
--controlbox-pane-background-color: white;
--controlbox-pane-bg-hover-color: #eff4f7;
--panel-divider-color: #e7e7e7;
--chat-gutter: 0.5em;
--minimized-chats-width: 130px;
--mobile-chat-width: 100%;
--mobile-chat-height: 400px;
// TODO: figure out a way to concatenate custom properties with strings.
// --font-path: "webfonts/icomoon/fonts/";
--normal-font: "Helvetica", "Arial", sans-serif;
--heading-font: 'Muli', normal;
--branding-font: 'Baumans', cursive;
--heading-display: block;
--heading-color: white;
--chatroom-badge-color: var(--chatroom-head-bg-color);
--chatroom-badge-hover-color: var(--chatroom-head-bg-color-dark);
--chatroom-correcting-color: #fadfd7; // lighten($red, 30%)
--chatroom-head-bg-color-dark: #D24E2B; // $red
--chatroom-head-bg-color: var(--redder-orange);
--chatroom-head-border-bottom: 0px;
--chatroom-head-button-color: var(--chatroom-head-bg-color);
--chatroom-head-color: white;
--chatroom-head-description-display: block;
--chatroom-head-description-link-color: white;
--chatroom-head-title-font-weight: normal;
--chatroom-head-title-padding-right: 0px;
--chatroom-width: 500px;
--muc-toolbar-btn-color: var(--redder-orange);
--muc-toolbar-btn-disabled-color: gray;
--headline-head-color: var(--orange);
--headline-message-color: #D2842B;
--chatbox-button-size: 14px;
--fullpage-chatbox-button-size: 16px;
--font-size-tiny: 10px;
--font-size-small: 12px;
--font-size: 14px;
--font-size-large: 16px;
--font-size-huge: 20px;
--message-font-size: var(--font-size);
--separator-text-color: var(--message-text-color);
--chat-separator-border-bottom: 2px solid var(--chat-head-color);
--chatroom-separator-border-bottom: 2px solid var(--chatroom-head-bg-color);
--chatbox-message-input-border-top: 4px solid var(--chat-head-color);
--chatroom-message-input-border-top: 4px solid var(--chatroom-head-bg-color);
--line-height-small: 14px;
--line-height: 16px;
--line-height-large: 20px;
--line-height-huge: 27px;
--occupants-padding: 1em;
--occupants-background-color: white;
--occupants-border-left: 0.2143rem solid var(--panel-divider-color);
--occupants-border-bottom: 1px solid lightgrey;
--embedded-emoji-picker-height: 300px;
--avatar-border-radius: 10%;
--avatar-border: 1px solid lightgrey;
--avatar-background-color: white;
--fullpage-chat-height: calc(var(--vh, 1vh) * 100);
--fullpage-chat-width: 100%;
--fullpage-emoji-picker-height: 300px;
--fullpage-max-chat-textarea-height: 15em;
--overlayed-chat-head-height: 55px;
--overlayed-chat-height: 450px;
--overlayed-chat-width: 300px;
--overlayed-chatbox-hover-height: 1em;
--overlayed-emoji-picker-height: 200px;
--overlayed-max-chat-textarea-height: 200px;
--overlayed-badge-color: #818479; // $gray-color
--list-toggle-color: #818479; // $gray-color
--list-toggle-hover-color: #585B51; // $dark-gray-color
--list-toggle-font-weight: normal;
--list-item-hover-color: rgba(0, 0, 0, 0.035);
--list-item-action-color: #e3eef3; // lighten($lightest-blue, 25%)
--list-item-link-color: inherit;
--list-item-link-hover-color: var(--dark-link-color);
--list-item-open-color: var(--controlbox-head-color);
--list-item-open-hover-color: var(--controlbox-head-color);
--list-dot-circle-color: #f6dec1; // lighten($orange, 25%)
}
#conversejs.theme-concord {
--avatar-border-radius: 10%;
--avatar-border: 0px;
--avatar-background-color: none;
--controlbox-pane-background-color: #333;
--panel-divider-color: #333;
--controlbox-pane-bg-hover-color: #464646;
--controlbox-heading-color: #777;
--controlbox-heading-font-weight: bold;
--groupchats-header-color: var(--redder-orange);
--chat-textarea-background-color: #F6F6F6;
--chat-correcting-color: #FFFFC0;
--chat-head-text-color: #AAA;
--controlbox-text-color: #DDD;
--chat-info-color: var(--subdued-color);
--chatbox-border-radius: 0px;
--heading-display: inline;
--heading-color: #9B4D;
--link-hover-color: var(--lighter-blue);
--chatroom-badge-color: var(--redder-orange);
--chatroom-badge-hover-color: #D24E2B; // $red
--chatroom-correcting-color: #FFFFC0;
--chatroom-head-bg-color: white;
--chatroom-head-border-bottom: 1px solid #EEE;
--chatroom-head-button-color: #999;
--chatroom-head-color: #7E7E7E;
--chatroom-head-description-border-left: 1px solid #DDD;
--chatroom-head-description-color: black;
--chatroom-head-description-display: inline;
--chatroom-head-description-link-color: #00b3f4;
--chatroom-head-description-padding-left: 12px;
--chatroom-head-title-font-weight: bold;
--chatroom-head-title-padding-right: 12px;
--muc-toolbar-btn-color: #7E7E7E;
--muc-toolbar-btn-disabled-color: lightgray;
--occupants-background-color: #F3F3F3;
--occupants-border-left: 0px;
--occupants-border-bottom: 0px;
--separator-text-color: #AAA;
--chat-separator-border-bottom: 1px solid #AAA;
--chatroom-separator-border-bottom: 1px solid #AAA;
--chatroom-message-input-border-top: 1px solid #CCC;
--chatbox-message-input-border-top: 1px solid #CCC;
--fullpage-chatbox-button-size: 24px;
--list-toggle-font-weight: bold;
--list-item-link-color: #F1F1F1;
--list-item-link-hover-color: #DDD;
--list-item-open-color: #444;
--list-item-open-hover-color: #444;
}

101
sass/font-awesome.scss vendored
View File

@ -1,101 +0,0 @@
@font-face {
font-family: 'Baumans';
font-style: normal;
font-weight: 400;
src: local('Baumans Regular'), local('Baumans-Regular'), url('webfonts/baumans.ttf') format('truetype');
}
@font-face {
font-family: 'Muli';
font-style: normal;
font-weight: 400;
src: local('Muli Regular'), local('Muli-Regular'), url('webfonts/muli.ttf') format('truetype');
}
@font-face {
font-family: 'ConverseFontAwesomeBrands';
font-style: normal;
font-weight: normal;
src: url('webfonts/fa-brands-400.eot');
src: url('webfonts/fa-brands-400.eot?#iefix') format('embedded-opentype'),
url('webfonts/fa-brands-400.woff2') format('woff2'),
url('webfonts/fa-brands-400.woff') format('woff'),
url('webfonts/fa-brands-400.ttf') format('truetype'),
url('webfonts/fa-brands-400.svg#fontawesome') format('svg');
}
@font-face {
font-family: 'ConverseFontAwesomeRegular';
font-style: normal;
font-weight: 400;
src: url('webfonts/fa-regular-400.eot');
src: url('webfonts/fa-regular-400.eot?#iefix') format('embedded-opentype'),
url('webfonts/fa-regular-400.woff2') format('woff2'),
url('webfonts/fa-regular-400.woff') format('woff'),
url('webfonts/fa-regular-400.ttf') format('truetype'),
url('webfonts/fa-regular-400.svg#fontawesome') format('svg');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'ConverseFontAwesomeSolid';
font-style: normal;
font-weight: 900;
src: url('webfonts/fa-solid-900.eot');
src: url('webfonts/fa-solid-900.eot?#iefix') format('embedded-opentype'),
url('webfonts/fa-solid-900.svg#fontawesome') format('svg'),
url('webfonts/fa-solid-900.woff2') format('woff2'),
url('webfonts/fa-solid-900.woff') format('woff'),
url('webfonts/fa-solid-900.ttf') format('truetype');
}
@import "@fortawesome/fontawesome-free/scss/variables";
@import "@fortawesome/fontawesome-free/scss/mixins";
@import "@fortawesome/fontawesome-free/scss/core";
@import "@fortawesome/fontawesome-free/scss/larger";
@import "@fortawesome/fontawesome-free/scss/fixed-width";
@import "@fortawesome/fontawesome-free/scss/list";
@import "@fortawesome/fontawesome-free/scss/bordered-pulled";
@import "@fortawesome/fontawesome-free/scss/animated";
@import "@fortawesome/fontawesome-free/scss/rotated-flipped";
@import "@fortawesome/fontawesome-free/scss/stacked";
@import "@fortawesome/fontawesome-free/scss/icons";
@import "@fortawesome/fontawesome-free/scss/screen-reader";
#conversejs, .converse-website {
/* Apparent font-awesome bug? The circle has some kind of bottom margin */
converse-icon:before {
content: none !important;
}
.far:not(converse-icon) {
font-family: 'ConverseFontAwesomeRegular' !important;
font-weight: 400;
}
.fa:not(converse-icon),
.fas:not(converse-icon) {
font-family: 'ConverseFontAwesomeSolid' !important;
font-weight: 900;
}
.fab:not(converse-icon) {
font-family: 'ConverseFontAwesomeBrands';
}
.fa:not(converse-icon),
.far:not(converse-icon),
.fas:not(converse-icon),
.fab:not(converse-icon) {
display: inline-block;
font-size: inherit;
text-rendering: auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.fa-info-circle {
height: 1em;
}
}

Binary file not shown.

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 699 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,803 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!--
Font Awesome Free 5.13.0 by @fontawesome - https://fontawesome.com
License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
-->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<metadata>
Created by FontForge 20190801 at Mon Mar 23 10:45:51 2020
By Robert Madole
Copyright (c) Font Awesome
</metadata>
<defs>
<font id="FontAwesome5Free-Regular" horiz-adv-x="512" >
<font-face
font-family="Font Awesome 5 Free Regular"
font-weight="400"
font-stretch="normal"
units-per-em="512"
panose-1="2 0 5 3 0 0 0 0 0 0"
ascent="448"
descent="-64"
bbox="-0.0663408 -64.0662 640.01 448.1"
underline-thickness="25"
underline-position="-50"
unicode-range="U+0020-F5C8"
/>
<missing-glyph />
<glyph glyph-name="heart" unicode="&#xf004;"
d="M458.4 383.7c75.2998 -63.4004 64.0996 -166.601 10.5996 -221.3l-175.4 -178.7c-10 -10.2002 -23.2998 -15.7998 -37.5996 -15.7998c-14.2002 0 -27.5996 5.69922 -37.5996 15.8994l-175.4 178.7c-53.5996 54.7002 -64.5996 157.9 10.5996 221.2
c57.8008 48.7002 147.101 41.2998 202.4 -15c55.2998 56.2998 144.6 63.5996 202.4 15zM434.8 196.2c36.2002 36.8994 43.7998 107.7 -7.2998 150.8c-38.7002 32.5996 -98.7002 27.9004 -136.5 -10.5996l-35 -35.7002l-35 35.7002
c-37.5996 38.2998 -97.5996 43.1992 -136.5 10.5c-51.2002 -43.1006 -43.7998 -113.5 -7.2998 -150.7l175.399 -178.7c2.40039 -2.40039 4.40039 -2.40039 6.80078 0z" />
<glyph glyph-name="star" unicode="&#xf005;" horiz-adv-x="576"
d="M528.1 276.5c26.2002 -3.7998 36.7002 -36.0996 17.7002 -54.5996l-105.7 -103l25 -145.5c4.5 -26.3008 -23.1992 -45.9004 -46.3994 -33.7002l-130.7 68.7002l-130.7 -68.7002c-23.2002 -12.2998 -50.8994 7.39941 -46.3994 33.7002l25 145.5l-105.7 103
c-19 18.5 -8.5 50.7998 17.7002 54.5996l146.1 21.2998l65.2998 132.4c11.7998 23.8994 45.7002 23.5996 57.4004 0l65.2998 -132.4zM388.6 135.7l100.601 98l-139 20.2002l-62.2002 126l-62.2002 -126l-139 -20.2002l100.601 -98l-23.7002 -138.4l124.3 65.2998
l124.3 -65.2998z" />
<glyph glyph-name="user" unicode="&#xf007;" horiz-adv-x="448"
d="M313.6 144c74.2002 0 134.4 -60.2002 134.4 -134.4v-25.5996c0 -26.5 -21.5 -48 -48 -48h-352c-26.5 0 -48 21.5 -48 48v25.5996c0 74.2002 60.2002 134.4 134.4 134.4c28.7998 0 42.5 -16 89.5996 -16s60.9004 16 89.5996 16zM400 -16v25.5996
c0 47.6006 -38.7998 86.4004 -86.4004 86.4004c-14.6992 0 -37.8994 -16 -89.5996 -16c-51.2998 0 -75 16 -89.5996 16c-47.6006 0 -86.4004 -38.7998 -86.4004 -86.4004v-25.5996h352zM224 160c-79.5 0 -144 64.5 -144 144s64.5 144 144 144s144 -64.5 144 -144
s-64.5 -144 -144 -144zM224 400c-52.9004 0 -96 -43.0996 -96 -96s43.0996 -96 96 -96s96 43.0996 96 96s-43.0996 96 -96 96z" />
<glyph glyph-name="clock" unicode="&#xf017;"
d="M256 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM256 -8c110.5 0 200 89.5 200 200s-89.5 200 -200 200s-200 -89.5 -200 -200s89.5 -200 200 -200zM317.8 96.4004l-84.8994 61.6992
c-3.10059 2.30078 -4.90039 5.90039 -4.90039 9.7002v164.2c0 6.59961 5.40039 12 12 12h32c6.59961 0 12 -5.40039 12 -12v-141.7l66.7998 -48.5996c5.40039 -3.90039 6.5 -11.4004 2.60059 -16.7998l-18.8008 -25.9004c-3.89941 -5.2998 -11.3994 -6.5 -16.7998 -2.59961z
" />
<glyph glyph-name="list-alt" unicode="&#xf022;"
d="M464 416c26.5098 0 48 -21.4902 48 -48v-352c0 -26.5098 -21.4902 -48 -48 -48h-416c-26.5098 0 -48 21.4902 -48 48v352c0 26.5098 21.4902 48 48 48h416zM458 16c3.31152 0 6 2.68848 6 6v340c0 3.31152 -2.68848 6 -6 6h-404c-3.31152 0 -6 -2.68848 -6 -6v-340
c0 -3.31152 2.68848 -6 6 -6h404zM416 108v-24c0 -6.62695 -5.37305 -12 -12 -12h-200c-6.62695 0 -12 5.37305 -12 12v24c0 6.62695 5.37305 12 12 12h200c6.62695 0 12 -5.37305 12 -12zM416 204v-24c0 -6.62695 -5.37305 -12 -12 -12h-200c-6.62695 0 -12 5.37305 -12 12
v24c0 6.62695 5.37305 12 12 12h200c6.62695 0 12 -5.37305 12 -12zM416 300v-24c0 -6.62695 -5.37305 -12 -12 -12h-200c-6.62695 0 -12 5.37305 -12 12v24c0 6.62695 5.37305 12 12 12h200c6.62695 0 12 -5.37305 12 -12zM164 288c0 -19.8818 -16.1182 -36 -36 -36
s-36 16.1182 -36 36s16.1182 36 36 36s36 -16.1182 36 -36zM164 192c0 -19.8818 -16.1182 -36 -36 -36s-36 16.1182 -36 36s16.1182 36 36 36s36 -16.1182 36 -36zM164 96c0 -19.8818 -16.1182 -36 -36 -36s-36 16.1182 -36 36s16.1182 36 36 36s36 -16.1182 36 -36z" />
<glyph glyph-name="flag" unicode="&#xf024;"
d="M336.174 368c35.4668 0 73.0195 12.6914 108.922 28.1797c31.6406 13.6514 66.9043 -9.65723 66.9043 -44.1162v-239.919c0 -16.1953 -8.1543 -31.3057 -21.7129 -40.1631c-26.5762 -17.3643 -70.0693 -39.9814 -128.548 -39.9814c-68.6084 0 -112.781 32 -161.913 32
c-56.5674 0 -89.957 -11.2803 -127.826 -28.5566v-83.4434c0 -8.83691 -7.16309 -16 -16 -16h-16c-8.83691 0 -16 7.16309 -16 16v406.438c-14.3428 8.2998 -24 23.7979 -24 41.5615c0 27.5693 23.2422 49.71 51.2012 47.8965
c22.9658 -1.49023 41.8662 -19.4717 44.4805 -42.3379c0.177734 -1.52441 0.321289 -4.00781 0.321289 -5.54199c0 -4.30176 -1.10352 -11.1035 -2.46289 -15.1846c22.418 8.68555 49.4199 15.168 80.7207 15.168c68.6084 0 112.781 -32 161.913 -32zM464 112v240
c-31.5059 -14.6338 -84.5547 -32 -127.826 -32c-59.9111 0 -101.968 32 -161.913 32c-41.4365 0 -80.4766 -16.5879 -102.261 -32v-232c31.4473 14.5967 84.4648 24 127.826 24c59.9111 0 101.968 -32 161.913 -32c41.4365 0 80.4775 16.5879 102.261 32z" />
<glyph glyph-name="bookmark" unicode="&#xf02e;" horiz-adv-x="384"
d="M336 448c26.5098 0 48 -21.4902 48 -48v-464l-192 112l-192 -112v464c0 26.5098 21.4902 48 48 48h288zM336 19.5703v374.434c0 3.31348 -2.68555 5.99609 -6 5.99609h-276c-3.31152 0 -6 -2.68848 -6 -6v-374.43l144 84z" />
<glyph glyph-name="image" unicode="&#xf03e;"
d="M464 384c26.5098 0 48 -21.4902 48 -48v-288c0 -26.5098 -21.4902 -48 -48 -48h-416c-26.5098 0 -48 21.4902 -48 48v288c0 26.5098 21.4902 48 48 48h416zM458 48c3.31152 0 6 2.68848 6 6v276c0 3.31152 -2.68848 6 -6 6h-404c-3.31152 0 -6 -2.68848 -6 -6v-276
c0 -3.31152 2.68848 -6 6 -6h404zM128 296c22.0908 0 40 -17.9092 40 -40s-17.9092 -40 -40 -40s-40 17.9092 -40 40s17.9092 40 40 40zM96 96v48l39.5137 39.5146c4.6875 4.68652 12.2852 4.68652 16.9717 0l39.5146 -39.5146l119.514 119.515
c4.6875 4.68652 12.2852 4.68652 16.9717 0l87.5146 -87.5146v-80h-320z" />
<glyph glyph-name="edit" unicode="&#xf044;" horiz-adv-x="576"
d="M402.3 103.1l32 32c5 5 13.7002 1.5 13.7002 -5.69922v-145.4c0 -26.5 -21.5 -48 -48 -48h-352c-26.5 0 -48 21.5 -48 48v352c0 26.5 21.5 48 48 48h273.5c7.09961 0 10.7002 -8.59961 5.7002 -13.7002l-32 -32c-1.5 -1.5 -3.5 -2.2998 -5.7002 -2.2998h-241.5v-352h352
v113.5c0 2.09961 0.799805 4.09961 2.2998 5.59961zM558.9 304.9l-262.601 -262.601l-90.3994 -10c-26.2002 -2.89941 -48.5 19.2002 -45.6006 45.6006l10 90.3994l262.601 262.601c22.8994 22.8994 59.8994 22.8994 82.6992 0l43.2002 -43.2002
c22.9004 -22.9004 22.9004 -60 0.100586 -82.7998zM460.1 274l-58.0996 58.0996l-185.8 -185.899l-7.2998 -65.2998l65.2998 7.2998zM524.9 353.7l-43.2002 43.2002c-4.10059 4.09961 -10.7998 4.09961 -14.7998 0l-30.9004 -30.9004l58.0996 -58.0996l30.9004 30.8994
c4 4.2002 4 10.7998 -0.0996094 14.9004z" />
<glyph glyph-name="times-circle" unicode="&#xf057;"
d="M256 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM256 -8c110.5 0 200 89.5 200 200s-89.5 200 -200 200s-200 -89.5 -200 -200s89.5 -200 200 -200zM357.8 254.2l-62.2002 -62.2002l62.2002 -62.2002
c4.7002 -4.7002 4.7002 -12.2998 0 -17l-22.5996 -22.5996c-4.7002 -4.7002 -12.2998 -4.7002 -17 0l-62.2002 62.2002l-62.2002 -62.2002c-4.7002 -4.7002 -12.2998 -4.7002 -17 0l-22.5996 22.5996c-4.7002 4.7002 -4.7002 12.2998 0 17l62.2002 62.2002l-62.2002 62.2002
c-4.7002 4.7002 -4.7002 12.2998 0 17l22.5996 22.5996c4.7002 4.7002 12.2998 4.7002 17 0l62.2002 -62.2002l62.2002 62.2002c4.7002 4.7002 12.2998 4.7002 17 0l22.5996 -22.5996c4.7002 -4.7002 4.7002 -12.2998 0 -17z" />
<glyph glyph-name="check-circle" unicode="&#xf058;"
d="M256 440c136.967 0 248 -111.033 248 -248s-111.033 -248 -248 -248s-248 111.033 -248 248s111.033 248 248 248zM256 392c-110.549 0 -200 -89.4678 -200 -200c0 -110.549 89.4678 -200 200 -200c110.549 0 200 89.4678 200 200c0 110.549 -89.4678 200 -200 200z
M396.204 261.733c4.66699 -4.70508 4.63672 -12.3037 -0.0673828 -16.9717l-172.589 -171.204c-4.70508 -4.66797 -12.3027 -4.63672 -16.9697 0.0683594l-90.7812 91.5156c-4.66797 4.70605 -4.63672 12.3047 0.0683594 16.9717l22.7188 22.5361
c4.70508 4.66699 12.3027 4.63574 16.9697 -0.0693359l59.792 -60.2773l141.353 140.216c4.70508 4.66797 12.3027 4.6377 16.9697 -0.0673828z" />
<glyph glyph-name="question-circle" unicode="&#xf059;"
d="M256 440c136.957 0 248 -111.083 248 -248c0 -136.997 -111.043 -248 -248 -248s-248 111.003 -248 248c0 136.917 111.043 248 248 248zM256 -8c110.569 0 200 89.4697 200 200c0 110.529 -89.5088 200 -200 200c-110.528 0 -200 -89.5049 -200 -200
c0 -110.569 89.4678 -200 200 -200zM363.244 247.2c0 -67.0518 -72.4209 -68.084 -72.4209 -92.8633v-6.33691c0 -6.62695 -5.37305 -12 -12 -12h-45.6475c-6.62695 0 -12 5.37305 -12 12v8.65918c0 35.7451 27.1006 50.0342 47.5791 61.5156
c17.5615 9.84473 28.3242 16.541 28.3242 29.5791c0 17.2461 -21.999 28.6934 -39.7842 28.6934c-23.1885 0 -33.8936 -10.9775 -48.9424 -29.9697c-4.05664 -5.11914 -11.46 -6.07031 -16.666 -2.12402l-27.8232 21.0986
c-5.10742 3.87207 -6.25098 11.0654 -2.64453 16.3633c23.627 34.6934 53.7217 54.1846 100.575 54.1846c49.0713 0 101.45 -38.3037 101.45 -88.7998zM298 80c0 -23.1592 -18.8408 -42 -42 -42s-42 18.8408 -42 42s18.8408 42 42 42s42 -18.8408 42 -42z" />
<glyph glyph-name="eye" unicode="&#xf06e;" horiz-adv-x="576"
d="M288 304c0.0927734 0 0.244141 0.000976562 0.336914 0.000976562c61.6641 0 111.71 -50.0469 111.71 -111.711c0 -61.6631 -50.0459 -111.71 -111.71 -111.71s-111.71 50.0469 -111.71 111.71c0 8.71289 1.95898 22.5781 4.37305 30.9502
c6.93066 -3.94141 19.0273 -7.18457 27 -7.24023c30.9121 0 56 25.0879 56 56c-0.0556641 7.97266 -3.29883 20.0693 -7.24023 27c8.42383 2.62207 22.4189 4.8623 31.2402 5zM572.52 206.6c1.9209 -3.79883 3.47949 -10.3379 3.47949 -14.5947
s-1.55859 -10.7959 -3.47949 -14.5947c-54.1992 -105.771 -161.59 -177.41 -284.52 -177.41s-230.29 71.5898 -284.52 177.4c-1.9209 3.79883 -3.47949 10.3379 -3.47949 14.5947s1.55859 10.7959 3.47949 14.5947c54.1992 105.771 161.59 177.41 284.52 177.41
s230.29 -71.5898 284.52 -177.4zM288 48c98.6602 0 189.1 55 237.93 144c-48.8398 89 -139.27 144 -237.93 144s-189.09 -55 -237.93 -144c48.8398 -89 139.279 -144 237.93 -144z" />
<glyph glyph-name="eye-slash" unicode="&#xf070;" horiz-adv-x="640"
d="M634 -23c3.31738 -2.65137 6.00977 -8.25098 6.00977 -12.498c0 -3.10449 -1.57715 -7.58984 -3.51953 -10.0117l-10 -12.4902c-2.65234 -3.31152 -8.24707 -6 -12.4902 -6c-3.09961 0 -7.58008 1.57227 -10 3.50977l-598 467.49
c-3.31738 2.65137 -6.00977 8.25098 -6.00977 12.498c0 3.10449 1.57715 7.58984 3.51953 10.0117l10 12.4902c2.65234 3.31152 8.24707 6 12.4902 6c3.09961 0 7.58008 -1.57227 10 -3.50977zM296.79 301.53c6.33496 1.35059 16.7324 2.45801 23.21 2.46973
c60.4805 0 109.36 -47.9102 111.58 -107.85zM343.21 82.46c-6.33496 -1.34375 -16.7334 -2.44629 -23.21 -2.45996c-60.4697 0 -109.35 47.9102 -111.58 107.84zM320 336c-19.8799 0 -39.2803 -2.7998 -58.2197 -7.09961l-46.4102 36.29
c32.9199 11.8096 67.9297 18.8096 104.63 18.8096c122.93 0 230.29 -71.5898 284.57 -177.4c1.91992 -3.79883 3.47949 -10.3379 3.47949 -14.5947s-1.55957 -10.7959 -3.47949 -14.5947c-11.7197 -22.7598 -35.4189 -56.4092 -52.9004 -75.1104l-37.7402 29.5
c14.333 15.0156 34.0449 41.9854 44 60.2002c-48.8398 89 -139.279 144 -237.93 144zM320 48c19.8896 0 39.2803 2.7998 58.2197 7.08984l46.4102 -36.2803c-32.9199 -11.7598 -67.9297 -18.8096 -104.63 -18.8096c-122.92 0 -230.28 71.5898 -284.51 177.4
c-1.9209 3.79883 -3.47949 10.3379 -3.47949 14.5947s1.55859 10.7959 3.47949 14.5947c11.7168 22.7568 35.4111 56.4014 52.8896 75.1006l37.7402 -29.5c-14.3467 -15.0107 -34.0811 -41.9756 -44.0498 -60.1904c48.8496 -89 139.279 -144 237.93 -144z" />
<glyph glyph-name="calendar-alt" unicode="&#xf073;" horiz-adv-x="448"
d="M148 160h-40c-6.59961 0 -12 5.40039 -12 12v40c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-40c0 -6.59961 -5.40039 -12 -12 -12zM256 172c0 -6.59961 -5.40039 -12 -12 -12h-40c-6.59961 0 -12 5.40039 -12 12v40c0 6.59961 5.40039 12 12 12h40
c6.59961 0 12 -5.40039 12 -12v-40zM352 172c0 -6.59961 -5.40039 -12 -12 -12h-40c-6.59961 0 -12 5.40039 -12 12v40c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-40zM256 76c0 -6.59961 -5.40039 -12 -12 -12h-40c-6.59961 0 -12 5.40039 -12 12v40
c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-40zM160 76c0 -6.59961 -5.40039 -12 -12 -12h-40c-6.59961 0 -12 5.40039 -12 12v40c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-40zM352 76c0 -6.59961 -5.40039 -12 -12 -12h-40
c-6.59961 0 -12 5.40039 -12 12v40c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-40zM448 336v-352c0 -26.5 -21.5 -48 -48 -48h-352c-26.5 0 -48 21.5 -48 48v352c0 26.5 21.5 48 48 48h48v52c0 6.59961 5.40039 12 12 12h40
c6.59961 0 12 -5.40039 12 -12v-52h128v52c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-52h48c26.5 0 48 -21.5 48 -48zM400 -10v298h-352v-298c0 -3.2998 2.7002 -6 6 -6h340c3.2998 0 6 2.7002 6 6z" />
<glyph glyph-name="comment" unicode="&#xf075;"
d="M256 416c141.4 0 256 -93.0996 256 -208s-114.6 -208 -256 -208c-32.7998 0 -64 5.2002 -92.9004 14.2998c-29.0996 -20.5996 -77.5996 -46.2998 -139.1 -46.2998c-9.59961 0 -18.2998 5.7002 -22.0996 14.5c-3.80078 8.7998 -2 19 4.59961 26
c0.5 0.400391 31.5 33.7998 46.4004 73.2002c-33 35.0996 -52.9004 78.7002 -52.9004 126.3c0 114.9 114.6 208 256 208zM256 48c114.7 0 208 71.7998 208 160s-93.2998 160 -208 160s-208 -71.7998 -208 -160c0 -42.2002 21.7002 -74.0996 39.7998 -93.4004
l20.6006 -21.7998l-10.6006 -28.0996c-5.5 -14.5 -12.5996 -28.1006 -19.8994 -40.2002c23.5996 7.59961 43.1992 18.9004 57.5 29l19.5 13.7998l22.6992 -7.2002c25.3008 -8 51.7002 -12.0996 78.4004 -12.0996z" />
<glyph glyph-name="folder" unicode="&#xf07b;"
d="M464 320c26.5098 0 48 -21.4902 48 -48v-224c0 -26.5098 -21.4902 -48 -48 -48h-416c-26.5098 0 -48 21.4902 -48 48v288c0 26.5098 21.4902 48 48 48h146.74c8.49023 0 16.6299 -3.37012 22.6299 -9.37012l54.6299 -54.6299h192zM464 48v224h-198.62
c-8.49023 0 -16.6299 3.37012 -22.6299 9.37012l-54.6299 54.6299h-140.12v-288h416z" />
<glyph glyph-name="folder-open" unicode="&#xf07c;" horiz-adv-x="576"
d="M527.9 224c37.6992 0 60.6992 -41.5 40.6992 -73.4004l-79.8994 -128c-8.7998 -14.0996 -24.2002 -22.5996 -40.7002 -22.5996h-400c-26.5 0 -48 21.5 -48 48v288c0 26.5 21.5 48 48 48h160l64 -64h160c26.5 0 48 -21.5 48 -48v-48h47.9004zM48 330v-233.4l62.9004 104.2
c8.69922 14.4004 24.2998 23.2002 41.0996 23.2002h280v42c0 3.2998 -2.7002 6 -6 6h-173.9l-64 64h-134.1c-3.2998 0 -6 -2.7002 -6 -6zM448 48l80 128h-378.8l-77.2002 -128h376z" />
<glyph glyph-name="chart-bar" unicode="&#xf080;"
d="M396.8 96c-6.39941 0 -12.7998 6.40039 -12.7998 12.7998v230.4c0 6.39941 6.40039 12.7998 12.7998 12.7998h22.4004c6.39941 0 12.7998 -6.40039 12.7998 -12.7998v-230.4c0 -6.39941 -6.40039 -12.7998 -12.7998 -12.7998h-22.4004zM204.8 96
c-6.39941 0 -12.7998 6.40039 -12.7998 12.7998v198.4c0 6.39941 6.40039 12.7998 12.7998 12.7998h22.4004c6.39941 0 12.7998 -6.40039 12.7998 -12.7998v-198.4c0 -6.39941 -6.40039 -12.7998 -12.7998 -12.7998h-22.4004zM300.8 96
c-6.39941 0 -12.7998 6.40039 -12.7998 12.7998v134.4c0 6.39941 6.40039 12.7998 12.7998 12.7998h22.4004c6.39941 0 12.7998 -6.40039 12.7998 -12.7998v-134.4c0 -6.39941 -6.40039 -12.7998 -12.7998 -12.7998h-22.4004zM496 48c8.83984 0 16 -7.16016 16 -16v-16
c0 -8.83984 -7.16016 -16 -16 -16h-464c-17.6699 0 -32 14.3301 -32 32v336c0 8.83984 7.16016 16 16 16h16c8.83984 0 16 -7.16016 16 -16v-320h448zM108.8 96c-6.39941 0 -12.7998 6.40039 -12.7998 12.7998v70.4004c0 6.39941 6.40039 12.7998 12.7998 12.7998h22.4004
c6.39941 0 12.7998 -6.40039 12.7998 -12.7998v-70.4004c0 -6.39941 -6.40039 -12.7998 -12.7998 -12.7998h-22.4004z" />
<glyph glyph-name="comments" unicode="&#xf086;" horiz-adv-x="576"
d="M532 61.7998c15.2998 -30.7002 37.4004 -54.5 37.7998 -54.7998c6.2998 -6.7002 8 -16.5 4.40039 -25c-3.7002 -8.5 -12 -14 -21.2002 -14c-53.5996 0 -96.7002 20.2998 -125.2 38.7998c-19 -4.39941 -39 -6.7998 -59.7998 -6.7998
c-86.2002 0 -159.9 40.4004 -191.3 97.7998c-9.7002 1.2002 -19.2002 2.7998 -28.4004 4.90039c-28.5 -18.6006 -71.7002 -38.7998 -125.2 -38.7998c-9.19922 0 -17.5996 5.5 -21.1992 14c-3.7002 8.5 -1.90039 18.2998 4.39941 25
c0.400391 0.399414 22.4004 24.1992 37.7002 54.8994c-27.5 27.2002 -44 61.2002 -44 98.2002c0 88.4004 93.0996 160 208 160c86.2998 0 160.3 -40.5 191.8 -98.0996c99.7002 -11.8008 176.2 -77.9004 176.2 -157.9c0 -37.0996 -16.5 -71.0996 -44 -98.2002zM139.2 154.1
l19.7998 -4.5c16 -3.69922 32.5 -5.59961 49 -5.59961c86.7002 0 160 51.2998 160 112s-73.2998 112 -160 112s-160 -51.2998 -160 -112c0 -28.7002 16.2002 -50.5996 29.7002 -64l24.7998 -24.5l-15.5 -31.0996c-2.59961 -5.10059 -5.2998 -10.1006 -8 -14.8008
c14.5996 5.10059 29 12.3008 43.0996 21.4004zM498.3 96c13.5 13.4004 29.7002 35.2998 29.7002 64c0 49.2002 -48.2998 91.5 -112.7 106c0.299805 -3.2998 0.700195 -6.59961 0.700195 -10c0 -80.9004 -78 -147.5 -179.3 -158.3
c29.0996 -29.6006 77.2998 -49.7002 131.3 -49.7002c16.5 0 33 1.90039 49 5.59961l19.9004 4.60059l17.0996 -11.1006c14.0996 -9.09961 28.5 -16.2998 43.0996 -21.3994c-2.69922 4.7002 -5.39941 9.7002 -8 14.7998l-15.5 31.0996z" />
<glyph glyph-name="star-half" unicode="&#xf089;" horiz-adv-x="576"
d="M288 62.7002v-54.2998l-130.7 -68.6006c-23.3994 -12.2998 -50.8994 7.60059 -46.3994 33.7002l25 145.5l-105.7 103c-19 18.5 -8.5 50.7998 17.7002 54.5996l146.1 21.2002l65.2998 132.4c5.90039 11.8994 17.2998 17.7998 28.7002 17.7998v-68.0996l-62.2002 -126
l-139 -20.2002l100.601 -98l-23.7002 -138.4z" />
<glyph glyph-name="lemon" unicode="&#xf094;"
d="M484.112 420.111c28.1221 -28.123 35.9434 -68.0039 19.0215 -97.0547c-23.0576 -39.584 50.1436 -163.384 -82.3311 -295.86c-132.301 -132.298 -256.435 -59.3594 -295.857 -82.3291c-29.0459 -16.917 -68.9219 -9.11426 -97.0576 19.0205
c-28.1221 28.1221 -35.9434 68.0029 -19.0215 97.0547c23.0566 39.5859 -50.1436 163.386 82.3301 295.86c132.308 132.309 256.407 59.3496 295.862 82.332c29.0498 16.9219 68.9307 9.09863 97.0537 -19.0234zM461.707 347.217
c13.5166 23.2031 -27.7578 63.7314 -50.4883 50.4912c-66.6025 -38.7939 -165.646 45.5898 -286.081 -74.8457c-120.444 -120.445 -36.0449 -219.472 -74.8447 -286.08c-13.542 -23.2471 27.8145 -63.6953 50.4932 -50.4883
c66.6006 38.7949 165.636 -45.5996 286.076 74.8428c120.444 120.445 36.0449 219.472 74.8447 286.08zM291.846 338.481c1.37012 -10.96 -6.40332 -20.957 -17.3643 -22.3271c-54.8467 -6.85547 -135.779 -87.7871 -142.636 -142.636
c-1.37305 -10.9883 -11.3984 -18.7334 -22.3262 -17.3643c-10.9609 1.37012 -18.7344 11.3652 -17.3643 22.3262c9.16211 73.2852 104.167 168.215 177.364 177.364c10.9531 1.36816 20.9561 -6.40234 22.3262 -17.3633z" />
<glyph glyph-name="credit-card" unicode="&#xf09d;" horiz-adv-x="576"
d="M527.9 416c26.5996 0 48.0996 -21.5 48.0996 -48v-352c0 -26.5 -21.5 -48 -48.0996 -48h-479.801c-26.5996 0 -48.0996 21.5 -48.0996 48v352c0 26.5 21.5 48 48.0996 48h479.801zM54.0996 368c-3.2998 0 -6 -2.7002 -6 -6v-42h479.801v42c0 3.2998 -2.7002 6 -6 6
h-467.801zM521.9 16c3.2998 0 6 2.7002 6 6v170h-479.801v-170c0 -3.2998 2.7002 -6 6 -6h467.801zM192 116v-40c0 -6.59961 -5.40039 -12 -12 -12h-72c-6.59961 0 -12 5.40039 -12 12v40c0 6.59961 5.40039 12 12 12h72c6.59961 0 12 -5.40039 12 -12zM384 116v-40
c0 -6.59961 -5.40039 -12 -12 -12h-136c-6.59961 0 -12 5.40039 -12 12v40c0 6.59961 5.40039 12 12 12h136c6.59961 0 12 -5.40039 12 -12z" />
<glyph glyph-name="hdd" unicode="&#xf0a0;" horiz-adv-x="576"
d="M567.403 212.358c5.59668 -8.04688 8.59668 -17.6113 8.59668 -27.4121v-136.946c0 -26.5098 -21.4902 -48 -48 -48h-480c-26.5098 0 -48 21.4902 -48 48v136.946c0 8.30957 3.85156 20.5898 8.59668 27.4121l105.08 151.053
c7.90625 11.3652 25.5596 20.5889 39.4033 20.5889h0.000976562h269.838h0.000976562c13.8438 0 31.4971 -9.22363 39.4033 -20.5889zM153.081 336l-77.9131 -112h425.664l-77.9131 112h-269.838zM528 48v128h-480v-128h480zM496 112c0 -17.6729 -14.3271 -32 -32 -32
s-32 14.3271 -32 32s14.3271 32 32 32s32 -14.3271 32 -32zM400 112c0 -17.6729 -14.3271 -32 -32 -32s-32 14.3271 -32 32s14.3271 32 32 32s32 -14.3271 32 -32z" />
<glyph glyph-name="hand-point-right" unicode="&#xf0a4;"
d="M428.8 310.4c45.0996 0 83.2002 -38.1016 83.2002 -83.2002c0 -45.6162 -37.7646 -83.2002 -83.2002 -83.2002h-35.6475c-1.41602 -6.36719 -4.96875 -16.252 -7.92969 -22.0645c2.50586 -22.0059 -3.50293 -44.9775 -15.9844 -62.791
c-1.14062 -52.4863 -37.3984 -91.1445 -99.9404 -91.1445h-21.2988c-60.0635 0 -98.5117 40 -127.2 40h-2.67871c-5.74707 -4.95215 -13.5361 -8 -22.1201 -8h-64c-17.6729 0 -32 12.8936 -32 28.7998v230.4c0 15.9062 14.3271 28.7998 32 28.7998h64.001
c8.58398 0 16.373 -3.04785 22.1201 -8h2.67871c6.96387 0 14.8623 6.19336 30.1816 23.6689l0.128906 0.148438l0.130859 0.145508c8.85645 9.93652 18.1162 20.8398 25.8506 33.2529c18.7051 30.2471 30.3936 78.7842 75.707 78.7842c56.9277 0 92 -35.2861 92 -83.2002
v-0.0839844c0 -6.21777 -0.974609 -16.2148 -2.17578 -22.3154h86.1768zM428.8 192c18.9756 0 35.2002 16.2246 35.2002 35.2002c0 18.7002 -16.7754 35.2002 -35.2002 35.2002h-158.399c0 17.3242 26.3994 35.1992 26.3994 70.3994c0 26.4004 -20.625 35.2002 -44 35.2002
c-8.79395 0 -20.4443 -32.7119 -34.9258 -56.0996c-9.07422 -14.5752 -19.5244 -27.2256 -30.7988 -39.875c-16.1094 -18.374 -33.8359 -36.6328 -59.0752 -39.5967v-176.753c42.79 -3.7627 74.5088 -39.6758 120 -39.6758h21.2988
c40.5244 0 57.124 22.1973 50.6006 61.3252c14.6113 8.00098 24.1514 33.9785 12.9248 53.625c19.3652 18.2246 17.7871 46.3809 4.9502 61.0498h91.0254zM88 64c0 13.2549 -10.7451 24 -24 24s-24 -10.7451 -24 -24s10.7451 -24 24 -24s24 10.7451 24 24z" />
<glyph glyph-name="hand-point-left" unicode="&#xf0a5;"
d="M0 227.2c0 45.0986 38.1006 83.2002 83.2002 83.2002h86.1758c-1.3623 6.91016 -2.17578 14.374 -2.17578 22.3994c0 47.9141 35.0723 83.2002 92 83.2002c45.3135 0 57.002 -48.5371 75.7061 -78.7852c7.73438 -12.4121 16.9951 -23.3154 25.8506 -33.2529
l0.130859 -0.145508l0.128906 -0.148438c15.3213 -17.4746 23.2197 -23.668 30.1836 -23.668h2.67871c5.74707 4.95215 13.5361 8 22.1201 8h64c17.6729 0 32 -12.8936 32 -28.7998v-230.4c0 -15.9062 -14.3271 -28.7998 -32 -28.7998h-64
c-8.58398 0 -16.373 3.04785 -22.1201 8h-2.67871c-28.6885 0 -67.1367 -40 -127.2 -40h-21.2988c-62.542 0 -98.8008 38.6582 -99.9404 91.1445c-12.4814 17.8135 -18.4922 40.7852 -15.9844 62.791c-2.96094 5.8125 -6.51367 15.6973 -7.92969 22.0645h-35.6465
c-45.4355 0 -83.2002 37.584 -83.2002 83.2002zM48 227.2c0 -18.9756 16.2246 -35.2002 35.2002 -35.2002h91.0244c-12.8369 -14.6689 -14.415 -42.8252 4.9502 -61.0498c-11.2256 -19.6465 -1.68652 -45.624 12.9248 -53.625
c-6.52246 -39.1279 10.0771 -61.3252 50.6016 -61.3252h21.2988c45.4912 0 77.21 35.9131 120 39.6768v176.752c-25.2393 2.96289 -42.9658 21.2227 -59.0752 39.5967c-11.2744 12.6494 -21.7246 25.2998 -30.7988 39.875
c-14.4814 23.3877 -26.1318 56.0996 -34.9258 56.0996c-23.375 0 -44 -8.7998 -44 -35.2002c0 -35.2002 26.3994 -53.0752 26.3994 -70.3994h-158.399c-18.4248 0 -35.2002 -16.5 -35.2002 -35.2002zM448 88c-13.2549 0 -24 -10.7451 -24 -24s10.7451 -24 24 -24
s24 10.7451 24 24s-10.7451 24 -24 24z" />
<glyph glyph-name="hand-point-up" unicode="&#xf0a6;" horiz-adv-x="448"
d="M105.6 364.8c0 45.0996 38.1016 83.2002 83.2002 83.2002c45.6162 0 83.2002 -37.7646 83.2002 -83.2002v-35.6465c6.36719 -1.41602 16.252 -4.96875 22.0645 -7.92969c22.0059 2.50684 44.9775 -3.50293 62.791 -15.9844
c52.4863 -1.14062 91.1445 -37.3984 91.1445 -99.9404v-21.2988c0 -60.0635 -40 -98.5117 -40 -127.2v-2.67871c4.95215 -5.74707 8 -13.5361 8 -22.1201v-64c0 -17.6729 -12.8936 -32 -28.7998 -32h-230.4c-15.9062 0 -28.7998 14.3271 -28.7998 32v64
c0 8.58398 3.04785 16.373 8 22.1201v2.67871c0 6.96387 -6.19336 14.8623 -23.6689 30.1816l-0.148438 0.128906l-0.145508 0.130859c-9.93652 8.85645 -20.8398 18.1162 -33.2529 25.8506c-30.2471 18.7051 -78.7842 30.3936 -78.7842 75.707
c0 56.9277 35.2861 92 83.2002 92h0.0839844c6.21777 0 16.2148 -0.974609 22.3154 -2.17578v86.1768zM224 364.8c0 18.9756 -16.2246 35.2002 -35.2002 35.2002c-18.7002 0 -35.2002 -16.7754 -35.2002 -35.2002v-158.399c-17.3242 0 -35.1992 26.3994 -70.3994 26.3994
c-26.4004 0 -35.2002 -20.625 -35.2002 -44c0 -8.79395 32.7119 -20.4443 56.0996 -34.9258c14.5752 -9.07422 27.2256 -19.5244 39.875 -30.7988c18.374 -16.1094 36.6328 -33.8359 39.5967 -59.0752h176.753c3.7627 42.79 39.6758 74.5088 39.6758 120v21.2988
c0 40.5244 -22.1973 57.124 -61.3252 50.6006c-8.00098 14.6113 -33.9785 24.1514 -53.625 12.9248c-18.2246 19.3652 -46.3809 17.7871 -61.0498 4.9502v91.0254zM352 24c-13.2549 0 -24 -10.7451 -24 -24s10.7451 -24 24 -24s24 10.7451 24 24s-10.7451 24 -24 24z" />
<glyph glyph-name="hand-point-down" unicode="&#xf0a7;" horiz-adv-x="448"
d="M188.8 -64c-45.0986 0 -83.2002 38.1006 -83.2002 83.2002v86.1758c-6.91016 -1.3623 -14.374 -2.17578 -22.3994 -2.17578c-47.9141 0 -83.2002 35.0723 -83.2002 92c0 45.3135 48.5371 57.002 78.7852 75.707c12.4121 7.73438 23.3154 16.9951 33.2529 25.8506
l0.145508 0.130859l0.148438 0.128906c17.4746 15.3213 23.668 23.2197 23.668 30.1836v2.67871c-4.95215 5.74707 -8 13.5361 -8 22.1201v64c0 17.6729 12.8936 32 28.7998 32h230.4c15.9062 0 28.7998 -14.3271 28.7998 -32v-64.001
c0 -8.58398 -3.04785 -16.373 -8 -22.1201v-2.67871c0 -28.6885 40 -67.1367 40 -127.2v-21.2988c0 -62.542 -38.6582 -98.8008 -91.1445 -99.9404c-17.8135 -12.4814 -40.7852 -18.4922 -62.791 -15.9844c-5.8125 -2.96094 -15.6973 -6.51367 -22.0645 -7.92969v-35.6465
c0 -45.4355 -37.584 -83.2002 -83.2002 -83.2002zM188.8 -16c18.9756 0 35.2002 16.2246 35.2002 35.2002v91.0244c14.6689 -12.8369 42.8252 -14.415 61.0498 4.9502c19.6465 -11.2256 45.624 -1.68652 53.625 12.9248c39.1279 -6.52246 61.3252 10.0771 61.3252 50.6016
v21.2988c0 45.4912 -35.9131 77.21 -39.6768 120h-176.752c-2.96289 -25.2393 -21.2227 -42.9658 -39.5967 -59.0752c-12.6494 -11.2744 -25.2998 -21.7246 -39.875 -30.7988c-23.3877 -14.4814 -56.0996 -26.1318 -56.0996 -34.9258c0 -23.375 8.7998 -44 35.2002 -44
c35.2002 0 53.0752 26.3994 70.3994 26.3994v-158.399c0 -18.4248 16.5 -35.2002 35.2002 -35.2002zM328 384c0 -13.2549 10.7451 -24 24 -24s24 10.7451 24 24s-10.7451 24 -24 24s-24 -10.7451 -24 -24z" />
<glyph glyph-name="copy" unicode="&#xf0c5;" horiz-adv-x="448"
d="M433.941 382.059c7.75977 -7.75977 14.0586 -22.9658 14.0586 -33.9404v-268.118c0 -26.5098 -21.4902 -48 -48 -48h-80v-48c0 -26.5098 -21.4902 -48 -48 -48h-224c-26.5098 0 -48 21.4902 -48 48v320c0 26.5098 21.4902 48 48 48h80v48c0 26.5098 21.4902 48 48 48
h172.118c10.9746 0 26.1807 -6.29883 33.9404 -14.0586zM266 -16c3.31152 0 6 2.68848 6 6v42h-96c-26.5098 0 -48 21.4902 -48 48v224h-74c-3.31152 0 -6 -2.68848 -6 -6v-308c0 -3.31152 2.68848 -6 6 -6h212zM394 80c3.31152 0 6 2.68848 6 6v202h-88
c-13.2549 0 -24 10.7451 -24 24v88h-106c-3.31152 0 -6 -2.68848 -6 -6v-308c0 -3.31152 2.68848 -6 6 -6h212zM400 336v9.63184v0.000976562c0 1.37207 -0.787109 3.27246 -1.75684 4.24219l-48.3682 48.3682c-1.12598 1.125 -2.65234 1.75684 -4.24316 1.75684h-9.63184
v-64h64z" />
<glyph glyph-name="save" unicode="&#xf0c7;" horiz-adv-x="448"
d="M433.941 318.059c7.75977 -7.75977 14.0586 -22.9658 14.0586 -33.9404v-268.118c0 -26.5098 -21.4902 -48 -48 -48h-352c-26.5098 0 -48 21.4902 -48 48v352c0 26.5098 21.4902 48 48 48h268.118c10.9746 0 26.1807 -6.29883 33.9404 -14.0586zM272 368h-128v-80h128v80
zM394 16c3.31152 0 6 2.68848 6 6v259.632v0.000976562c0 1.37207 -0.787109 3.27246 -1.75684 4.24219l-78.2432 78.2432v-100.118c0 -13.2549 -10.7451 -24 -24 -24h-176c-13.2549 0 -24 10.7451 -24 24v104h-42c-3.31152 0 -6 -2.68848 -6 -6v-340
c0 -3.31152 2.68848 -6 6 -6h340zM224 216c48.5234 0 88 -39.4766 88 -88s-39.4766 -88 -88 -88s-88 39.4766 -88 88s39.4766 88 88 88zM224 88c22.0557 0 40 17.9443 40 40s-17.9443 40 -40 40s-40 -17.9443 -40 -40s17.9443 -40 40 -40z" />
<glyph glyph-name="square" unicode="&#xf0c8;" horiz-adv-x="448"
d="M400 416c26.5 0 48 -21.5 48 -48v-352c0 -26.5 -21.5 -48 -48 -48h-352c-26.5 0 -48 21.5 -48 48v352c0 26.5 21.5 48 48 48h352zM394 16c3.2998 0 6 2.7002 6 6v340c0 3.2998 -2.7002 6 -6 6h-340c-3.2998 0 -6 -2.7002 -6 -6v-340c0 -3.2998 2.7002 -6 6 -6h340z" />
<glyph glyph-name="envelope" unicode="&#xf0e0;"
d="M464 384c26.5098 0 48 -21.4902 48 -48v-288c0 -26.5098 -21.4902 -48 -48 -48h-416c-26.5098 0 -48 21.4902 -48 48v288c0 26.5098 21.4902 48 48 48h416zM464 336h-416v-40.8047c22.4248 -18.2627 58.1797 -46.6602 134.587 -106.49
c16.834 -13.2422 50.2051 -45.0762 73.4131 -44.7012c23.2119 -0.371094 56.5723 31.4541 73.4131 44.7012c76.4189 59.8389 112.165 88.2305 134.587 106.49v40.8047zM48 48h416v185.601c-22.915 -18.252 -55.4189 -43.8691 -104.947 -82.6523
c-22.5439 -17.748 -60.3359 -55.1787 -103.053 -54.9473c-42.9277 -0.231445 -81.2051 37.75 -103.062 54.9551c-49.5293 38.7842 -82.0244 64.3945 -104.938 82.6455v-185.602z" />
<glyph glyph-name="lightbulb" unicode="&#xf0eb;" horiz-adv-x="352"
d="M176 368c8.83984 0 16 -7.16016 16 -16s-7.16016 -16 -16 -16c-35.2803 0 -64 -28.7002 -64 -64c0 -8.83984 -7.16016 -16 -16 -16s-16 7.16016 -16 16c0 52.9404 43.0596 96 96 96zM96.0596 -11.1699l-0.0400391 43.1797h159.961l-0.0507812 -43.1797
c-0.00976562 -3.13965 -0.939453 -6.21973 -2.67969 -8.83984l-24.5098 -36.8398c-2.95996 -4.45996 -7.95996 -7.14062 -13.3203 -7.14062h-78.8496c-5.35059 0 -10.3506 2.68066 -13.3203 7.14062l-24.5098 36.8398c-1.75 2.62012 -2.68066 5.68945 -2.68066 8.83984z
M176 448c97.2002 0 176 -78.7998 176 -176c0 -44.3701 -16.4502 -84.8496 -43.5498 -115.79c-16.6406 -18.9795 -42.7402 -58.79 -52.4199 -92.1602v-0.0498047h-48v0.0996094c0.00390625 4.04199 0.999023 10.4482 2.21973 14.3008
c5.67969 17.9893 22.9902 64.8496 62.0996 109.46c20.4102 23.29 31.6504 53.1699 31.6504 84.1396c0 70.5801 -57.4199 128 -128 128c-68.2803 0 -128.15 -54.3604 -127.95 -128c0.0898438 -30.9902 11.0703 -60.71 31.6104 -84.1396
c39.3496 -44.9004 56.5801 -91.8604 62.1699 -109.67c1.42969 -4.56055 2.13965 -9.30078 2.15039 -14.0703v-0.120117h-48v0.0595703c-9.68066 33.3604 -35.7803 73.1709 -52.4209 92.1602c-27.1094 30.9307 -43.5596 71.4102 -43.5596 115.78
c0 93.0303 73.7197 176 176 176z" />
<glyph glyph-name="bell" unicode="&#xf0f3;" horiz-adv-x="448"
d="M439.39 85.71c6 -6.44043 8.66016 -14.1602 8.61035 -21.71c-0.0996094 -16.4004 -12.9805 -32 -32.0996 -32h-383.801c-19.1191 0 -31.9893 15.5996 -32.0996 32c-0.0498047 7.5498 2.61035 15.2598 8.61035 21.71c19.3193 20.7598 55.4697 51.9902 55.4697 154.29
c0 77.7002 54.4795 139.9 127.939 155.16v20.8398c0 17.6699 14.3203 32 31.9805 32s31.9805 -14.3301 31.9805 -32v-20.8398c73.46 -15.2598 127.939 -77.46 127.939 -155.16c0 -102.3 36.1504 -133.53 55.4697 -154.29zM67.5303 80h312.939
c-21.2197 27.96 -44.4199 74.3203 -44.5293 159.42c0 0.200195 0.0595703 0.379883 0.0595703 0.580078c0 61.8604 -50.1396 112 -112 112s-112 -50.1396 -112 -112c0 -0.200195 0.0595703 -0.379883 0.0595703 -0.580078
c-0.109375 -85.0898 -23.3096 -131.45 -44.5293 -159.42zM224 -64c-35.3203 0 -63.9697 28.6504 -63.9697 64h127.939c0 -35.3496 -28.6494 -64 -63.9697 -64z" />
<glyph glyph-name="hospital" unicode="&#xf0f8;" horiz-adv-x="448"
d="M128 204v40c0 6.62695 5.37305 12 12 12h40c6.62695 0 12 -5.37305 12 -12v-40c0 -6.62695 -5.37305 -12 -12 -12h-40c-6.62695 0 -12 5.37305 -12 12zM268 192c-6.62695 0 -12 5.37305 -12 12v40c0 6.62695 5.37305 12 12 12h40c6.62695 0 12 -5.37305 12 -12v-40
c0 -6.62695 -5.37305 -12 -12 -12h-40zM192 108c0 -6.62695 -5.37305 -12 -12 -12h-40c-6.62695 0 -12 5.37305 -12 12v40c0 6.62695 5.37305 12 12 12h40c6.62695 0 12 -5.37305 12 -12v-40zM268 96c-6.62695 0 -12 5.37305 -12 12v40c0 6.62695 5.37305 12 12 12h40
c6.62695 0 12 -5.37305 12 -12v-40c0 -6.62695 -5.37305 -12 -12 -12h-40zM448 -28v-36h-448v36c0 6.62695 5.37305 12 12 12h19.5v378.965c0 11.6172 10.7451 21.0352 24 21.0352h88.5v40c0 13.2549 10.7451 24 24 24h112c13.2549 0 24 -10.7451 24 -24v-40h88.5
c13.2549 0 24 -9.41797 24 -21.0352v-378.965h19.5c6.62695 0 12 -5.37305 12 -12zM79.5 -15h112.5v67c0 6.62695 5.37305 12 12 12h40c6.62695 0 12 -5.37305 12 -12v-67h112.5v351h-64.5v-24c0 -13.2549 -10.7451 -24 -24 -24h-112c-13.2549 0 -24 10.7451 -24 24v24
h-64.5v-351zM266 384h-26v26c0 3.31152 -2.68848 6 -6 6h-20c-3.31152 0 -6 -2.68848 -6 -6v-26h-26c-3.31152 0 -6 -2.68848 -6 -6v-20c0 -3.31152 2.68848 -6 6 -6h26v-26c0 -3.31152 2.68848 -6 6 -6h20c3.31152 0 6 2.68848 6 6v26h26c3.31152 0 6 2.68848 6 6v20
c0 3.31152 -2.68848 6 -6 6z" />
<glyph glyph-name="plus-square" unicode="&#xf0fe;" horiz-adv-x="448"
d="M352 208v-32c0 -6.59961 -5.40039 -12 -12 -12h-88v-88c0 -6.59961 -5.40039 -12 -12 -12h-32c-6.59961 0 -12 5.40039 -12 12v88h-88c-6.59961 0 -12 5.40039 -12 12v32c0 6.59961 5.40039 12 12 12h88v88c0 6.59961 5.40039 12 12 12h32c6.59961 0 12 -5.40039 12 -12
v-88h88c6.59961 0 12 -5.40039 12 -12zM448 368v-352c0 -26.5 -21.5 -48 -48 -48h-352c-26.5 0 -48 21.5 -48 48v352c0 26.5 21.5 48 48 48h352c26.5 0 48 -21.5 48 -48zM400 22v340c0 3.2998 -2.7002 6 -6 6h-340c-3.2998 0 -6 -2.7002 -6 -6v-340
c0 -3.2998 2.7002 -6 6 -6h340c3.2998 0 6 2.7002 6 6z" />
<glyph glyph-name="circle" unicode="&#xf111;"
d="M256 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM256 -8c110.5 0 200 89.5 200 200s-89.5 200 -200 200s-200 -89.5 -200 -200s89.5 -200 200 -200z" />
<glyph glyph-name="smile" unicode="&#xf118;" horiz-adv-x="496"
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM168 208c-17.7002 0 -32 14.2998 -32 32s14.2998 32 32 32
s32 -14.2998 32 -32s-14.2998 -32 -32 -32zM328 208c-17.7002 0 -32 14.2998 -32 32s14.2998 32 32 32s32 -14.2998 32 -32s-14.2998 -32 -32 -32zM332 135.4c8.5 10.1992 23.7002 11.5 33.7998 3.09961c10.2002 -8.5 11.6006 -23.5996 3.10059 -33.7998
c-30 -36 -74.1006 -56.6006 -120.9 -56.6006s-90.9004 20.6006 -120.9 56.6006c-8.39941 10.2002 -7.09961 25.2998 3.10059 33.7998c10.0996 8.40039 25.2998 7.09961 33.7998 -3.09961c20.7998 -25.1006 51.5 -39.4004 84 -39.4004s63.2002 14.4004 84 39.4004z" />
<glyph glyph-name="frown" unicode="&#xf119;" horiz-adv-x="496"
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM168 208c-17.7002 0 -32 14.2998 -32 32s14.2998 32 32 32
s32 -14.2998 32 -32s-14.2998 -32 -32 -32zM328 272c17.7002 0 32 -14.2998 32 -32s-14.2998 -32 -32 -32s-32 14.2998 -32 32s14.2998 32 32 32zM248 144c40.2002 0 78 -17.7002 103.8 -48.5996c8.40039 -10.2002 7.10059 -25.3008 -3.09961 -33.8008
c-10.7002 -8.7998 -25.7002 -6.59961 -33.7998 3.10059c-16.6006 20 -41 31.3994 -66.9004 31.3994s-50.2998 -11.5 -66.9004 -31.3994c-8.5 -10.2002 -23.5996 -11.5 -33.7998 -3.10059c-10.2002 8.5 -11.5996 23.6006 -3.09961 33.8008
c25.7998 30.8994 63.5996 48.5996 103.8 48.5996z" />
<glyph glyph-name="meh" unicode="&#xf11a;" horiz-adv-x="496"
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM168 208c-17.7002 0 -32 14.2998 -32 32s14.2998 32 32 32
s32 -14.2998 32 -32s-14.2998 -32 -32 -32zM328 272c17.7002 0 32 -14.2998 32 -32s-14.2998 -32 -32 -32s-32 14.2998 -32 32s14.2998 32 32 32zM336 128c13.2002 0 24 -10.7998 24 -24s-10.7998 -24 -24 -24h-176c-13.2002 0 -24 10.7998 -24 24s10.7998 24 24 24h176z
" />
<glyph glyph-name="keyboard" unicode="&#xf11c;" horiz-adv-x="576"
d="M528 384c26.5098 0 48 -21.4902 48 -48v-288c0 -26.5098 -21.4902 -48 -48 -48h-480c-26.5098 0 -48 21.4902 -48 48v288c0 26.5098 21.4902 48 48 48h480zM536 48v288c0 4.41113 -3.58887 8 -8 8h-480c-4.41113 0 -8 -3.58887 -8 -8v-288c0 -4.41113 3.58887 -8 8 -8
h480c4.41113 0 8 3.58887 8 8zM170 178c0 -6.62695 -5.37305 -12 -12 -12h-28c-6.62695 0 -12 5.37305 -12 12v28c0 6.62695 5.37305 12 12 12h28c6.62695 0 12 -5.37305 12 -12v-28zM266 178c0 -6.62695 -5.37305 -12 -12 -12h-28c-6.62695 0 -12 5.37305 -12 12v28
c0 6.62695 5.37305 12 12 12h28c6.62695 0 12 -5.37305 12 -12v-28zM362 178c0 -6.62695 -5.37305 -12 -12 -12h-28c-6.62695 0 -12 5.37305 -12 12v28c0 6.62695 5.37305 12 12 12h28c6.62695 0 12 -5.37305 12 -12v-28zM458 178c0 -6.62695 -5.37305 -12 -12 -12h-28
c-6.62695 0 -12 5.37305 -12 12v28c0 6.62695 5.37305 12 12 12h28c6.62695 0 12 -5.37305 12 -12v-28zM122 96c0 -6.62695 -5.37305 -12 -12 -12h-28c-6.62695 0 -12 5.37305 -12 12v28c0 6.62695 5.37305 12 12 12h28c6.62695 0 12 -5.37305 12 -12v-28zM506 96
c0 -6.62695 -5.37305 -12 -12 -12h-28c-6.62695 0 -12 5.37305 -12 12v28c0 6.62695 5.37305 12 12 12h28c6.62695 0 12 -5.37305 12 -12v-28zM122 260c0 -6.62695 -5.37305 -12 -12 -12h-28c-6.62695 0 -12 5.37305 -12 12v28c0 6.62695 5.37305 12 12 12h28
c6.62695 0 12 -5.37305 12 -12v-28zM218 260c0 -6.62695 -5.37305 -12 -12 -12h-28c-6.62695 0 -12 5.37305 -12 12v28c0 6.62695 5.37305 12 12 12h28c6.62695 0 12 -5.37305 12 -12v-28zM314 260c0 -6.62695 -5.37305 -12 -12 -12h-28c-6.62695 0 -12 5.37305 -12 12v28
c0 6.62695 5.37305 12 12 12h28c6.62695 0 12 -5.37305 12 -12v-28zM410 260c0 -6.62695 -5.37305 -12 -12 -12h-28c-6.62695 0 -12 5.37305 -12 12v28c0 6.62695 5.37305 12 12 12h28c6.62695 0 12 -5.37305 12 -12v-28zM506 260c0 -6.62695 -5.37305 -12 -12 -12h-28
c-6.62695 0 -12 5.37305 -12 12v28c0 6.62695 5.37305 12 12 12h28c6.62695 0 12 -5.37305 12 -12v-28zM408 102c0 -6.62695 -5.37305 -12 -12 -12h-216c-6.62695 0 -12 5.37305 -12 12v16c0 6.62695 5.37305 12 12 12h216c6.62695 0 12 -5.37305 12 -12v-16z" />
<glyph glyph-name="calendar" unicode="&#xf133;" horiz-adv-x="448"
d="M400 384c26.5 0 48 -21.5 48 -48v-352c0 -26.5 -21.5 -48 -48 -48h-352c-26.5 0 -48 21.5 -48 48v352c0 26.5 21.5 48 48 48h48v52c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-52h128v52c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12
v-52h48zM394 -16c3.2998 0 6 2.7002 6 6v298h-352v-298c0 -3.2998 2.7002 -6 6 -6h340z" />
<glyph glyph-name="play-circle" unicode="&#xf144;"
d="M371.7 210c16.3994 -9.2002 16.3994 -32.9004 0 -42l-176 -101c-15.9004 -8.7998 -35.7002 2.59961 -35.7002 21v208c0 18.5 19.9004 29.7998 35.7002 21zM504 192c0 -137 -111 -248 -248 -248s-248 111 -248 248s111 248 248 248s248 -111 248 -248zM56 192
c0 -110.5 89.5 -200 200 -200s200 89.5 200 200s-89.5 200 -200 200s-200 -89.5 -200 -200z" />
<glyph glyph-name="minus-square" unicode="&#xf146;" horiz-adv-x="448"
d="M108 164c-6.59961 0 -12 5.40039 -12 12v32c0 6.59961 5.40039 12 12 12h232c6.59961 0 12 -5.40039 12 -12v-32c0 -6.59961 -5.40039 -12 -12 -12h-232zM448 368v-352c0 -26.5 -21.5 -48 -48 -48h-352c-26.5 0 -48 21.5 -48 48v352c0 26.5 21.5 48 48 48h352
c26.5 0 48 -21.5 48 -48zM400 22v340c0 3.2998 -2.7002 6 -6 6h-340c-3.2998 0 -6 -2.7002 -6 -6v-340c0 -3.2998 2.7002 -6 6 -6h340c3.2998 0 6 2.7002 6 6z" />
<glyph glyph-name="check-square" unicode="&#xf14a;" horiz-adv-x="448"
d="M400 416c26.5098 0 48 -21.4902 48 -48v-352c0 -26.5098 -21.4902 -48 -48 -48h-352c-26.5098 0 -48 21.4902 -48 48v352c0 26.5098 21.4902 48 48 48h352zM400 16v352h-352v-352h352zM364.136 257.724l-172.589 -171.204
c-4.70508 -4.66699 -12.3027 -4.63672 -16.9697 0.0683594l-90.7812 91.5156c-4.66699 4.70508 -4.63672 12.3037 0.0693359 16.9717l22.7188 22.5361c4.70508 4.66699 12.3027 4.63672 16.9697 -0.0693359l59.792 -60.2773l141.353 140.217
c4.70508 4.66699 12.3027 4.63672 16.9697 -0.0683594l22.5361 -22.7178c4.66699 -4.70605 4.63672 -12.3047 -0.0683594 -16.9717z" />
<glyph glyph-name="share-square" unicode="&#xf14d;" horiz-adv-x="576"
d="M561.938 289.94c18.75 -18.7402 18.75 -49.1406 0 -67.8809l-143.998 -144c-29.9727 -29.9727 -81.9404 -9.05273 -81.9404 33.9404v53.7998c-101.266 -7.83691 -99.625 -31.6406 -84.1104 -78.7598c14.2285 -43.0889 -33.4736 -79.248 -71.0195 -55.7402
c-51.6924 32.3057 -84.8701 83.0635 -84.8701 144.76c0 39.3408 12.2197 72.7402 36.3301 99.3008c19.8398 21.8398 47.7402 38.4697 82.9102 49.4199c36.7295 11.4395 78.3096 16.1094 120.76 17.9893v57.1982c0 42.9355 51.9258 63.9541 81.9404 33.9404zM384 112l144 144
l-144 144v-104.09c-110.86 -0.90332 -240 -10.5166 -240 -119.851c0 -52.1396 32.79 -85.6094 62.3096 -104.06c-39.8174 120.65 48.999 141.918 177.69 143.84v-103.84zM408.74 27.5068c6.14844 1.75684 15.5449 5.92383 20.9736 9.30273
c7.97656 4.95215 18.2861 -0.825195 18.2861 -10.2139v-42.5957c0 -26.5098 -21.4902 -48 -48 -48h-352c-26.5098 0 -48 21.4902 -48 48v352c0 26.5098 21.4902 48 48 48h132c6.62695 0 12 -5.37305 12 -12v-4.48633c0 -4.91699 -2.9873 -9.36914 -7.56934 -11.1514
c-13.7021 -5.33105 -26.3955 -11.5371 -38.0498 -18.585c-1.59668 -0.974609 -4.41016 -1.77051 -6.28027 -1.77734h-86.1006c-3.31152 0 -6 -2.68848 -6 -6v-340c0 -3.31152 2.68848 -6 6 -6h340c3.31152 0 6 2.68848 6 6v25.9658c0 5.37012 3.5791 10.0596 8.74023 11.541
z" />
<glyph glyph-name="compass" unicode="&#xf14e;" horiz-adv-x="496"
d="M347.94 318.14c16.6592 7.61035 33.8096 -9.54004 26.1992 -26.1992l-65.9697 -144.341c-2.73047 -5.97363 -9.7959 -13.0391 -15.7695 -15.7695l-144.341 -65.9697c-16.6592 -7.61035 -33.8096 9.5498 -26.1992 26.1992l65.9697 144.341
c2.73047 5.97363 9.7959 13.0391 15.7695 15.7695zM270.58 169.42c12.4697 12.4697 12.4697 32.6904 0 45.1602s-32.6904 12.4697 -45.1602 0s-12.4697 -32.6904 0 -45.1602s32.6904 -12.4697 45.1602 0zM248 440c136.97 0 248 -111.03 248 -248s-111.03 -248 -248 -248
s-248 111.03 -248 248s111.03 248 248 248zM248 -8c110.28 0 200 89.7197 200 200s-89.7197 200 -200 200s-200 -89.7197 -200 -200s89.7197 -200 200 -200z" />
<glyph glyph-name="caret-square-down" unicode="&#xf150;" horiz-adv-x="448"
d="M125.1 240h197.801c10.6992 0 16.0996 -13 8.5 -20.5l-98.9004 -98.2998c-4.7002 -4.7002 -12.2002 -4.7002 -16.9004 0l-98.8994 98.2998c-7.7002 7.5 -2.2998 20.5 8.39941 20.5zM448 368v-352c0 -26.5 -21.5 -48 -48 -48h-352c-26.5 0 -48 21.5 -48 48v352
c0 26.5 21.5 48 48 48h352c26.5 0 48 -21.5 48 -48zM400 22v340c0 3.2998 -2.7002 6 -6 6h-340c-3.2998 0 -6 -2.7002 -6 -6v-340c0 -3.2998 2.7002 -6 6 -6h340c3.2998 0 6 2.7002 6 6z" />
<glyph glyph-name="caret-square-up" unicode="&#xf151;" horiz-adv-x="448"
d="M322.9 144h-197.801c-10.6992 0 -16.0996 13 -8.5 20.5l98.9004 98.2998c4.7002 4.7002 12.2002 4.7002 16.9004 0l98.8994 -98.2998c7.7002 -7.5 2.2998 -20.5 -8.39941 -20.5zM448 368v-352c0 -26.5 -21.5 -48 -48 -48h-352c-26.5 0 -48 21.5 -48 48v352
c0 26.5 21.5 48 48 48h352c26.5 0 48 -21.5 48 -48zM400 22v340c0 3.2998 -2.7002 6 -6 6h-340c-3.2998 0 -6 -2.7002 -6 -6v-340c0 -3.2998 2.7002 -6 6 -6h340c3.2998 0 6 2.7002 6 6z" />
<glyph glyph-name="caret-square-right" unicode="&#xf152;" horiz-adv-x="448"
d="M176 93.0996v197.801c0 10.6992 13 16.0996 20.5 8.5l98.2998 -98.9004c4.7002 -4.7002 4.7002 -12.2002 0 -16.9004l-98.2998 -98.8994c-7.5 -7.7002 -20.5 -2.2998 -20.5 8.39941zM448 368v-352c0 -26.5 -21.5 -48 -48 -48h-352c-26.5 0 -48 21.5 -48 48v352
c0 26.5 21.5 48 48 48h352c26.5 0 48 -21.5 48 -48zM400 22v340c0 3.2998 -2.7002 6 -6 6h-340c-3.2998 0 -6 -2.7002 -6 -6v-340c0 -3.2998 2.7002 -6 6 -6h340c3.2998 0 6 2.7002 6 6z" />
<glyph glyph-name="file" unicode="&#xf15b;" horiz-adv-x="384"
d="M369.9 350.1c9 -9 14.0996 -21.2998 14.0996 -34v-332.1c0 -26.5 -21.5 -48 -48 -48h-288c-26.5 0 -48 21.5 -48 48v416c0 26.5 21.5 48 48 48.0996h204.1c12.7002 0 24.9004 -5.09961 33.9004 -14.0996zM332.1 320l-76.0996 76.0996v-76.0996h76.0996zM48 -16h288v288
h-104c-13.2998 0 -24 10.7002 -24 24v104h-160v-416z" />
<glyph glyph-name="file-alt" unicode="&#xf15c;" horiz-adv-x="384"
d="M288 200v-28c0 -6.59961 -5.40039 -12 -12 -12h-168c-6.59961 0 -12 5.40039 -12 12v28c0 6.59961 5.40039 12 12 12h168c6.59961 0 12 -5.40039 12 -12zM276 128c6.59961 0 12 -5.40039 12 -12v-28c0 -6.59961 -5.40039 -12 -12 -12h-168c-6.59961 0 -12 5.40039 -12 12
v28c0 6.59961 5.40039 12 12 12h168zM384 316.1v-332.1c0 -26.5 -21.5 -48 -48 -48h-288c-26.5 0 -48 21.5 -48 48v416c0 26.5 21.5 48 48 48h204.1c12.7002 0 24.9004 -5.09961 33.9004 -14.0996l83.9004 -83.9004c9 -8.90039 14.0996 -21.2002 14.0996 -33.9004z
M256 396.1v-76.0996h76.0996zM336 -16v288h-104c-13.2998 0 -24 10.7002 -24 24v104h-160v-416h288z" />
<glyph glyph-name="thumbs-up" unicode="&#xf164;"
d="M466.27 161.31c4.6748 -22.6465 0.864258 -44.5371 -8.98926 -62.9893c2.95898 -23.8682 -4.02148 -48.5654 -17.3398 -66.9902c-0.954102 -55.9072 -35.8232 -95.3301 -112.94 -95.3301c-7 0 -15 0.00976562 -22.2197 0.00976562
c-102.742 0 -133.293 38.9395 -177.803 39.9404c-3.56934 -13.7764 -16.085 -23.9502 -30.9775 -23.9502h-64c-17.6729 0 -32 14.3271 -32 32v240c0 17.6729 14.3271 32 32 32h98.7598c19.1455 16.9531 46.0137 60.6533 68.7598 83.4004
c13.667 13.667 10.1533 108.6 71.7607 108.6c57.5801 0 95.2695 -31.9355 95.2695 -104.73c0 -18.4092 -3.92969 -33.7295 -8.84961 -46.5391h36.4795c48.6025 0 85.8203 -41.5654 85.8203 -85.5801c0 -19.1504 -4.95996 -34.9902 -13.7305 -49.8408zM404.52 107.48
c21.5811 20.3838 18.6992 51.0645 5.21094 65.6191c9.44922 0 22.3594 18.9102 22.2695 37.8105c-0.0898438 18.9102 -16.71 37.8203 -37.8203 37.8203h-103.989c0 37.8193 28.3594 55.3691 28.3594 94.5391c0 23.75 0 56.7305 -47.2695 56.7305
c-18.9102 -18.9102 -9.45996 -66.1797 -37.8203 -94.54c-26.5596 -26.5703 -66.1797 -97.46 -94.54 -97.46h-10.9199v-186.17c53.6113 0 100.001 -37.8203 171.64 -37.8203h37.8203c35.5117 0 60.8203 17.1201 53.1201 65.9004
c15.2002 8.16016 26.5 36.4395 13.9395 57.5703zM88 16c0 13.2549 -10.7451 24 -24 24s-24 -10.7451 -24 -24s10.7451 -24 24 -24s24 10.7451 24 24z" />
<glyph glyph-name="thumbs-down" unicode="&#xf165;"
d="M466.27 222.69c8.77051 -14.8506 13.7305 -30.6904 13.7305 -49.8408c0 -44.0146 -37.2178 -85.5801 -85.8203 -85.5801h-36.4795c4.91992 -12.8096 8.84961 -28.1299 8.84961 -46.5391c0 -72.7949 -37.6895 -104.73 -95.2695 -104.73
c-61.6074 0 -58.0938 94.9326 -71.7607 108.6c-22.7461 22.7471 -49.6133 66.4473 -68.7598 83.4004h-7.05176c-5.5332 -9.56152 -15.8662 -16 -27.708 -16h-64c-17.6729 0 -32 14.3271 -32 32v240c0 17.6729 14.3271 32 32 32h64c8.11328 0 15.5146 -3.02539 21.1553 -8
h10.8447c40.9971 0 73.1953 39.9902 176.78 39.9902c7.21973 0 15.2197 0.00976562 22.2197 0.00976562c77.1172 0 111.986 -39.4229 112.94 -95.3301c13.3184 -18.4248 20.2979 -43.1221 17.3398 -66.9902c9.85352 -18.4521 13.6641 -40.3428 8.98926 -62.9893zM64 152
c13.2549 0 24 10.7451 24 24s-10.7451 24 -24 24s-24 -10.7451 -24 -24s10.7451 -24 24 -24zM394.18 135.27c21.1104 0 37.7305 18.9102 37.8203 37.8203c0.0898438 18.9004 -12.8203 37.8105 -22.2695 37.8105c13.4883 14.5547 16.3701 45.2354 -5.21094 65.6191
c12.5605 21.1309 1.26074 49.4102 -13.9395 57.5703c7.7002 48.7803 -17.6084 65.9004 -53.1201 65.9004h-37.8203c-71.6387 0 -118.028 -37.8203 -171.64 -37.8203v-186.17h10.9199c28.3604 0 67.9805 -70.8896 94.54 -97.46
c28.3604 -28.3604 18.9102 -75.6299 37.8203 -94.54c47.2695 0 47.2695 32.9805 47.2695 56.7305c0 39.1699 -28.3594 56.7197 -28.3594 94.5391h103.989z" />
<glyph glyph-name="sun" unicode="&#xf185;"
d="M494.2 226.1c11.2002 -7.59961 17.7998 -20.0996 17.8994 -33.6992c0 -13.4004 -6.69922 -26 -17.7998 -33.5l-59.7998 -40.5l13.7002 -71c2.5 -13.2002 -1.60059 -26.8008 -11.1006 -36.3008s-22.8994 -13.7998 -36.2998 -11.0996l-70.8994 13.7002l-40.4004 -59.9004
c-7.5 -11.0996 -20.0996 -17.7998 -33.5 -17.7998s-26 6.7002 -33.5 17.9004l-40.4004 59.8994l-70.7998 -13.7002c-13.3994 -2.59961 -26.7998 1.60059 -36.2998 11.1006s-13.7002 23.0996 -11.0996 36.2998l13.6992 71l-59.7998 40.5
c-11.0996 7.5 -17.7998 20 -17.7998 33.5s6.59961 26 17.7998 33.5996l59.7998 40.5l-13.6992 71c-2.60059 13.2002 1.59961 26.7002 11.0996 36.3008c9.5 9.59961 23 13.6992 36.2998 11.1992l70.7998 -13.6992l40.4004 59.8994c15.0996 22.2998 51.9004 22.2998 67 0
l40.4004 -59.8994l70.8994 13.6992c13 2.60059 26.6006 -1.59961 36.2002 -11.0996c9.5 -9.59961 13.7002 -23.2002 11.0996 -36.4004l-13.6992 -71zM381.3 140.5l76.7998 52.0996l-76.7998 52l17.6006 91.1006l-91 -17.6006l-51.9004 76.9004l-51.7998 -76.7998
l-91 17.5996l17.5996 -91.2002l-76.7998 -52l76.7998 -52l-17.5996 -91.1992l90.8994 17.5996l51.9004 -77l51.9004 76.9004l91 -17.6006zM256 296c57.2998 0 104 -46.7002 104 -104s-46.7002 -104 -104 -104s-104 46.7002 -104 104s46.7002 104 104 104zM256 136
c30.9004 0 56 25.0996 56 56s-25.0996 56 -56 56s-56 -25.0996 -56 -56s25.0996 -56 56 -56z" />
<glyph glyph-name="moon" unicode="&#xf186;"
d="M279.135 -64c-141.424 0 -256 114.64 -256 256c0 141.425 114.641 256 256 256c13.0068 -0.00195312 33.9443 -1.91797 46.7354 -4.27734c44.0205 -8.13086 53.7666 -66.8691 15.0215 -88.9189c-41.374 -23.5439 -67.4336 -67.4121 -67.4336 -115.836
c0 -83.5234 75.9238 -146.475 158.272 -130.792c43.6904 8.32129 74.5186 -42.5693 46.248 -77.4004c-47.8613 -58.9717 -120.088 -94.7754 -198.844 -94.7754zM279.135 400c-114.875 0 -208 -93.125 -208 -208s93.125 -208 208 -208
c65.2314 0 123.439 30.0361 161.575 77.0244c-111.611 -21.2568 -215.252 64.0957 -215.252 177.943c0 67.5127 36.9326 126.392 91.6934 157.555c-12.3271 2.27637 -25.0312 3.47754 -38.0166 3.47754z" />
<glyph glyph-name="caret-square-left" unicode="&#xf191;" horiz-adv-x="448"
d="M272 290.9v-197.801c0 -10.6992 -13 -16.0996 -20.5 -8.5l-98.2998 98.9004c-4.7002 4.7002 -4.7002 12.2002 0 16.9004l98.2998 98.8994c7.5 7.7002 20.5 2.2998 20.5 -8.39941zM448 368v-352c0 -26.5 -21.5 -48 -48 -48h-352c-26.5 0 -48 21.5 -48 48v352
c0 26.5 21.5 48 48 48h352c26.5 0 48 -21.5 48 -48zM400 22v340c0 3.2998 -2.7002 6 -6 6h-340c-3.2998 0 -6 -2.7002 -6 -6v-340c0 -3.2998 2.7002 -6 6 -6h340c3.2998 0 6 2.7002 6 6z" />
<glyph glyph-name="dot-circle" unicode="&#xf192;"
d="M256 392c-110.549 0 -200 -89.4678 -200 -200c0 -110.549 89.4678 -200 200 -200c110.549 0 200 89.4678 200 200c0 110.549 -89.4678 200 -200 200zM256 440c136.967 0 248 -111.033 248 -248s-111.033 -248 -248 -248s-248 111.033 -248 248s111.033 248 248 248z
M256 272c44.1826 0 80 -35.8174 80 -80s-35.8174 -80 -80 -80s-80 35.8174 -80 80s35.8174 80 80 80z" />
<glyph glyph-name="building" unicode="&#xf1ad;" horiz-adv-x="448"
d="M128 300v40c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-40c0 -6.59961 -5.40039 -12 -12 -12h-40c-6.59961 0 -12 5.40039 -12 12zM268 288c-6.59961 0 -12 5.40039 -12 12v40c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-40
c0 -6.59961 -5.40039 -12 -12 -12h-40zM140 192c-6.59961 0 -12 5.40039 -12 12v40c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-40c0 -6.59961 -5.40039 -12 -12 -12h-40zM268 192c-6.59961 0 -12 5.40039 -12 12v40c0 6.59961 5.40039 12 12 12h40
c6.59961 0 12 -5.40039 12 -12v-40c0 -6.59961 -5.40039 -12 -12 -12h-40zM192 108c0 -6.59961 -5.40039 -12 -12 -12h-40c-6.59961 0 -12 5.40039 -12 12v40c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-40zM268 96c-6.59961 0 -12 5.40039 -12 12v40
c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-40c0 -6.59961 -5.40039 -12 -12 -12h-40zM448 -28v-36h-448v36c0 6.59961 5.40039 12 12 12h19.5v440c0 13.2998 10.7002 24 24 24h337c13.2998 0 24 -10.7002 24 -24v-440h19.5
c6.59961 0 12 -5.40039 12 -12zM79.5 -15h112.5v67c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-67h112.5v414l-288.5 1z" />
<glyph glyph-name="file-pdf" unicode="&#xf1c1;" horiz-adv-x="384"
d="M369.9 350.1c9 -9 14.0996 -21.2998 14.0996 -34v-332.1c0 -26.5 -21.5 -48 -48 -48h-288c-26.5 0 -48 21.5 -48 48v416c0 26.5 21.5 48 48 48.0996h204.1c12.7002 0 24.9004 -5.09961 33.9004 -14.0996zM332.1 320l-76.0996 76.0996v-76.0996h76.0996zM48 -16h288v288
h-104c-13.2998 0 -24 10.7002 -24 24v104h-160v-416zM298.2 127.7c10.5 -10.5 8 -38.7002 -17.5 -38.7002c-14.7998 0 -36.9004 6.7998 -55.7998 17c-21.6006 -3.59961 -46 -12.7002 -68.4004 -20.0996c-50.0996 -86.4004 -79.4004 -47 -76.0996 -31.2002
c4 20 31 35.8994 51 46.2002c10.5 18.3994 25.3994 50.5 35.3994 74.3994c-7.39941 28.6006 -11.3994 51 -7 67.1006c4.7998 17.6992 38.4004 20.2998 42.6006 -5.90039c4.69922 -15.4004 -1.5 -39.9004 -5.40039 -56c8.09961 -21.2998 19.5996 -35.7998 36.7998 -46.2998
c17.4004 2.2002 52.2002 5.5 64.4004 -6.5zM100.1 49.9004c0 -0.700195 11.4004 4.69922 30.4004 35c-5.90039 -5.5 -25.2998 -21.3008 -30.4004 -35zM181.7 240.5c-2.5 0 -2.60059 -26.9004 1.7998 -40.7998c4.90039 8.7002 5.59961 40.7998 -1.7998 40.7998zM157.3 103.9
c15.9004 6.09961 34 14.8994 54.7998 19.1992c-11.1992 8.30078 -21.7998 20.4004 -30.0996 35.5c-6.7002 -17.6992 -15 -37.7998 -24.7002 -54.6992zM288.9 108.9c3.59961 2.39941 -2.2002 10.3994 -37.3008 7.7998c32.3008 -13.7998 37.3008 -7.7998 37.3008 -7.7998z" />
<glyph glyph-name="file-word" unicode="&#xf1c2;" horiz-adv-x="384"
d="M369.9 350.1c9 -9 14.0996 -21.2998 14.0996 -34v-332.1c0 -26.5 -21.5 -48 -48 -48h-288c-26.5 0 -48 21.5 -48 48v416c0 26.5 21.5 48 48 48.0996h204.1c12.7002 0 24.9004 -5.09961 33.9004 -14.0996zM332.1 320l-76.0996 76.0996v-76.0996h76.0996zM48 -16h288v288
h-104c-13.2998 0 -24 10.7002 -24 24v104h-160v-416zM268.1 192v0.200195h15.8008c7.7998 0 13.5 -7.2998 11.5996 -14.9004c-4.2998 -17 -13.7002 -54.0996 -34.5 -136c-1.2998 -5.39941 -6.09961 -9.09961 -11.5996 -9.09961h-24.7002
c-5.5 0 -10.2998 3.7998 -11.6006 9.09961c-5.2998 20.9004 -17.7998 71 -17.8994 71.4004l-2.90039 17.2998c-0.5 -5.2998 -1.5 -11.0996 -3 -17.2998l-17.8994 -71.4004c-1.30078 -5.39941 -6.10059 -9.09961 -11.6006 -9.09961h-25.2002
c-5.59961 0 -10.3994 3.7002 -11.6992 9.09961c-6.5 26.5 -25.2002 103.4 -33.2002 136c-1.7998 7.5 3.89941 14.7998 11.7002 14.7998h16.7998c5.7998 0 10.7002 -4.09961 11.7998 -9.69922c5 -25.7002 18.4004 -93.8008 19.0996 -99
c0.300781 -1.7002 0.400391 -3.10059 0.5 -4.2002c0.800781 7.5 0.400391 4.7002 24.8008 103.7c1.39941 5.2998 6.19922 9.09961 11.6992 9.09961h13.3008c5.59961 0 10.3994 -3.7998 11.6992 -9.2002c23.9004 -99.7002 22.8008 -94.3994 23.6006 -99.5
c0.299805 -1.7002 0.5 -3.09961 0.700195 -4.2998c0.599609 8.09961 0.399414 5.7998 21 103.5c1.09961 5.5 6 9.5 11.6992 9.5z" />
<glyph glyph-name="file-excel" unicode="&#xf1c3;" horiz-adv-x="384"
d="M369.9 350.1c9 -9 14.0996 -21.2998 14.0996 -34v-332.1c0 -26.5 -21.5 -48 -48 -48h-288c-26.5 0 -48 21.5 -48 48v416c0 26.5 21.5 48 48 48.0996h204.1c12.7002 0 24.9004 -5.09961 33.9004 -14.0996zM332.1 320l-76.0996 76.0996v-76.0996h76.0996zM48 -16h288v288
h-104c-13.2998 0 -24 10.7002 -24 24v104h-160v-416zM260 224c9.2002 0 15 -10 10.2998 -18c-16 -27.5 -45.5996 -76.9004 -46.2998 -78l46.4004 -78c4.59961 -8 -1.10059 -18 -10.4004 -18h-28.7998c-4.40039 0 -8.5 2.40039 -10.6006 6.2998
c-22.6992 41.7998 -13.6992 27.5 -28.5996 57.7002c-5.59961 -12.7002 -6.90039 -17.7002 -28.5996 -57.7002c-2.10059 -3.89941 -6.10059 -6.2998 -10.5 -6.2998h-28.9004c-9.2998 0 -15.0996 10 -10.4004 18l46.3008 78l-46.3008 78c-4.59961 8 1.10059 18 10.4004 18
h28.9004c4.39941 0 8.5 -2.40039 10.5996 -6.2998c21.7002 -40.4004 14.7002 -28.6006 28.5996 -57.7002c6.40039 15.2998 10.6006 24.5996 28.6006 57.7002c2.09961 3.89941 6.09961 6.2998 10.5 6.2998h28.7998z" />
<glyph glyph-name="file-powerpoint" unicode="&#xf1c4;" horiz-adv-x="384"
d="M369.9 350.1c9 -9 14.0996 -21.2998 14.0996 -34v-332.1c0 -26.5 -21.5 -48 -48 -48h-288c-26.5 0 -48 21.5 -48 48v416c0 26.5 21.5 48 48 48.0996h204.1c12.7002 0 24.9004 -5.09961 33.9004 -14.0996zM332.1 320l-76.0996 76.0996v-76.0996h76.0996zM48 -16h288v288
h-104c-13.2998 0 -24 10.7002 -24 24v104h-160v-416zM120 44v168c0 6.59961 5.40039 12 12 12h69.2002c36.7002 0 62.7998 -27 62.7998 -66.2998c0 -74.2998 -68.7002 -66.5 -95.5 -66.5v-47.2002c0 -6.59961 -5.40039 -12 -12 -12h-24.5c-6.59961 0 -12 5.40039 -12 12z
M168.5 131.4h23c7.90039 0 13.9004 2.39941 18.0996 7.19922c8.5 9.80078 8.40039 28.5 0.100586 37.8008c-4.10059 4.59961 -9.90039 7 -17.4004 7h-23.8994v-52h0.0996094z" />
<glyph glyph-name="file-image" unicode="&#xf1c5;" horiz-adv-x="384"
d="M369.9 350.1c9 -9 14.0996 -21.2998 14.0996 -34v-332.1c0 -26.5 -21.5 -48 -48 -48h-288c-26.5 0 -48 21.5 -48 48v416c0 26.5 21.5 48 48 48.0996h204.1c12.7002 0 24.9004 -5.09961 33.9004 -14.0996zM332.1 320l-76.0996 76.0996v-76.0996h76.0996zM48 -16h288v288
h-104c-13.2998 0 -24 10.7002 -24 24v104h-160v-416zM80 32v64l39.5 39.5c4.7002 4.7002 12.2998 4.7002 17 0l39.5 -39.5l87.5 87.5c4.7002 4.7002 12.2998 4.7002 17 0l23.5 -23.5v-128h-224zM128 272c26.5 0 48 -21.5 48 -48s-21.5 -48 -48 -48s-48 21.5 -48 48
s21.5 48 48 48z" />
<glyph glyph-name="file-archive" unicode="&#xf1c6;" horiz-adv-x="384"
d="M128.3 288h32v-32h-32v32zM192.3 384v-32h-32v32h32zM128.3 352h32v-32h-32v32zM192.3 320v-32h-32v32h32zM369.9 350.1c9 -9 14.0996 -21.2998 14.0996 -34v-332.1c0 -26.5 -21.5 -48 -48 -48h-288c-26.5 0 -48 21.5 -48 48v416c0 26.5 21.5 48 48 48.0996h204.1
c12.7002 0 24.9004 -5.09961 33.9004 -14.0996zM256 396.1v-76.0996h76.0996zM336 -16v288h-104c-13.2998 0 -24 10.7002 -24 24v104h-48.2998v-16h-32v16h-79.7002v-416h288zM194.2 182.3l17.2998 -87.7002c6.40039 -32.3994 -18.4004 -62.5996 -51.5 -62.5996
c-33.2002 0 -58 30.4004 -51.4004 62.9004l19.7002 97.0996v32h32v-32h22.1006c5.7998 0 10.6992 -4.09961 11.7998 -9.7002zM160.3 57.9004c17.9004 0 32.4004 12.0996 32.4004 27c0 14.8994 -14.5 27 -32.4004 27c-17.8994 0 -32.3994 -12.1006 -32.3994 -27
c0 -14.9004 14.5 -27 32.3994 -27zM192.3 256v-32h-32v32h32z" />
<glyph glyph-name="file-audio" unicode="&#xf1c7;" horiz-adv-x="384"
d="M369.941 350.059c7.75977 -7.75977 14.0586 -22.9658 14.0586 -33.9404v-332.118c0 -26.5098 -21.4902 -48 -48 -48h-288c-26.5098 0 -48 21.4902 -48 48v416c0 26.5098 21.4902 48 48 48h204.118c10.9746 0 26.1807 -6.29883 33.9404 -14.0586zM332.118 320
l-76.1182 76.1182v-76.1182h76.1182zM48 -16h288v288h-104c-13.2549 0 -24 10.7451 -24 24v104h-160v-416zM192 60.0244c0 -10.6914 -12.9258 -16.0459 -20.4854 -8.48535l-35.5146 35.9746h-28c-6.62695 0 -12 5.37305 -12 12v56c0 6.62695 5.37305 12 12 12h28
l35.5146 36.9473c7.56055 7.56055 20.4854 2.20605 20.4854 -8.48535v-135.951zM233.201 107.154c9.05078 9.29688 9.05957 24.1328 0.000976562 33.4385c-22.1494 22.752 12.2344 56.2461 34.3945 33.4814c27.1982 -27.9404 27.2119 -72.4443 0.000976562 -100.401
c-21.793 -22.3857 -56.9463 10.3154 -34.3965 33.4814z" />
<glyph glyph-name="file-video" unicode="&#xf1c8;" horiz-adv-x="384"
d="M369.941 350.059c7.75977 -7.75977 14.0586 -22.9658 14.0586 -33.9404v-332.118c0 -26.5098 -21.4902 -48 -48 -48h-288c-26.5098 0 -48 21.4902 -48 48v416c0 26.5098 21.4902 48 48 48h204.118c10.9746 0 26.1807 -6.29883 33.9404 -14.0586zM332.118 320
l-76.1182 76.1182v-76.1182h76.1182zM48 -16h288v288h-104c-13.2549 0 -24 10.7451 -24 24v104h-160v-416zM276.687 195.303c10.0049 10.0049 27.3135 2.99707 27.3135 -11.3135v-111.976c0 -14.2939 -17.2959 -21.332 -27.3135 -11.3135l-52.6865 52.6738v-37.374
c0 -11.0459 -8.9541 -20 -20 -20h-104c-11.0459 0 -20 8.9541 -20 20v104c0 11.0459 8.9541 20 20 20h104c11.0459 0 20 -8.9541 20 -20v-37.374z" />
<glyph glyph-name="file-code" unicode="&#xf1c9;" horiz-adv-x="384"
d="M149.9 98.9004c3.5 -3.30078 3.69922 -8.90039 0.399414 -12.4004l-17.3994 -18.5996c-1.60059 -1.80078 -4 -2.80078 -6.40039 -2.80078c-2.2002 0 -4.40039 0.900391 -6 2.40039l-57.7002 54.0996c-3.7002 3.40039 -3.7002 9.30078 0 12.8008l57.7002 54.0996
c3.40039 3.2998 9 3.2002 12.4004 -0.400391l17.3994 -18.5996l0.200195 -0.200195c3.2002 -3.59961 2.7998 -9.2002 -0.799805 -12.3994l-32.7998 -28.9004l32.7998 -28.9004zM369.9 350.1c9 -9 14.0996 -21.2998 14.0996 -34v-332.1c0 -26.5 -21.5 -48 -48 -48h-288
c-26.5 0 -48 21.5 -48 48v416c0 26.5 21.5 48 48 48.0996h204.1c12.7002 0 24.9004 -5.09961 33.9004 -14.0996zM256 396.1v-76.0996h76.0996zM336 -16v288h-104c-13.2998 0 -24 10.7002 -24 24v104h-160v-416h288zM209.6 234l24.4004 -7
c4.7002 -1.2998 7.40039 -6.2002 6 -10.9004l-54.7002 -188.199c-1.2998 -4.60059 -6.2002 -7.40039 -10.8994 -6l-24.4004 7.09961c-4.7002 1.2998 -7.40039 6.2002 -6 10.9004l54.7002 188.1c1.39941 4.7002 6.2002 7.40039 10.8994 6zM234.1 157.1
c-3.5 3.30078 -3.69922 8.90039 -0.399414 12.4004l17.3994 18.5996c3.30078 3.60059 8.90039 3.7002 12.4004 0.400391l57.7002 -54.0996c3.7002 -3.40039 3.7002 -9.30078 0 -12.8008l-57.7002 -54.0996c-3.5 -3.2998 -9.09961 -3.09961 -12.4004 0.400391
l-17.3994 18.5996l-0.200195 0.200195c-3.2002 3.59961 -2.7998 9.2002 0.799805 12.3994l32.7998 28.9004l-32.7998 28.9004z" />
<glyph glyph-name="life-ring" unicode="&#xf1cd;"
d="M256 -56c-136.967 0 -248 111.033 -248 248s111.033 248 248 248s248 -111.033 248 -248s-111.033 -248 -248 -248zM152.602 20.7197c63.2178 -38.3184 143.579 -38.3184 206.797 0l-53.4111 53.4111c-31.8467 -13.5215 -68.168 -13.5059 -99.9746 0zM336 192
c0 44.1123 -35.8877 80 -80 80s-80 -35.8877 -80 -80s35.8877 -80 80 -80s80 35.8877 80 80zM427.28 88.6016c38.3184 63.2178 38.3184 143.579 0 206.797l-53.4111 -53.4111c13.5215 -31.8467 13.5049 -68.168 0 -99.9746zM359.397 363.28
c-63.2168 38.3184 -143.578 38.3184 -206.796 0l53.4111 -53.4111c31.8457 13.5215 68.167 13.5049 99.9736 0zM84.7197 295.398c-38.3184 -63.2178 -38.3184 -143.579 0 -206.797l53.4111 53.4111c-13.5215 31.8467 -13.5059 68.168 0 99.9746z" />
<glyph glyph-name="paper-plane" unicode="&#xf1d8;"
d="M440 441.5c34.5996 19.9004 77.5996 -8.7998 71.5 -48.9004l-59.4004 -387.199c-2.2998 -14.5 -11.0996 -27.3008 -23.8994 -34.5c-7.2998 -4.10059 -15.4004 -6.2002 -23.6006 -6.2002c-6.19922 0 -12.3994 1.2002 -18.2998 3.59961l-111.899 46.2002l-43.8008 -59.0996
c-27.3994 -36.9004 -86.5996 -17.8008 -86.5996 28.5996v84.4004l-114.3 47.2998c-36.7998 15.0996 -40.1006 66 -5.7002 85.8994zM192 -16l36.5996 49.5l-36.5996 15.0996v-64.5996zM404.6 12.7002l59.4004 387.3l-416 -240l107.8 -44.5996l211.5 184.3
c14.2002 12.2998 34.4004 -5.7002 23.7002 -21.2002l-140.2 -202.3z" />
<glyph glyph-name="futbol" unicode="&#xf1e3;" horiz-adv-x="496"
d="M483.8 268.6c42.2998 -130.199 -29 -270.1 -159.2 -312.399c-25.5 -8.2998 -51.2998 -12.2002 -76.6992 -12.2002c-104.5 0 -201.7 66.5996 -235.7 171.4c-42.2998 130.199 29 270.1 159.2 312.399c25.5 8.2998 51.2998 12.2002 76.6992 12.2002
c104.5 0 201.7 -66.5996 235.7 -171.4zM409.3 74.9004c6.10059 8.39941 12.1006 16.8994 16.7998 26.1992c14.3008 28.1006 21.5 58.5 21.7002 89.2002l-38.8994 36.4004l-71.1006 -22.1006l-24.3994 -75.1992l43.6992 -60.9004zM409.3 310.3
c-24.5 33.4004 -58.7002 58.4004 -97.8994 71.4004l-47.4004 -26.2002v-73.7998l64.2002 -46.5l70.7002 22zM184.9 381.6c-39.9004 -13.2998 -73.5 -38.5 -97.8008 -71.8994l10.1006 -52.5l70.5996 -22l64.2002 46.5v73.7998zM139 68.5l43.5 61.7002l-24.2998 74.2998
l-71.1006 22.2002l-39 -36.4004c0.5 -55.7002 23.4004 -95.2002 37.8008 -115.3zM187.2 1.5c64.0996 -20.4004 115.5 -1.7998 121.7 0l22.3994 48.0996l-44.2998 61.7002h-78.5996l-43.6006 -61.7002z" />
<glyph glyph-name="newspaper" unicode="&#xf1ea;" horiz-adv-x="576"
d="M552 384c13.2549 0 24 -10.7451 24 -24v-336c0 -13.2549 -10.7451 -24 -24 -24h-496c-30.9277 0 -56 25.0723 -56 56v272c0 13.2549 10.7451 24 24 24h42.752c6.60547 18.623 24.3896 32 45.248 32h440zM48 56c0 -4.41113 3.58887 -8 8 -8s8 3.58887 8 8v248h-16v-248z
M528 48v288h-416v-280c0 -2.7168 -0.204102 -5.38574 -0.578125 -8h416.578zM172 168c-6.62695 0 -12 5.37305 -12 12v96c0 6.62695 5.37305 12 12 12h136c6.62695 0 12 -5.37305 12 -12v-96c0 -6.62695 -5.37305 -12 -12 -12h-136zM200 248v-40h80v40h-80zM160 108v24
c0 6.62695 5.37305 12 12 12h136c6.62695 0 12 -5.37305 12 -12v-24c0 -6.62695 -5.37305 -12 -12 -12h-136c-6.62695 0 -12 5.37305 -12 12zM352 108v24c0 6.62695 5.37305 12 12 12h104c6.62695 0 12 -5.37305 12 -12v-24c0 -6.62695 -5.37305 -12 -12 -12h-104
c-6.62695 0 -12 5.37305 -12 12zM352 252v24c0 6.62695 5.37305 12 12 12h104c6.62695 0 12 -5.37305 12 -12v-24c0 -6.62695 -5.37305 -12 -12 -12h-104c-6.62695 0 -12 5.37305 -12 12zM352 180v24c0 6.62695 5.37305 12 12 12h104c6.62695 0 12 -5.37305 12 -12v-24
c0 -6.62695 -5.37305 -12 -12 -12h-104c-6.62695 0 -12 5.37305 -12 12z" />
<glyph glyph-name="bell-slash" unicode="&#xf1f6;" horiz-adv-x="640"
d="M633.99 -23.0195c6.91016 -5.52051 8.01953 -15.5908 2.5 -22.4902l-10 -12.4902c-5.53027 -6.88965 -15.5898 -8.00977 -22.4902 -2.49023l-598 467.51c-6.90039 5.52051 -8.01953 15.5908 -2.49023 22.4902l10 12.4902
c5.52051 6.90039 15.5898 8.00977 22.4902 2.49023zM163.53 80h182.84l61.3994 -48h-279.659c-19.1201 0 -31.9902 15.5996 -32.1006 32c-0.0498047 7.5498 2.61035 15.2598 8.61035 21.71c18.3701 19.7402 51.5703 49.6904 54.8398 140.42l45.4697 -35.5498
c-6.91992 -54.7803 -24.6895 -88.5498 -41.3994 -110.58zM320 352c-23.3496 0 -45 -7.17969 -62.9404 -19.4004l-38.1699 29.8408c19.6807 15.7793 43.1104 27.3096 69.1299 32.7197v20.8398c0 17.6699 14.3203 32 31.9805 32s31.9805 -14.3301 31.9805 -32v-20.8398
c73.46 -15.2598 127.939 -77.46 127.939 -155.16c0 -41.3604 6.03027 -70.7197 14.3398 -92.8496l-59.5293 46.54c-1.63086 13.96 -2.77051 28.8896 -2.79004 45.7295c0 0.200195 0.0595703 0.379883 0.0595703 0.580078c0 61.8604 -50.1396 112 -112 112zM320 -64
c-35.3203 0 -63.9697 28.6504 -63.9697 64h127.939c0 -35.3496 -28.6494 -64 -63.9697 -64z" />
<glyph glyph-name="copyright" unicode="&#xf1f9;"
d="M256 440c136.967 0 248 -111.033 248 -248s-111.033 -248 -248 -248s-248 111.033 -248 248s111.033 248 248 248zM256 -8c110.549 0 200 89.4678 200 200c0 110.549 -89.4678 200 -200 200c-110.549 0 -200 -89.4688 -200 -200c0 -110.549 89.4678 -200 200 -200z
M363.351 93.0645c-9.61328 -9.71289 -45.5293 -41.3965 -104.064 -41.3965c-82.4297 0 -140.484 61.4248 -140.484 141.567c0 79.1514 60.2754 139.4 139.763 139.4c55.5303 0 88.7373 -26.6201 97.5928 -34.7783c2.13379 -1.96289 3.86523 -5.9082 3.86523 -8.80762
c0 -1.95508 -0.864258 -4.87402 -1.92969 -6.51465l-18.1543 -28.1133c-3.8418 -5.9502 -11.9668 -7.28223 -17.499 -2.9209c-8.5957 6.77637 -31.8145 22.5381 -61.708 22.5381c-48.3037 0 -77.916 -35.3301 -77.916 -80.082c0 -41.5889 26.8877 -83.6924 78.2764 -83.6924
c32.6572 0 56.8428 19.0391 65.7266 27.2256c5.26953 4.85645 13.5957 4.03906 17.8193 -1.73828l19.8652 -27.1699c1.28613 -1.74512 2.33008 -4.91992 2.33008 -7.08789c0 -2.72363 -1.56055 -6.5 -3.48242 -8.42969z" />
<glyph glyph-name="closed-captioning" unicode="&#xf20a;"
d="M464 384c26.5 0 48 -21.5 48 -48v-288c0 -26.5 -21.5 -48 -48 -48h-416c-26.5 0 -48 21.5 -48 48v288c0 26.5 21.5 48 48 48h416zM458 48c3.2998 0 6 2.7002 6 6v276c0 3.2998 -2.7002 6 -6 6h-404c-3.2998 0 -6 -2.7002 -6 -6v-276c0 -3.2998 2.7002 -6 6 -6h404z
M246.9 133.7c1.69922 -2.40039 1.5 -5.60059 -0.5 -7.7002c-53.6006 -56.7998 -172.801 -32.0996 -172.801 67.9004c0 97.2998 121.7 119.5 172.5 70.0996c2.10059 -2 2.5 -3.2002 1 -5.7002l-17.5 -30.5c-1.89941 -3.09961 -6.19922 -4 -9.09961 -1.7002
c-40.7998 32 -94.5996 14.9004 -94.5996 -31.1992c0 -48 51 -70.5 92.1992 -32.6006c2.80078 2.5 7.10059 2.10059 9.2002 -0.899414zM437.3 133.7c1.7002 -2.40039 1.5 -5.60059 -0.5 -7.7002c-53.5996 -56.9004 -172.8 -32.0996 -172.8 67.9004
c0 97.2998 121.7 119.5 172.5 70.0996c2.09961 -2 2.5 -3.2002 1 -5.7002l-17.5 -30.5c-1.90039 -3.09961 -6.2002 -4 -9.09961 -1.7002c-40.8008 32 -94.6006 14.9004 -94.6006 -31.1992c0 -48 51 -70.5 92.2002 -32.6006c2.7998 2.5 7.09961 2.10059 9.2002 -0.899414z
" />
<glyph glyph-name="object-group" unicode="&#xf247;"
d="M500 320h-12v-256h12c6.62695 0 12 -5.37305 12 -12v-72c0 -6.62695 -5.37305 -12 -12 -12h-72c-6.62695 0 -12 5.37305 -12 12v12h-320v-12c0 -6.62695 -5.37305 -12 -12 -12h-72c-6.62695 0 -12 5.37305 -12 12v72c0 6.62695 5.37305 12 12 12h12v256h-12
c-6.62695 0 -12 5.37305 -12 12v72c0 6.62695 5.37305 12 12 12h72c6.62695 0 12 -5.37305 12 -12v-12h320v12c0 6.62695 5.37305 12 12 12h72c6.62695 0 12 -5.37305 12 -12v-72c0 -6.62695 -5.37305 -12 -12 -12zM448 384v-32h32v32h-32zM32 384v-32h32v32h-32zM64 0v32
h-32v-32h32zM480 0v32h-32v-32h32zM440 64v256h-12c-6.62695 0 -12 5.37305 -12 12v12h-320v-12c0 -6.62695 -5.37305 -12 -12 -12h-12v-256h12c6.62695 0 12 -5.37305 12 -12v-12h320v12c0 6.62695 5.37305 12 12 12h12zM404 256c6.62695 0 12 -5.37207 12 -12v-168
c0 -6.62793 -5.37305 -12 -12 -12h-200c-6.62695 0 -12 5.37207 -12 12v52h-84c-6.62695 0 -12 5.37207 -12 12v168c0 6.62793 5.37305 12 12 12h200c6.62695 0 12 -5.37207 12 -12v-52h84zM136 280v-112h144v112h-144zM376 104v112h-56v-76
c0 -6.62793 -5.37305 -12 -12 -12h-76v-24h144z" />
<glyph glyph-name="object-ungroup" unicode="&#xf248;" horiz-adv-x="576"
d="M564 224h-12v-160h12c6.62695 0 12 -5.37305 12 -12v-72c0 -6.62695 -5.37305 -12 -12 -12h-72c-6.62695 0 -12 5.37305 -12 12v12h-224v-12c0 -6.62695 -5.37305 -12 -12 -12h-72c-6.62695 0 -12 5.37305 -12 12v72c0 6.62695 5.37305 12 12 12h12v24h-88v-12
c0 -6.62695 -5.37305 -12 -12 -12h-72c-6.62695 0 -12 5.37305 -12 12v72c0 6.62695 5.37305 12 12 12h12v160h-12c-6.62695 0 -12 5.37305 -12 12v72c0 6.62695 5.37305 12 12 12h72c6.62695 0 12 -5.37305 12 -12v-12h224v12c0 6.62695 5.37305 12 12 12h72
c6.62695 0 12 -5.37305 12 -12v-72c0 -6.62695 -5.37305 -12 -12 -12h-12v-24h88v12c0 6.62695 5.37305 12 12 12h72c6.62695 0 12 -5.37305 12 -12v-72c0 -6.62695 -5.37305 -12 -12 -12zM352 384v-32h32v32h-32zM352 128v-32h32v32h-32zM64 96v32h-32v-32h32zM64 352v32
h-32v-32h32zM96 136h224v12c0 6.62695 5.37305 12 12 12h12v160h-12c-6.62695 0 -12 5.37305 -12 12v12h-224v-12c0 -6.62695 -5.37305 -12 -12 -12h-12v-160h12c6.62695 0 12 -5.37305 12 -12v-12zM224 0v32h-32v-32h32zM504 64v160h-12c-6.62695 0 -12 5.37305 -12 12v12
h-88v-88h12c6.62695 0 12 -5.37305 12 -12v-72c0 -6.62695 -5.37305 -12 -12 -12h-72c-6.62695 0 -12 5.37305 -12 12v12h-88v-24h12c6.62695 0 12 -5.37305 12 -12v-12h224v12c0 6.62695 5.37305 12 12 12h12zM544 0v32h-32v-32h32zM544 256v32h-32v-32h32z" />
<glyph glyph-name="sticky-note" unicode="&#xf249;" horiz-adv-x="448"
d="M448 99.8936c0 -10.9746 -6.29883 -26.1797 -14.0586 -33.9404l-83.8828 -83.8818c-7.75977 -7.76074 -22.9658 -14.0596 -33.9404 -14.0596h-268.118c-26.5098 0 -48 21.4902 -48 48v351.988c0 26.5098 21.4902 48 48 48h352c26.5098 0 48 -21.4902 48 -48v-268.106z
M320 19.8936l76.1182 76.1182h-76.1182v-76.1182zM400 368h-352v-351.988h224v104c0 13.2549 10.7451 24 24 24h104v223.988z" />
<glyph glyph-name="clone" unicode="&#xf24d;"
d="M464 448c26.5098 0 48 -21.4902 48 -48v-320c0 -26.5098 -21.4902 -48 -48 -48h-48v-48c0 -26.5098 -21.4902 -48 -48 -48h-320c-26.5098 0 -48 21.4902 -48 48v320c0 26.5098 21.4902 48 48 48h48v48c0 26.5098 21.4902 48 48 48h320zM362 -16c3.31152 0 6 2.68848 6 6
v42h-224c-26.5098 0 -48 21.4902 -48 48v224h-42c-3.31152 0 -6 -2.68848 -6 -6v-308c0 -3.31152 2.68848 -6 6 -6h308zM458 80c3.31152 0 6 2.68848 6 6v308c0 3.31152 -2.68848 6 -6 6h-308c-3.31152 0 -6 -2.68848 -6 -6v-308c0 -3.31152 2.68848 -6 6 -6h308z" />
<glyph glyph-name="hourglass" unicode="&#xf254;" horiz-adv-x="384"
d="M368 400c0 -80.0996 -31.8984 -165.619 -97.1797 -208c64.9912 -42.1934 97.1797 -127.436 97.1797 -208h4c6.62695 0 12 -5.37305 12 -12v-24c0 -6.62695 -5.37305 -12 -12 -12h-360c-6.62695 0 -12 5.37305 -12 12v24c0 6.62695 5.37305 12 12 12h4
c0 80.0996 31.8994 165.619 97.1797 208c-64.9912 42.1934 -97.1797 127.436 -97.1797 208h-4c-6.62695 0 -12 5.37305 -12 12v24c0 6.62695 5.37305 12 12 12h360c6.62695 0 12 -5.37305 12 -12v-24c0 -6.62695 -5.37305 -12 -12 -12h-4zM64 400
c0 -101.621 57.3066 -184 128 -184s128 82.3799 128 184h-256zM320 -16c0 101.62 -57.3076 184 -128 184s-128 -82.3799 -128 -184h256z" />
<glyph glyph-name="hand-rock" unicode="&#xf255;"
d="M408.864 368.948c48.8213 20.751 103.136 -15.0723 103.136 -67.9111v-114.443c0 -15.3955 -3.08887 -30.3906 -9.18262 -44.5674l-42.835 -99.6562c-4.99707 -11.625 -3.98242 -18.8574 -3.98242 -42.3701c0 -17.6729 -14.3271 -32 -32 -32h-252
c-17.6729 0 -32 14.3271 -32 32c0 27.3301 1.1416 29.2012 -3.11035 32.9033l-97.71 85.0811c-24.8994 21.6797 -39.1797 52.8926 -39.1797 85.6338v56.9531c0 47.4277 44.8457 82.0215 91.0459 71.1807c1.96094 55.751 63.5107 87.8262 110.671 60.8057
c29.1895 31.0713 78.8604 31.4473 108.334 -0.0214844c32.7051 18.6846 76.4121 10.3096 98.8135 -23.5879zM464 186.594v114.445c0 34.29 -52 33.8232 -52 0.676758c0 -8.83594 -7.16309 -16 -16 -16h-7c-8.83691 0 -16 7.16406 -16 16v26.751
c0 34.457 -52 33.707 -52 0.676758v-27.4287c0 -8.83594 -7.16309 -16 -16 -16h-7c-8.83691 0 -16 7.16406 -16 16v40.4658c0 34.3525 -52 33.8115 -52 0.677734v-41.1436c0 -8.83594 -7.16406 -16 -16 -16h-7c-8.83594 0 -16 7.16406 -16 16v26.751
c0 34.4023 -52 33.7744 -52 0.676758v-116.571c0 -8.83203 -7.16797 -16 -16 -16c-3.30664 0 -8.01367 1.7627 -10.5068 3.93359l-7 6.09473c-3.03223 2.64062 -5.49316 8.04688 -5.49316 12.0674v0v41.2275c0 34.2148 -52 33.8857 -52 0.677734v-56.9531
c0 -18.8555 8.27441 -36.874 22.7002 -49.4365l97.71 -85.0801c12.4502 -10.8398 19.5898 -26.4463 19.5898 -42.8164v-10.2861h220v7.07617c0 13.21 2.65332 26.0791 7.88281 38.25l42.835 99.6553c2.91602 6.75391 5.28223 18.207 5.28223 25.5635v0.0488281z" />
<glyph glyph-name="hand-paper" unicode="&#xf256;" horiz-adv-x="448"
d="M372.57 335.359c39.9062 5.63281 75.4297 -25.7393 75.4297 -66.3594v-131.564c-0.00195312 -12.7666 -2.33008 -33.2246 -5.19531 -45.666l-30.1836 -130.958c-3.34668 -14.5234 -16.2783 -24.8125 -31.1816 -24.8125h-222.897
c-9.10352 0 -20.7793 6.01758 -26.0615 13.4316l-119.97 168.415c-21.2441 29.8203 -14.8047 71.3574 14.5498 93.1533c18.7754 13.9395 42.1309 16.2979 62.083 8.87109v126.13c0 44.0547 41.125 75.5439 82.4053 64.9834c23.8926 48.1963 92.3535 50.2471 117.982 0.74707
c42.5186 11.1445 83.0391 -21.9346 83.0391 -65.5469v-10.8242zM399.997 137.437l-0.00195312 131.563c0 24.9492 -36.5703 25.5508 -36.5703 -0.691406v-76.3086c0 -8.83691 -7.16309 -16 -16 -16h-6.85645c-8.83691 0 -16 7.16309 -16 16v154.184
c0 25.501 -36.5703 26.3633 -36.5703 0.691406v-154.875c0 -8.83691 -7.16309 -16 -16 -16h-6.85645c-8.83691 0 -16 7.16309 -16 16v188.309c0 25.501 -36.5703 26.3545 -36.5703 0.691406v-189c0 -8.83691 -7.16309 -16 -16 -16h-6.85645c-8.83691 0 -16 7.16309 -16 16
v153.309c0 25.501 -36.5713 26.3359 -36.5713 0.691406v-206.494c0 -15.5703 -20.0352 -21.9092 -29.0303 -9.2832l-27.1279 38.0791c-14.3711 20.1709 -43.833 -2.33496 -29.3945 -22.6045l115.196 -161.697h201.92l27.3252 118.551
c2.63086 11.417 3.96484 23.1553 3.96484 34.8857z" />
<glyph glyph-name="hand-scissors" unicode="&#xf257;"
d="M256 -32c-44.9561 0 -77.3428 43.2627 -64.0244 85.8535c-21.6484 13.71 -34.0156 38.7617 -30.3408 65.0068h-87.6348c-40.8037 0 -74 32.8105 -74 73.1406c0 40.3291 33.1963 73.1396 74 73.1396l94 -9.14062l-78.8496 18.6787
c-38.3076 14.7422 -57.04 57.4707 -41.9424 95.1123c15.0303 37.4736 57.7549 55.7803 95.6416 41.2012l144.929 -55.7568c24.9551 30.5566 57.8086 43.9932 92.2178 24.7324l97.999 -54.8525c20.9746 -11.7393 34.0049 -33.8457 34.0049 -57.6904v-205.702
c0 -30.7422 -21.4404 -57.5576 -51.7979 -64.5537l-118.999 -27.4268c-4.97168 -1.14648 -10.0889 -1.72949 -15.2031 -1.72949zM256 16.0127l70 -0.000976562c1.23633 0 3.21777 0.225586 4.42285 0.501953l119.001 27.4277
c8.58203 1.97754 14.5762 9.29102 14.5762 17.7812v205.701c0 6.4873 -3.62109 12.542 -9.44922 15.8047l-98 54.8545c-8.13965 4.55566 -18.668 2.61914 -24.4873 -4.50781l-21.7646 -26.6475c-2.65039 -3.24512 -8.20215 -5.87891 -12.3926 -5.87891
c-1.64062 0 -4.21484 0.477539 -5.74609 1.06738l-166.549 64.0908c-32.6543 12.5664 -50.7744 -34.5771 -19.2227 -46.7168l155.357 -59.7852c5.66016 -2.17773 10.2539 -8.86816 10.2539 -14.9326v0v-11.6328c0 -8.83691 -7.16309 -16 -16 -16h-182
c-34.375 0 -34.4297 -50.2803 0 -50.2803h182c8.83691 0 16 -7.16309 16 -16v-6.85645c0 -8.83691 -7.16309 -16 -16 -16h-28c-25.1221 0 -25.1592 -36.5674 0 -36.5674h28c8.83691 0 16 -7.16211 16 -16v-6.85547c0 -8.83691 -7.16309 -16 -16 -16
c-25.1201 0 -25.1602 -36.5674 0 -36.5674z" />
<glyph glyph-name="hand-lizard" unicode="&#xf258;" horiz-adv-x="576"
d="M556.686 157.458c12.6357 -19.4863 19.3145 -42.0615 19.3145 -65.2871v-124.171h-224v71.582l-99.751 38.7871c-2.7832 1.08203 -5.70996 1.63086 -8.69727 1.63086h-131.552c-30.8789 0 -56 25.1211 -56 56c0 48.5234 39.4766 88 88 88h113.709l18.333 48h-196.042
c-44.1123 0 -80 35.8877 -80 80v8c0 30.8779 25.1211 56 56 56h293.917c24.5 0 47.084 -12.2725 60.4111 -32.8291zM528 16v76.1709v0.0478516c0 11.7461 -5.19141 29.2734 -11.5879 39.124l-146.358 225.715c-4.44336 6.85254 -11.9707 10.9424 -20.1367 10.9424h-293.917
c-4.41113 0 -8 -3.58887 -8 -8v-8c0 -17.6445 14.3555 -32 32 -32h213.471c25.2021 0 42.626 -25.293 33.6299 -48.8457l-24.5518 -64.2812c-7.05371 -18.4658 -25.0732 -30.873 -44.8398 -30.873h-113.709c-22.0557 0 -40 -17.9443 -40 -40c0 -4.41113 3.58887 -8 8 -8
h131.552h0.0517578c7.44141 0 19.1074 -2.19238 26.041 -4.89355l99.752 -38.7881c18.5898 -7.22852 30.6035 -24.7881 30.6035 -44.7363v-23.582h128z" />
<glyph glyph-name="hand-spock" unicode="&#xf259;"
d="M501.03 331.824c6.05762 -9.77832 10.9746 -27.0498 10.9746 -38.5518c0 -4.80664 -0.915039 -12.499 -2.04297 -17.1709l-57.623 -241.963c-12.748 -54.1729 -68.2627 -98.1387 -123.915 -98.1387h-0.345703h-107.455h-0.224609
c-33.8135 0 -81.2148 18.834 -105.807 42.041l-91.3652 85.9766c-12.8213 12.0469 -23.2266 36.1016 -23.2266 53.6943c0 16.1299 8.97266 38.7529 20.0273 50.499c5.31836 5.66406 29.875 29.3926 68.1152 21.8477l-24.3594 82.1973
c-1.68164 5.66406 -3.0459 15.0576 -3.0459 20.9668c0 37.5938 30.417 70.502 67.8955 73.4551c-0.204102 2.03125 -0.369141 5.33691 -0.369141 7.37891c0 31.627 24.8594 63.6895 55.4902 71.5684c43.248 10.9785 80.5645 -17.7012 89.6602 -53.0723l13.6836 -53.207
l4.64648 22.6602c6.76074 32.417 39.123 58.8115 72.2373 58.916c8.73438 0 56.625 -3.26953 70.7383 -54.0801c15.0664 0.710938 46.9199 -3.50977 66.3105 -35.0176zM463.271 287.219c7.86914 32.9844 -42.1211 45.2695 -50.0859 11.9219l-24.8008 -104.146
c-4.38867 -18.4141 -31.7783 -11.8926 -28.0557 6.2168l28.5479 139.166c7.39844 36.0703 -43.3076 45.0703 -50.1182 11.9629l-31.791 -154.971c-3.54883 -17.3086 -28.2832 -18.0469 -32.7109 -0.804688l-47.3262 184.035
c-8.43359 32.8105 -58.3691 20.2676 -49.8652 -12.8359l42.4414 -165.039c4.81641 -18.7207 -23.3711 -26.9121 -28.9648 -8.00781l-31.3438 105.779c-9.6875 32.6465 -59.1191 18.2578 -49.3867 -14.625l36.0137 -121.539
c5.61816 -18.9521 10.1777 -50.377 10.1777 -70.1436v-0.00878906c0 -6.54297 -8.05664 -10.9355 -13.4824 -5.82617l-51.123 48.1074c-24.7852 23.4082 -60.0527 -14.1875 -35.2793 -37.4902l91.3691 -85.9805c16.9629 -16.0068 49.6592 -28.998 72.9824 -28.998h0.154297
h107.455h0.216797c34.7402 0 69.3936 27.4443 77.3525 61.2598z" />
<glyph glyph-name="hand-pointer" unicode="&#xf25a;" horiz-adv-x="448"
d="M358.182 268.639c43.1934 16.6348 89.8184 -15.7949 89.8184 -62.6387v-84c-0.000976562 -4.25 -0.775391 -11.0615 -1.72754 -15.2041l-27.4297 -118.999c-6.98242 -30.2969 -33.7549 -51.7969 -64.5566 -51.7969h-178.286c-21.2588 0 -41.3682 10.4102 -53.791 27.8457
l-109.699 154.001c-21.2432 29.8193 -14.8047 71.3574 14.5498 93.1523c18.8115 13.9658 42.1748 16.2822 62.083 8.87207v161.129c0 36.9443 29.7363 67 66.2861 67s66.2861 -30.0557 66.2861 -67v-73.6338c20.4131 2.85742 41.4678 -3.94238 56.5947 -19.6289
c27.1934 12.8467 60.3799 5.66992 79.8721 -19.0986zM80.9854 168.303c-14.4004 20.2119 -43.8008 -2.38281 -29.3945 -22.6055l109.712 -154c3.43457 -4.81934 8.92871 -7.69727 14.6973 -7.69727h178.285c8.49219 0 15.8037 5.99414 17.7822 14.5762l27.4297 119.001
c0.333008 1.44629 0.501953 2.93457 0.501953 4.42285v84c0 25.1602 -36.5713 25.1211 -36.5713 0c0 -8.83594 -7.16309 -16 -16 -16h-6.85645c-8.83691 0 -16 7.16406 -16 16v21c0 25.1602 -36.5713 25.1201 -36.5713 0v-21c0 -8.83594 -7.16309 -16 -16 -16h-6.85938
c-8.83691 0 -16 7.16406 -16 16v35c0 25.1602 -36.5703 25.1201 -36.5703 0v-35c0 -8.83594 -7.16309 -16 -16 -16h-6.85742c-8.83691 0 -16 7.16406 -16 16v175c0 25.1602 -36.5713 25.1201 -36.5713 0v-241.493c0 -15.5703 -20.0352 -21.9092 -29.0303 -9.2832z
M176.143 48v96c0 8.83691 6.26855 16 14 16h6c7.73242 0 14 -7.16309 14 -16v-96c0 -8.83691 -6.26758 -16 -14 -16h-6c-7.73242 0 -14 7.16309 -14 16zM251.571 48v96c0 8.83691 6.26758 16 14 16h6c7.73145 0 14 -7.16309 14 -16v-96c0 -8.83691 -6.26855 -16 -14 -16h-6
c-7.73242 0 -14 7.16309 -14 16zM327 48v96c0 8.83691 6.26758 16 14 16h6c7.73242 0 14 -7.16309 14 -16v-96c0 -8.83691 -6.26758 -16 -14 -16h-6c-7.73242 0 -14 7.16309 -14 16z" />
<glyph glyph-name="hand-peace" unicode="&#xf25b;" horiz-adv-x="448"
d="M362.146 256.024c42.5908 13.3184 85.8535 -19.0684 85.8535 -64.0244l-0.0117188 -70.001c-0.000976562 -4.25 -0.775391 -11.0615 -1.72949 -15.2031l-27.4268 -118.999c-6.99707 -30.3564 -33.8105 -51.7969 -64.5547 -51.7969h-205.702
c-23.8447 0 -45.9502 13.0303 -57.6904 34.0059l-54.8525 97.999c-19.2607 34.4092 -5.82422 67.2617 24.7324 92.2178l-55.7568 144.928c-14.5791 37.8867 3.72754 80.6113 41.2012 95.6416c37.6406 15.0977 80.3691 -3.63477 95.1123 -41.9424l18.6787 -78.8496
l-9.14062 94c0 40.8037 32.8096 74 73.1396 74s73.1406 -33.1963 73.1406 -74v-87.6348c26.2451 3.6748 51.2959 -8.69238 65.0068 -30.3408zM399.987 122l-0.000976562 70c0 25.1602 -36.5674 25.1201 -36.5674 0c0 -8.83691 -7.16309 -16 -16 -16h-6.85547
c-8.83789 0 -16 7.16309 -16 16v28c0 25.1592 -36.5674 25.1221 -36.5674 0v-28c0 -8.83691 -7.16309 -16 -16 -16h-6.85645c-8.83691 0 -16 7.16309 -16 16v182c0 34.4297 -50.2803 34.375 -50.2803 0v-182c0 -8.83691 -7.16309 -16 -16 -16h-11.6328v0
c-6.06445 0 -12.7549 4.59375 -14.9326 10.2539l-59.7842 155.357c-12.1396 31.5518 -59.2842 13.4326 -46.7168 -19.2227l64.0898 -166.549c0.589844 -1.53125 1.06738 -4.10547 1.06738 -5.74609c0 -4.19043 -2.63379 -9.74219 -5.87891 -12.3926l-26.6475 -21.7646
c-7.12695 -5.81934 -9.06445 -16.3467 -4.50781 -24.4873l54.8535 -98c3.26367 -5.82812 9.31934 -9.44922 15.8057 -9.44922h205.701c8.49121 0 15.8037 5.99414 17.7812 14.5762l27.4277 119.001c0.333008 1.44629 0.501953 2.93457 0.501953 4.42285z" />
<glyph glyph-name="registered" unicode="&#xf25d;"
d="M256 440c136.967 0 248 -111.033 248 -248s-111.033 -248 -248 -248s-248 111.033 -248 248s111.033 248 248 248zM256 -8c110.549 0 200 89.4678 200 200c0 110.549 -89.4678 200 -200 200c-110.549 0 -200 -89.4688 -200 -200c0 -110.549 89.4678 -200 200 -200z
M366.442 73.791c4.40332 -7.99219 -1.37012 -17.791 -10.5107 -17.791h-42.8096h-0.0126953c-3.97559 0 -8.71582 2.84961 -10.5801 6.36035l-47.5156 89.3027h-31.958v-83.6631c0 -6.61719 -5.38281 -12 -12 -12h-38.5674c-6.61719 0 -12 5.38281 -12 12v248.304
c0 6.61719 5.38281 12 12 12h78.667c71.251 0 101.498 -32.749 101.498 -85.252c0 -31.6123 -15.2148 -59.2969 -39.4824 -73.1758c3.02148 -4.61719 0.225586 0.199219 53.2715 -96.085zM256.933 208.094c20.9131 0 32.4307 11.5186 32.4316 32.4316
c0 19.5752 -6.5127 31.709 -38.9297 31.709h-27.377v-64.1406h33.875z" />
<glyph glyph-name="calendar-plus" unicode="&#xf271;" horiz-adv-x="448"
d="M336 156v-24c0 -6.59961 -5.40039 -12 -12 -12h-76v-76c0 -6.59961 -5.40039 -12 -12 -12h-24c-6.59961 0 -12 5.40039 -12 12v76h-76c-6.59961 0 -12 5.40039 -12 12v24c0 6.59961 5.40039 12 12 12h76v76c0 6.59961 5.40039 12 12 12h24c6.59961 0 12 -5.40039 12 -12
v-76h76c6.59961 0 12 -5.40039 12 -12zM448 336v-352c0 -26.5 -21.5 -48 -48 -48h-352c-26.5 0 -48 21.5 -48 48v352c0 26.5 21.5 48 48 48h48v52c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-52h128v52c0 6.59961 5.40039 12 12 12h40
c6.59961 0 12 -5.40039 12 -12v-52h48c26.5 0 48 -21.5 48 -48zM400 -10v298h-352v-298c0 -3.2998 2.7002 -6 6 -6h340c3.2998 0 6 2.7002 6 6z" />
<glyph glyph-name="calendar-minus" unicode="&#xf272;" horiz-adv-x="448"
d="M124 120c-6.59961 0 -12 5.40039 -12 12v24c0 6.59961 5.40039 12 12 12h200c6.59961 0 12 -5.40039 12 -12v-24c0 -6.59961 -5.40039 -12 -12 -12h-200zM448 336v-352c0 -26.5 -21.5 -48 -48 -48h-352c-26.5 0 -48 21.5 -48 48v352c0 26.5 21.5 48 48 48h48v52
c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-52h128v52c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-52h48c26.5 0 48 -21.5 48 -48zM400 -10v298h-352v-298c0 -3.2998 2.7002 -6 6 -6h340c3.2998 0 6 2.7002 6 6z" />
<glyph glyph-name="calendar-times" unicode="&#xf273;" horiz-adv-x="448"
d="M311.7 73.2998l-17 -17c-4.7002 -4.7002 -12.2998 -4.7002 -17 0l-53.7002 53.7998l-53.7002 -53.6992c-4.7002 -4.7002 -12.2998 -4.7002 -17 0l-17 17c-4.7002 4.69922 -4.7002 12.2998 0 17l53.7002 53.6992l-53.7002 53.7002c-4.7002 4.7002 -4.7002 12.2998 0 17
l17 17c4.7002 4.7002 12.2998 4.7002 17 0l53.7002 -53.7002l53.7002 53.7002c4.7002 4.7002 12.2998 4.7002 17 0l17 -17c4.7002 -4.7002 4.7002 -12.2998 0 -17l-53.7998 -53.7998l53.6992 -53.7002c4.80078 -4.7002 4.80078 -12.2998 0.100586 -17zM448 336v-352
c0 -26.5 -21.5 -48 -48 -48h-352c-26.5 0 -48 21.5 -48 48v352c0 26.5 21.5 48 48 48h48v52c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-52h128v52c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-52h48c26.5 0 48 -21.5 48 -48zM400 -10
v298h-352v-298c0 -3.2998 2.7002 -6 6 -6h340c3.2998 0 6 2.7002 6 6z" />
<glyph glyph-name="calendar-check" unicode="&#xf274;" horiz-adv-x="448"
d="M400 384c26.5098 0 48 -21.4902 48 -48v-352c0 -26.5098 -21.4902 -48 -48 -48h-352c-26.5098 0 -48 21.4902 -48 48v352c0 26.5098 21.4902 48 48 48h48v52c0 6.62695 5.37305 12 12 12h40c6.62695 0 12 -5.37305 12 -12v-52h128v52c0 6.62695 5.37305 12 12 12h40
c6.62695 0 12 -5.37305 12 -12v-52h48zM394 -16c3.31152 0 6 2.68848 6 6v298h-352v-298c0 -3.31152 2.68848 -6 6 -6h340zM341.151 184.65l-142.31 -141.169c-4.70508 -4.66699 -12.3027 -4.6377 -16.9707 0.0673828l-75.0908 75.6992
c-4.66699 4.70508 -4.6377 12.3027 0.0673828 16.9707l22.7197 22.5361c4.70508 4.66699 12.3027 4.63672 16.9697 -0.0693359l44.1035 -44.4609l111.072 110.182c4.70508 4.66699 12.3027 4.63672 16.9707 -0.0683594l22.5361 -22.7178
c4.66699 -4.70508 4.63672 -12.3027 -0.0683594 -16.9697z" />
<glyph glyph-name="map" unicode="&#xf279;" horiz-adv-x="576"
d="M560.02 416c8.4502 0 15.9805 -6.83008 15.9805 -16.0195v-346.32c0 -11.9609 -9.01367 -25.2705 -20.1201 -29.71l-151.83 -52.8105c-5.32617 -1.7334 -14.1953 -3.13965 -19.7969 -3.13965c-5.7373 0 -14.8105 1.47363 -20.2529 3.29004l-172 60.71l-170.05 -62.8398
c-1.99023 -0.790039 -4 -1.16016 -5.95996 -1.16016c-8.45996 0 -15.9902 6.83008 -15.9902 16.0195v346.32c0.00292969 11.959 9.0166 25.2686 20.1201 29.71l151.83 52.8105c6.43945 2.08984 13.1201 3.13965 19.8096 3.13965
c5.73242 -0.00195312 14.8008 -1.47168 20.2402 -3.28027l172 -60.7197h0.00976562l170.05 62.8398c1.98047 0.790039 4 1.16016 5.95996 1.16016zM224 357.58v-285.97l128 -45.1904v285.97zM48 29.9502l127.36 47.0801l0.639648 0.229492v286.2l-128 -44.5303v-288.979z
M528 65.0801v288.97l-127.36 -47.0693l-0.639648 -0.240234v-286.19z" />
<glyph glyph-name="comment-alt" unicode="&#xf27a;"
d="M448 448c35.2998 0 64 -28.7002 64 -64v-288c0 -35.2998 -28.7002 -64 -64 -64h-144l-124.9 -93.5996c-2.19922 -1.7002 -4.69922 -2.40039 -7.09961 -2.40039c-6.2002 0 -12 4.90039 -12 12v84h-96c-35.2998 0 -64 28.7002 -64 64v288c0 35.2998 28.7002 64 64 64h384z
M464 96v288c0 8.7998 -7.2002 16 -16 16h-384c-8.7998 0 -16 -7.2002 -16 -16v-288c0 -8.7998 7.2002 -16 16 -16h144v-60l67.2002 50.4004l12.7998 9.59961h160c8.7998 0 16 7.2002 16 16z" />
<glyph glyph-name="pause-circle" unicode="&#xf28b;"
d="M256 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM256 -8c110.5 0 200 89.5 200 200s-89.5 200 -200 200s-200 -89.5 -200 -200s89.5 -200 200 -200zM352 272v-160c0 -8.7998 -7.2002 -16 -16 -16h-48
c-8.7998 0 -16 7.2002 -16 16v160c0 8.7998 7.2002 16 16 16h48c8.7998 0 16 -7.2002 16 -16zM240 272v-160c0 -8.7998 -7.2002 -16 -16 -16h-48c-8.7998 0 -16 7.2002 -16 16v160c0 8.7998 7.2002 16 16 16h48c8.7998 0 16 -7.2002 16 -16z" />
<glyph glyph-name="stop-circle" unicode="&#xf28d;"
d="M504 192c0 -137 -111 -248 -248 -248s-248 111 -248 248s111 248 248 248s248 -111 248 -248zM56 192c0 -110.5 89.5 -200 200 -200s200 89.5 200 200s-89.5 200 -200 200s-200 -89.5 -200 -200zM352 272v-160c0 -8.7998 -7.2002 -16 -16 -16h-160
c-8.7998 0 -16 7.2002 -16 16v160c0 8.7998 7.2002 16 16 16h160c8.7998 0 16 -7.2002 16 -16z" />
<glyph glyph-name="handshake" unicode="&#xf2b5;" horiz-adv-x="640"
d="M519.2 320.1h120.8v-255.699h-64c-17.5 0 -31.7998 14.1992 -31.9004 31.6992h-57.8994c-1.7998 -8.19922 -5.2998 -16.0996 -10.9004 -23l-26.2002 -32.2998c-15.7998 -19.3994 -41.8994 -25.5 -64 -16.7998c-13.5 -16.5996 -30.5996 -24 -48.7998 -24
c-15.0996 0 -28.5996 5.09961 -41.0996 15.9004c-31.7998 -21.9004 -74.7002 -21.3008 -105.601 3.7998l-84.5996 76.3994h-9.09961c-0.100586 -17.5 -14.3008 -31.6992 -31.9004 -31.6992h-64v255.699h118l47.5996 47.6006c10.5 10.3994 24.8008 16.2998 39.6006 16.2998
h226.8v0c12.7812 0 30.5225 -7.30273 39.5996 -16.2998zM48 96.4004c8.7998 0 16 7.09961 16 16c0 8.7998 -7.2002 16 -16 16s-16 -7.2002 -16 -16c0 -8.80078 7.2002 -16 16 -16zM438 103.3c2.7002 3.40039 2.2002 8.5 -1.2002 11.2998l-108.2 87.8008l-8.19922 -7.5
c-40.3008 -36.8008 -86.7002 -11.8008 -101.5 4.39941c-26.7002 29 -25 74.4004 4.39941 101.3l38.7002 35.5h-56.7002c-2 -0.799805 -3.7002 -1.5 -5.7002 -2.2998l-61.6992 -61.5996h-41.9004v-128.101h27.7002l97.2998 -88
c16.0996 -13.0996 41.4004 -10.5 55.2998 6.60059l15.6006 19.2002l36.7998 -31.5c3 -2.40039 12 -4.90039 18 2.39941l30 36.5l23.8994 -19.3994c3.5 -2.80078 8.5 -2.2002 11.3008 1.19922zM544 144.1v128h-44.7002l-61.7002 61.6006
c-1.39941 1.5 -3.39941 2.2998 -5.5 2.2998l-83.6992 -0.200195c-10 0 -19.6006 -3.7002 -27 -10.5l-65.6006 -60.0996c-9.7002 -8.7998 -10.5 -24 -1.2002 -33.9004c8.90039 -9.39941 25.1006 -8.7002 34.6006 0l55.2002 50.6006c6.5 5.89941 16.5996 5.5 22.5996 -1
l10.9004 -11.7002c6 -6.5 5.5 -16.6006 -1 -22.6006l-12.5 -11.3994l102.699 -83.4004c2.80078 -2.2998 5.40039 -4.89941 7.7002 -7.7002h69.2002zM592 96.4004c8.7998 0 16 7.09961 16 16c0 8.7998 -7.2002 16 -16 16s-16 -7.2002 -16 -16c0 -8.80078 7.2002 -16 16 -16z
" />
<glyph glyph-name="envelope-open" unicode="&#xf2b6;"
d="M494.586 283.484c9.6123 -7.94824 17.4141 -24.5205 17.4141 -36.9932v-262.491c0 -26.5098 -21.4902 -48 -48 -48h-416c-26.5098 0 -48 21.4902 -48 48v262.515c0 12.5166 7.84668 29.1279 17.5146 37.0771c4.08008 3.35449 110.688 89.0996 135.15 108.549
c22.6992 18.1426 60.1299 55.8594 103.335 55.8594c43.4365 0 81.2314 -38.1914 103.335 -55.8594c23.5283 -18.707 130.554 -104.773 135.251 -108.656zM464 -10v253.632v0.00488281c0 1.5791 -0.996094 3.66602 -2.22363 4.6582
c-15.8633 12.8232 -108.793 87.5752 -132.366 106.316c-17.5527 14.0195 -49.7168 45.3887 -73.4102 45.3887c-23.6016 0 -55.2451 -30.8799 -73.4102 -45.3887c-23.5713 -18.7393 -116.494 -93.4795 -132.364 -106.293
c-1.40918 -1.13965 -2.22559 -2.85254 -2.22559 -4.66504v-253.653c0 -3.31152 2.68848 -6 6 -6h404c3.31152 0 6 2.68848 6 6zM432.009 177.704c4.24902 -5.15918 3.46484 -12.7949 -1.74512 -16.9814c-28.9746 -23.2822 -59.2734 -47.5967 -70.9287 -56.8623
c-22.6992 -18.1436 -60.1299 -55.8604 -103.335 -55.8604c-43.4521 0 -81.2871 38.2373 -103.335 55.8604c-11.2793 8.9668 -41.7441 33.4131 -70.9268 56.8643c-5.20996 4.1875 -5.99316 11.8223 -1.74512 16.9814l15.2578 18.5283
c4.17773 5.07227 11.6572 5.84277 16.7793 1.72559c28.6182 -23.001 58.5654 -47.0352 70.5596 -56.5713c17.5527 -14.0195 49.7168 -45.3887 73.4102 -45.3887c23.6016 0 55.2461 30.8799 73.4102 45.3887c11.9941 9.53516 41.9434 33.5703 70.5625 56.5684
c5.12207 4.11621 12.6016 3.3457 16.7783 -1.72656z" />
<glyph glyph-name="address-book" unicode="&#xf2b9;" horiz-adv-x="448"
d="M436 288h-20v-64h20c6.59961 0 12 -5.40039 12 -12v-40c0 -6.59961 -5.40039 -12 -12 -12h-20v-64h20c6.59961 0 12 -5.40039 12 -12v-40c0 -6.59961 -5.40039 -12 -12 -12h-20v-48c0 -26.5 -21.5 -48 -48 -48h-320c-26.5 0 -48 21.5 -48 48v416c0 26.5 21.5 48 48 48
h320c26.5 0 48 -21.5 48 -48v-48h20c6.59961 0 12 -5.40039 12 -12v-40c0 -6.59961 -5.40039 -12 -12 -12zM368 -16v416h-320v-416h320zM208 192c-35.2998 0 -64 28.7002 -64 64s28.7002 64 64 64s64 -28.7002 64 -64s-28.7002 -64 -64 -64zM118.4 64
c-12.4004 0 -22.4004 8.59961 -22.4004 19.2002v19.2002c0 31.7998 30.0996 57.5996 67.2002 57.5996c11.3994 0 17.8994 -8 44.7998 -8c26.0996 0 34 8 44.7998 8c37.1006 0 67.2002 -25.7998 67.2002 -57.5996v-19.2002c0 -10.6006 -10 -19.2002 -22.4004 -19.2002
h-179.199z" />
<glyph glyph-name="address-card" unicode="&#xf2bb;" horiz-adv-x="576"
d="M528 416c26.5 0 48 -21.5 48 -48v-352c0 -26.5 -21.5 -48 -48 -48h-480c-26.5 0 -48 21.5 -48 48v352c0 26.5 21.5 48 48 48h480zM528 16v352h-480v-352h480zM208 192c-35.2998 0 -64 28.7002 -64 64s28.7002 64 64 64s64 -28.7002 64 -64s-28.7002 -64 -64 -64z
M118.4 64c-12.4004 0 -22.4004 8.59961 -22.4004 19.2002v19.2002c0 31.7998 30.0996 57.5996 67.2002 57.5996c11.3994 0 17.8994 -8 44.7998 -8c26.0996 0 34 8 44.7998 8c37.1006 0 67.2002 -25.7998 67.2002 -57.5996v-19.2002
c0 -10.6006 -10 -19.2002 -22.4004 -19.2002h-179.199zM360 128c-4.40039 0 -8 3.59961 -8 8v16c0 4.40039 3.59961 8 8 8h112c4.40039 0 8 -3.59961 8 -8v-16c0 -4.40039 -3.59961 -8 -8 -8h-112zM360 192c-4.40039 0 -8 3.59961 -8 8v16c0 4.40039 3.59961 8 8 8h112
c4.40039 0 8 -3.59961 8 -8v-16c0 -4.40039 -3.59961 -8 -8 -8h-112zM360 256c-4.40039 0 -8 3.59961 -8 8v16c0 4.40039 3.59961 8 8 8h112c4.40039 0 8 -3.59961 8 -8v-16c0 -4.40039 -3.59961 -8 -8 -8h-112z" />
<glyph glyph-name="user-circle" unicode="&#xf2bd;" horiz-adv-x="496"
d="M248 344c53 0 96 -43 96 -96s-43 -96 -96 -96s-96 43 -96 96s43 96 96 96zM248 200c26.5 0 48 21.5 48 48s-21.5 48 -48 48s-48 -21.5 -48 -48s21.5 -48 48 -48zM248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8
c49.7002 0 95.0996 18.2998 130.1 48.4004c-14.8994 23 -40.3994 38.5 -69.5996 39.5c-20.7998 -6.5 -40.5996 -9.60059 -60.5 -9.60059s-39.7002 3.2002 -60.5 9.60059c-29.2002 -0.900391 -54.7002 -16.5 -69.5996 -39.5c35 -30.1006 80.3994 -48.4004 130.1 -48.4004z
M410.7 76.0996c23.3994 32.7002 37.2998 72.7002 37.2998 115.9c0 110.3 -89.7002 200 -200 200s-200 -89.7002 -200 -200c0 -43.2002 13.9004 -83.2002 37.2998 -115.9c24.5 31.4004 62.2002 51.9004 105.101 51.9004c10.1992 0 26.0996 -9.59961 57.5996 -9.59961
c31.5996 0 47.4004 9.59961 57.5996 9.59961c43 0 80.7002 -20.5 105.101 -51.9004z" />
<glyph glyph-name="id-badge" unicode="&#xf2c1;" horiz-adv-x="384"
d="M336 448c26.5 0 48 -21.5 48 -48v-416c0 -26.5 -21.5 -48 -48 -48h-288c-26.5 0 -48 21.5 -48 48v416c0 26.5 21.5 48 48 48h288zM336 -16v416h-288v-416h288zM144 336c-8.7998 0 -16 7.2002 -16 16s7.2002 16 16 16h96c8.7998 0 16 -7.2002 16 -16s-7.2002 -16 -16 -16
h-96zM192 160c-35.2998 0 -64 28.7002 -64 64s28.7002 64 64 64s64 -28.7002 64 -64s-28.7002 -64 -64 -64zM102.4 32c-12.4004 0 -22.4004 8.59961 -22.4004 19.2002v19.2002c0 31.7998 30.0996 57.5996 67.2002 57.5996c11.3994 0 17.8994 -8 44.7998 -8
c26.0996 0 34 8 44.7998 8c37.1006 0 67.2002 -25.7998 67.2002 -57.5996v-19.2002c0 -10.6006 -10 -19.2002 -22.4004 -19.2002h-179.199z" />
<glyph glyph-name="id-card" unicode="&#xf2c2;" horiz-adv-x="576"
d="M528 416c26.5 0 48 -21.5 48 -48v-352c0 -26.5 -21.5 -48 -48 -48h-480c-26.5 0 -48 21.5 -48 48v352c0 26.5 21.5 48 48 48h480zM528 16v288h-480v-288h32.7998c-1 4.5 -0.799805 -3.59961 -0.799805 22.4004c0 31.7998 30.0996 57.5996 67.2002 57.5996
c11.3994 0 17.8994 -8 44.7998 -8c26.0996 0 34 8 44.7998 8c37.1006 0 67.2002 -25.7998 67.2002 -57.5996c0 -26 0.0996094 -17.9004 -0.799805 -22.4004h224.8zM360 96c-4.40039 0 -8 3.59961 -8 8v16c0 4.40039 3.59961 8 8 8h112c4.40039 0 8 -3.59961 8 -8v-16
c0 -4.40039 -3.59961 -8 -8 -8h-112zM360 160c-4.40039 0 -8 3.59961 -8 8v16c0 4.40039 3.59961 8 8 8h112c4.40039 0 8 -3.59961 8 -8v-16c0 -4.40039 -3.59961 -8 -8 -8h-112zM360 224c-4.40039 0 -8 3.59961 -8 8v16c0 4.40039 3.59961 8 8 8h112
c4.40039 0 8 -3.59961 8 -8v-16c0 -4.40039 -3.59961 -8 -8 -8h-112zM192 128c-35.2998 0 -64 28.7002 -64 64s28.7002 64 64 64s64 -28.7002 64 -64s-28.7002 -64 -64 -64z" />
<glyph glyph-name="window-maximize" unicode="&#xf2d0;"
d="M464 416c26.5 0 48 -21.5 48 -48v-352c0 -26.5 -21.5 -48 -48 -48h-416c-26.5 0 -48 21.5 -48 48v352c0 26.5 21.5 48 48 48h416zM464 22v234h-416v-234c0 -3.2998 2.7002 -6 6 -6h404c3.2998 0 6 2.7002 6 6z" />
<glyph glyph-name="window-minimize" unicode="&#xf2d1;"
d="M480 -32h-448c-17.7002 0 -32 14.2998 -32 32s14.2998 32 32 32h448c17.7002 0 32 -14.2998 32 -32s-14.2998 -32 -32 -32z" />
<glyph glyph-name="window-restore" unicode="&#xf2d2;"
d="M464 448c26.5 0 48 -21.5 48 -48v-320c0 -26.5 -21.5 -48 -48 -48h-48v-48c0 -26.5 -21.5 -48 -48 -48h-320c-26.5 0 -48 21.5 -48 48v320c0 26.5 21.5 48 48 48h48v48c0 26.5 21.5 48 48 48h320zM368 -16v208h-320v-208h320zM464 80v320h-320v-48h224
c26.5 0 48 -21.5 48 -48v-224h48z" />
<glyph glyph-name="snowflake" unicode="&#xf2dc;" horiz-adv-x="448"
d="M440.1 92.7998c7.60059 -4.39941 10.1006 -14.2002 5.5 -21.7002l-7.89941 -13.8994c-4.40039 -7.7002 -14 -10.2998 -21.5 -5.90039l-39.2002 23l9.09961 -34.7002c2.30078 -8.5 -2.69922 -17.2998 -11.0996 -19.5996l-15.2002 -4.09961
c-8.39941 -2.30078 -17.0996 2.7998 -19.2998 11.2998l-21.2998 81l-71.9004 42.2002v-84.5l58.2998 -59.3008c6.10059 -6.19922 6.10059 -16.3994 0 -22.5996l-11.0996 -11.2998c-6.09961 -6.2002 -16.0996 -6.2002 -22.2002 0l-24.8994 25.3994v-46.0996
c0 -8.7998 -7 -16 -15.7002 -16h-15.7002c-8.7002 0 -15.7002 7.2002 -15.7002 16v45.9004l-24.8994 -25.4004c-6.10059 -6.2002 -16.1006 -6.2002 -22.2002 0l-11.1006 11.2998c-6.09961 6.2002 -6.09961 16.4004 0 22.6006l58.3008 59.2998v84.5l-71.9004 -42.2002
l-21.2998 -81c-2.2998 -8.5 -10.9004 -13.5996 -19.2998 -11.2998l-15.2002 4.09961c-8.40039 2.2998 -13.2998 11.1006 -11.1006 19.6006l9.10059 34.6992l-39.2002 -23c-7.5 -4.39941 -17.2002 -1.7998 -21.5 5.90039l-7.90039 13.9004
c-4.2998 7.69922 -1.69922 17.5 5.80078 21.8994l39.1992 23l-34.0996 9.2998c-8.40039 2.30078 -13.2998 11.1006 -11.0996 19.6006l4.09961 15.5c2.2998 8.5 10.9004 13.5996 19.2998 11.2998l79.7002 -21.7002l71.9004 42.2002l-71.9004 42.2002l-79.7002 -21.7002
c-8.39941 -2.2998 -17.0996 2.7998 -19.2998 11.2998l-4.09961 15.5c-2.30078 8.5 2.69922 17.2998 11.0996 19.6006l34.0996 9.09961l-39.1992 23c-7.60059 4.5 -10.1006 14.2002 -5.80078 21.9004l7.90039 13.8994c4.40039 7.7002 14 10.2998 21.5 5.90039l39.2002 -23
l-9.10059 34.7002c-2.2998 8.5 2.7002 17.2998 11.1006 19.5996l15.2002 4.09961c8.39941 2.30078 17.0996 -2.7998 19.2998 -11.2998l21.2998 -81l71.9004 -42.2002v84.5l-58.3008 59.3008c-6.09961 6.19922 -6.09961 16.3994 0 22.5996l11.5 11.2998
c6.10059 6.2002 16.1006 6.2002 22.2002 0l24.9004 -25.3994v46.0996c0 8.7998 7 16 15.7002 16h15.6992c8.7002 0 15.7002 -7.2002 15.7002 -16v-45.9004l24.9004 25.4004c6.09961 6.2002 16.0996 6.2002 22.2002 0l11.0996 -11.2998
c6.09961 -6.2002 6.09961 -16.4004 0 -22.6006l-58.2998 -59.2998v-84.5l71.8994 42.2002l21.3008 81c2.2998 8.5 10.8994 13.5996 19.2998 11.2998l15.2002 -4.09961c8.39941 -2.2998 13.2998 -11.1006 11.0996 -19.6006l-9.09961 -34.6992l39.1992 23
c7.5 4.39941 17.2002 1.7998 21.5 -5.90039l7.90039 -13.9004c4.2998 -7.69922 1.7002 -17.5 -5.7998 -21.8994l-39.2002 -23l34.0996 -9.2998c8.40039 -2.30078 13.3008 -11.1006 11.1006 -19.6006l-4.10059 -15.5c-2.2998 -8.5 -10.8994 -13.5996 -19.2998 -11.2998
l-79.7002 21.7002l-71.8994 -42.2002l71.7998 -42.2002l79.7002 21.7002c8.39941 2.2998 17.0996 -2.7998 19.2998 -11.2998l4.09961 -15.5c2.30078 -8.5 -2.69922 -17.2998 -11.0996 -19.6006l-34.0996 -9.2998z" />
<glyph glyph-name="trash-alt" unicode="&#xf2ed;" horiz-adv-x="448"
d="M268 32c-6.62402 0 -12 5.37598 -12 12v216c0 6.62402 5.37598 12 12 12h24c6.62402 0 12 -5.37598 12 -12v-216c0 -6.62402 -5.37598 -12 -12 -12h-24zM432 368c8.83203 0 16 -7.16797 16 -16v-16c0 -8.83203 -7.16797 -16 -16 -16h-16v-336
c0 -26.4961 -21.5039 -48 -48 -48h-288c-26.4961 0 -48 21.5039 -48 48v336h-16c-8.83203 0 -16 7.16797 -16 16v16c0 8.83203 7.16797 16 16 16h82.4102l34.0195 56.7002c7.71875 12.8613 26.1572 23.2998 41.1572 23.2998h0.00292969h100.82h0.0224609
c15 0 33.4385 -10.4385 41.1572 -23.2998l34 -56.7002h82.4102zM171.84 397.09l-17.4502 -29.0898h139.221l-17.46 29.0898c-0.96582 1.60645 -3.26953 2.91016 -5.14355 2.91016h-0.00683594h-94h-0.0166016c-1.87402 0 -4.17871 -1.30371 -5.14355 -2.91016zM368 -16v336
h-288v-336h288zM156 32c-6.62402 0 -12 5.37598 -12 12v216c0 6.62402 5.37598 12 12 12h24c6.62402 0 12 -5.37598 12 -12v-216c0 -6.62402 -5.37598 -12 -12 -12h-24z" />
<glyph glyph-name="images" unicode="&#xf302;" horiz-adv-x="576"
d="M480 32v-16c0 -26.5098 -21.4902 -48 -48 -48h-384c-26.5098 0 -48 21.4902 -48 48v256c0 26.5098 21.4902 48 48 48h16v-48h-10c-3.31152 0 -6 -2.68848 -6 -6v-244c0 -3.31152 2.68848 -6 6 -6h372c3.31152 0 6 2.68848 6 6v10h48zM522 368h-372
c-3.31152 0 -6 -2.68848 -6 -6v-244c0 -3.31152 2.68848 -6 6 -6h372c3.31152 0 6 2.68848 6 6v244c0 3.31152 -2.68848 6 -6 6zM528 416c26.5098 0 48 -21.4902 48 -48v-256c0 -26.5098 -21.4902 -48 -48 -48h-384c-26.5098 0 -48 21.4902 -48 48v256
c0 26.5098 21.4902 48 48 48h384zM264 304c0 -22.0908 -17.9092 -40 -40 -40s-40 17.9092 -40 40s17.9092 40 40 40s40 -17.9092 40 -40zM192 208l39.5146 39.5146c4.68652 4.68652 12.2842 4.68652 16.9717 0l39.5137 -39.5146l103.515 103.515
c4.68652 4.68652 12.2842 4.68652 16.9717 0l71.5137 -71.5146v-80h-288v48z" />
<glyph glyph-name="clipboard" unicode="&#xf328;" horiz-adv-x="384"
d="M336 384c26.5 0 48 -21.5 48 -48v-352c0 -26.5 -21.5 -48 -48 -48h-288c-26.5 0 -48 21.5 -48 48v352c0 26.5 21.5 48 48 48h80c0 35.2998 28.7002 64 64 64s64 -28.7002 64 -64h80zM192 408c-13.2998 0 -24 -10.7002 -24 -24s10.7002 -24 24 -24s24 10.7002 24 24
s-10.7002 24 -24 24zM336 -10v340c0 3.2998 -2.7002 6 -6 6h-42v-36c0 -6.59961 -5.40039 -12 -12 -12h-168c-6.59961 0 -12 5.40039 -12 12v36h-42c-3.2998 0 -6 -2.7002 -6 -6v-340c0 -3.2998 2.7002 -6 6 -6h276c3.2998 0 6 2.7002 6 6z" />
<glyph glyph-name="arrow-alt-circle-down" unicode="&#xf358;"
d="M256 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM256 -8c110.5 0 200 89.5 200 200s-89.5 200 -200 200s-200 -89.5 -200 -200s89.5 -200 200 -200zM224 308c0 6.59961 5.40039 12 12 12h40c6.59961 0 12 -5.40039 12 -12v-116
h67c10.7002 0 16.0996 -12.9004 8.5 -20.5l-99 -99c-4.7002 -4.7002 -12.2998 -4.7002 -17 0l-99 99c-7.5 7.59961 -2.2002 20.5 8.5 20.5h67v116z" />
<glyph glyph-name="arrow-alt-circle-left" unicode="&#xf359;"
d="M8 192c0 137 111 248 248 248s248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248zM456 192c0 110.5 -89.5 200 -200 200s-200 -89.5 -200 -200s89.5 -200 200 -200s200 89.5 200 200zM384 212v-40c0 -6.59961 -5.40039 -12 -12 -12h-116v-67
c0 -10.7002 -12.9004 -16 -20.5 -8.5l-99 99c-4.7002 4.7002 -4.7002 12.2998 0 17l99 99c7.59961 7.59961 20.5 2.2002 20.5 -8.5v-67h116c6.59961 0 12 -5.40039 12 -12z" />
<glyph glyph-name="arrow-alt-circle-right" unicode="&#xf35a;"
d="M504 192c0 -137 -111 -248 -248 -248s-248 111 -248 248s111 248 248 248s248 -111 248 -248zM56 192c0 -110.5 89.5 -200 200 -200s200 89.5 200 200s-89.5 200 -200 200s-200 -89.5 -200 -200zM128 172v40c0 6.59961 5.40039 12 12 12h116v67
c0 10.7002 12.9004 16 20.5 8.5l99 -99c4.7002 -4.7002 4.7002 -12.2998 0 -17l-99 -99c-7.59961 -7.59961 -20.5 -2.2002 -20.5 8.5v67h-116c-6.59961 0 -12 5.40039 -12 12z" />
<glyph glyph-name="arrow-alt-circle-up" unicode="&#xf35b;"
d="M256 -56c-137 0 -248 111 -248 248s111 248 248 248s248 -111 248 -248s-111 -248 -248 -248zM256 392c-110.5 0 -200 -89.5 -200 -200s89.5 -200 200 -200s200 89.5 200 200s-89.5 200 -200 200zM276 64h-40c-6.59961 0 -12 5.40039 -12 12v116h-67
c-10.7002 0 -16 12.9004 -8.5 20.5l99 99c4.7002 4.7002 12.2998 4.7002 17 0l99 -99c7.59961 -7.59961 2.2002 -20.5 -8.5 -20.5h-67v-116c0 -6.59961 -5.40039 -12 -12 -12z" />
<glyph glyph-name="gem" unicode="&#xf3a5;" horiz-adv-x="576"
d="M464 448c4.09961 0 7.7998 -2 10.0996 -5.40039l99.9004 -147.199c2.90039 -4.40039 2.59961 -10.1006 -0.700195 -14.2002l-276 -340.8c-4.7998 -5.90039 -13.7998 -5.90039 -18.5996 0l-276 340.8c-3.2998 4 -3.60059 9.7998 -0.700195 14.2002l100 147.199
c2.2002 3.40039 6 5.40039 10 5.40039h352zM444.7 400h-56.7998l51.6992 -96h68.4004zM242.6 400l-51.5996 -96h194l-51.7002 96h-90.7002zM131.3 400l-63.2998 -96h68.4004l51.6992 96h-56.7998zM88.2998 256l119.7 -160l-68.2998 160h-51.4004zM191.2 256l96.7998 -243.3
l96.7998 243.3h-193.6zM368 96l119.6 160h-51.3994z" />
<glyph glyph-name="money-bill-alt" unicode="&#xf3d1;" horiz-adv-x="640"
d="M320 304c53.0195 0 96 -50.1396 96 -112c0 -61.8701 -43 -112 -96 -112c-53.0195 0 -96 50.1504 -96 112c0 61.8604 42.9805 112 96 112zM360 136v16c0 4.41992 -3.58008 8 -8 8h-16v88c0 4.41992 -3.58008 8 -8 8h-13.5801h-0.000976562
c-4.01074 0 -9.97266 -1.80566 -13.3086 -4.03027l-15.3301 -10.2197c-1.96777 -1.30957 -3.56445 -4.29004 -3.56445 -6.65332c0 -1.33691 0.601562 -3.32422 1.34375 -4.43652l8.88086 -13.3105c1.30859 -1.9668 4.29004 -3.56445 6.65332 -3.56445
c1.33691 0 3.32422 0.602539 4.43652 1.34473l0.469727 0.310547v-55.4404h-16c-4.41992 0 -8 -3.58008 -8 -8v-16c0 -4.41992 3.58008 -8 8 -8h64c4.41992 0 8 3.58008 8 8zM608 384c17.6699 0 32 -14.3301 32 -32v-320c0 -17.6699 -14.3301 -32 -32 -32h-576
c-17.6699 0 -32 14.3301 -32 32v320c0 17.6699 14.3301 32 32 32h576zM592 112v160c-35.3496 0 -64 28.6504 -64 64h-416c0 -35.3496 -28.6504 -64 -64 -64v-160c35.3496 0 64 -28.6504 64 -64h416c0 35.3496 28.6504 64 64 64z" />
<glyph glyph-name="window-close" unicode="&#xf410;"
d="M464 416c26.5 0 48 -21.5 48 -48v-352c0 -26.5 -21.5 -48 -48 -48h-416c-26.5 0 -48 21.5 -48 48v352c0 26.5 21.5 48 48 48h416zM464 22v340c0 3.2998 -2.7002 6 -6 6h-404c-3.2998 0 -6 -2.7002 -6 -6v-340c0 -3.2998 2.7002 -6 6 -6h404c3.2998 0 6 2.7002 6 6z
M356.5 253.4l-61.4004 -61.4004l61.4004 -61.4004c4.59961 -4.59961 4.59961 -12.0996 0 -16.7998l-22.2998 -22.2998c-4.60059 -4.59961 -12.1006 -4.59961 -16.7998 0l-61.4004 61.4004l-61.4004 -61.4004c-4.59961 -4.59961 -12.0996 -4.59961 -16.7998 0
l-22.2998 22.2998c-4.59961 4.60059 -4.59961 12.1006 0 16.7998l61.4004 61.4004l-61.4004 61.4004c-4.59961 4.59961 -4.59961 12.0996 0 16.7998l22.2998 22.2998c4.60059 4.59961 12.1006 4.59961 16.7998 0l61.4004 -61.4004l61.4004 61.4004
c4.59961 4.59961 12.0996 4.59961 16.7998 0l22.2998 -22.2998c4.7002 -4.60059 4.7002 -12.1006 0 -16.7998z" />
<glyph glyph-name="comment-dots" unicode="&#xf4ad;"
d="M144 240c17.7002 0 32 -14.2998 32 -32s-14.2998 -32 -32 -32s-32 14.2998 -32 32s14.2998 32 32 32zM256 240c17.7002 0 32 -14.2998 32 -32s-14.2998 -32 -32 -32s-32 14.2998 -32 32s14.2998 32 32 32zM368 240c17.7002 0 32 -14.2998 32 -32s-14.2998 -32 -32 -32
s-32 14.2998 -32 32s14.2998 32 32 32zM256 416c141.4 0 256 -93.0996 256 -208s-114.6 -208 -256 -208c-32.7998 0 -64 5.2002 -92.9004 14.2998c-29.0996 -20.5996 -77.5996 -46.2998 -139.1 -46.2998c-9.59961 0 -18.2998 5.7002 -22.0996 14.5
c-3.80078 8.7998 -2 19 4.59961 26c0.5 0.400391 31.5 33.7998 46.4004 73.2002c-33 35.0996 -52.9004 78.7002 -52.9004 126.3c0 114.9 114.6 208 256 208zM256 48c114.7 0 208 71.7998 208 160s-93.2998 160 -208 160s-208 -71.7998 -208 -160
c0 -42.2002 21.7002 -74.0996 39.7998 -93.4004l20.6006 -21.7998l-10.6006 -28.0996c-5.5 -14.5 -12.5996 -28.1006 -19.8994 -40.2002c23.5996 7.59961 43.1992 18.9004 57.5 29l19.5 13.7998l22.6992 -7.2002c25.3008 -8 51.7002 -12.0996 78.4004 -12.0996z" />
<glyph glyph-name="smile-wink" unicode="&#xf4da;" horiz-adv-x="496"
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM365.8 138.4c10.2002 -8.5 11.6006 -23.6006 3.10059 -33.8008
c-30 -36 -74.1006 -56.5996 -120.9 -56.5996s-90.9004 20.5996 -120.9 56.5996c-8.39941 10.2002 -7.09961 25.3008 3.10059 33.8008c10.0996 8.39941 25.2998 7.09961 33.7998 -3.10059c20.7998 -25.0996 51.5 -39.3994 84 -39.3994s63.2002 14.3994 84 39.3994
c8.5 10.2002 23.5996 11.6006 33.7998 3.10059zM168 208c-17.7002 0 -32 14.2998 -32 32s14.2998 32 32 32s32 -14.2998 32 -32s-14.2998 -32 -32 -32zM328 268c25.7002 0 55.9004 -16.9004 59.7002 -42.0996c1.7998 -11.1006 -11.2998 -18.2002 -19.7998 -10.8008l-9.5 8.5
c-14.8008 13.2002 -46.2002 13.2002 -61 0l-9.5 -8.5c-8.30078 -7.39941 -21.5 -0.399414 -19.8008 10.8008c4 25.1992 34.2002 42.0996 59.9004 42.0996z" />
<glyph glyph-name="angry" unicode="&#xf556;" horiz-adv-x="496"
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM248 136c33.5996 0 65.2002 -14.7998 86.7998 -40.5996
c8.40039 -10.2002 7.10059 -25.3008 -3.09961 -33.8008c-10.6006 -8.89941 -25.7002 -6.69922 -33.7998 3c-24.8008 29.7002 -75 29.7002 -99.8008 0c-8.5 -10.1992 -23.5996 -11.5 -33.7998 -3s-11.5996 23.6006 -3.09961 33.8008
c21.5996 25.7998 53.2002 40.5996 86.7998 40.5996zM200 208c0 -17.7002 -14.2998 -32.0996 -32 -32.0996s-32 14.2998 -32 32c0 6.19922 2.2002 11.6992 5.2998 16.5996l-28.2002 8.5c-12.6992 3.7998 -19.8994 17.2002 -16.0996 29.9004
c3.7998 12.6992 17.0996 20 29.9004 16.0996l80 -24c12.6992 -3.7998 19.8994 -17.2002 16.0996 -29.9004c-3.09961 -10.3994 -12.7002 -17.0996 -23 -17.0996zM399 262.9c3.7998 -12.7002 -3.40039 -26.1006 -16.0996 -29.8008l-28.2002 -8.5
c3.09961 -4.89941 5.2998 -10.3994 5.2998 -16.5996c0 -17.7002 -14.2998 -32 -32 -32s-32 14.2998 -32 32c-10.2998 0 -19.9004 6.7002 -23 17.0996c-3.7998 12.7002 3.40039 26.1006 16.0996 29.9004l80 24c12.8008 3.7998 26.1006 -3.40039 29.9004 -16.0996z" />
<glyph glyph-name="dizzy" unicode="&#xf567;" horiz-adv-x="496"
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM214.2 209.9
c-7.90039 -7.90039 -20.5 -7.90039 -28.4004 -0.200195l-17.7998 17.7998l-17.7998 -17.7998c-7.7998 -7.7998 -20.5 -7.7998 -28.2998 0c-7.80078 7.7998 -7.80078 20.5 0 28.2998l17.8994 17.9004l-17.8994 17.8994c-7.80078 7.7998 -7.80078 20.5 0 28.2998
c7.7998 7.80078 20.5 7.80078 28.2998 0l17.7998 -17.7998l17.9004 17.9004c7.7998 7.7998 20.5 7.7998 28.2998 0s7.7998 -20.5 0 -28.2998l-17.9004 -17.9004l17.9004 -17.7998c7.7998 -7.7998 7.7998 -20.5 0 -28.2998zM374.2 302.1
c7.7002 -7.7998 7.7002 -20.3994 0 -28.1992l-17.9004 -17.9004l17.7998 -18c7.80078 -7.7998 7.80078 -20.5 0 -28.2998c-7.7998 -7.7998 -20.5 -7.7998 -28.2998 0l-17.7998 17.7998l-17.7998 -17.7998c-7.7998 -7.7998 -20.5 -7.7998 -28.2998 0
c-7.80078 7.7998 -7.80078 20.5 0 28.2998l17.8994 17.9004l-17.8994 17.8994c-7.80078 7.7998 -7.80078 20.5 0 28.2998c7.7998 7.80078 20.5 7.80078 28.2998 0l17.7998 -17.7998l17.9004 17.7998c7.7998 7.80078 20.5 7.80078 28.2998 0zM248 176
c35.2998 0 64 -28.7002 64 -64s-28.7002 -64 -64 -64s-64 28.7002 -64 64s28.7002 64 64 64z" />
<glyph glyph-name="flushed" unicode="&#xf579;" horiz-adv-x="496"
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM344 304c44.2002 0 80 -35.7998 80 -80s-35.7998 -80 -80 -80
s-80 35.7998 -80 80s35.7998 80 80 80zM344 176c26.5 0 48 21.5 48 48s-21.5 48 -48 48s-48 -21.5 -48 -48s21.5 -48 48 -48zM344 248c13.2998 0 24 -10.7002 24 -24s-10.7002 -24 -24 -24s-24 10.7002 -24 24s10.7002 24 24 24zM232 224c0 -44.2002 -35.7998 -80 -80 -80
s-80 35.7998 -80 80s35.7998 80 80 80s80 -35.7998 80 -80zM152 176c26.5 0 48 21.5 48 48s-21.5 48 -48 48s-48 -21.5 -48 -48s21.5 -48 48 -48zM152 248c13.2998 0 24 -10.7002 24 -24s-10.7002 -24 -24 -24s-24 10.7002 -24 24s10.7002 24 24 24zM312 104
c13.2002 0 24 -10.7998 24 -24s-10.7998 -24 -24 -24h-128c-13.2002 0 -24 10.7998 -24 24s10.7998 24 24 24h128z" />
<glyph glyph-name="frown-open" unicode="&#xf57a;" horiz-adv-x="496"
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM200 240c0 -17.7002 -14.2998 -32 -32 -32s-32 14.2998 -32 32
s14.2998 32 32 32s32 -14.2998 32 -32zM328 272c17.7002 0 32 -14.2998 32 -32s-14.2998 -32 -32 -32s-32 14.2998 -32 32s14.2998 32 32 32zM248 160c35.5996 0 88.7998 -21.2998 95.7998 -61.2002c2 -11.7998 -9.09961 -21.5996 -20.5 -18.0996
c-31.2002 9.59961 -59.3994 15.2998 -75.2998 15.2998s-44.0996 -5.7002 -75.2998 -15.2998c-11.5 -3.40039 -22.5 6.2998 -20.5 18.0996c7 39.9004 60.2002 61.2002 95.7998 61.2002z" />
<glyph glyph-name="grimace" unicode="&#xf57f;" horiz-adv-x="496"
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM168 208c-17.7002 0 -32 14.2998 -32 32s14.2998 32 32 32
s32 -14.2998 32 -32s-14.2998 -32 -32 -32zM328 208c-17.7002 0 -32 14.2998 -32 32s14.2998 32 32 32s32 -14.2998 32 -32s-14.2998 -32 -32 -32zM344 192c26.5 0 48 -21.5 48 -48v-32c0 -26.5 -21.5 -48 -48 -48h-192c-26.5 0 -48 21.5 -48 48v32c0 26.5 21.5 48 48 48
h192zM176 96v24h-40v-8c0 -8.7998 7.2002 -16 16 -16h24zM176 136v24h-24c-8.7998 0 -16 -7.2002 -16 -16v-8h40zM240 96v24h-48v-24h48zM240 136v24h-48v-24h48zM304 96v24h-48v-24h48zM304 136v24h-48v-24h48zM360 112v8h-40v-24h24c8.7998 0 16 7.2002 16 16zM360 136v8
c0 8.7998 -7.2002 16 -16 16h-24v-24h40z" />
<glyph glyph-name="grin" unicode="&#xf580;" horiz-adv-x="496"
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM353.6 143.4c10 3.09961 19.3008 -5.5 17.7002 -15.3008
c-8 -47.0996 -71.2998 -80 -123.3 -80s-115.4 32.9004 -123.3 80c-1.7002 9.90039 7.7998 18.4004 17.7002 15.3008c26 -8.30078 64.3994 -13.1006 105.6 -13.1006s79.7002 4.7998 105.6 13.1006zM168 208c-17.7002 0 -32 14.2998 -32 32s14.2998 32 32 32
s32 -14.2998 32 -32s-14.2998 -32 -32 -32zM328 208c-17.7002 0 -32 14.2998 -32 32s14.2998 32 32 32s32 -14.2998 32 -32s-14.2998 -32 -32 -32z" />
<glyph glyph-name="grin-alt" unicode="&#xf581;" horiz-adv-x="496"
d="M200.3 200c-7.5 -11.4004 -24.5996 -12 -32.7002 0c-12.3994 18.7002 -15.1992 37.2998 -15.6992 56c0.599609 18.7002 3.2998 37.2998 15.6992 56c7.60059 11.4004 24.7002 12 32.7002 0c12.4004 -18.7002 15.2002 -37.2998 15.7002 -56
c-0.599609 -18.7002 -3.2998 -37.2998 -15.7002 -56zM328.3 200c-7.5 -11.4004 -24.5996 -12 -32.7002 0c-12.3994 18.7002 -15.1992 37.2998 -15.6992 56c0.599609 18.7002 3.2998 37.2998 15.6992 56c7.60059 11.4004 24.7002 12 32.7002 0
c12.4004 -18.7002 15.2002 -37.2998 15.7002 -56c-0.599609 -18.7002 -3.2998 -37.2998 -15.7002 -56zM248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200
s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM353.6 143.4c10 3.09961 19.3008 -5.5 17.7002 -15.3008c-8 -47.0996 -71.2998 -80 -123.3 -80s-115.4 32.8008 -123.3 80c-1.7002 10 7.7998 18.4004 17.7002 15.3008c26 -8.30078 64.3994 -13.1006 105.6 -13.1006
s79.7002 4.7998 105.6 13.1006z" />
<glyph glyph-name="grin-beam" unicode="&#xf582;" horiz-adv-x="496"
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM353.6 143.4c10 3.09961 19.3008 -5.5 17.7002 -15.3008
c-8 -47.0996 -71.2998 -80 -123.3 -80s-115.4 32.9004 -123.3 80c-1.7002 10 7.89941 18.4004 17.7002 15.3008c26 -8.30078 64.3994 -13.1006 105.6 -13.1006s79.7002 4.7998 105.6 13.1006zM117.7 216.3c-3.60059 1.10059 -6 4.60059 -5.7002 8.2998
c3.2998 42.1006 32.2002 71.4004 56 71.4004s52.7002 -29.2998 56 -71.4004c0.299805 -3.7998 -2.09961 -7.19922 -5.7002 -8.2998c-3.09961 -1 -7.2002 0 -9.2998 3.7002l-9.5 17c-7.7002 13.7002 -19.2002 21.5996 -31.5 21.5996s-23.7998 -7.89941 -31.5 -21.5996
l-9.5 -17c-1.90039 -3.2002 -5.7998 -4.7998 -9.2998 -3.7002zM277.7 216.3c-3.60059 1.10059 -6 4.60059 -5.7002 8.2998c3.2998 42.1006 32.2002 71.4004 56 71.4004s52.7002 -29.2998 56 -71.4004c0.299805 -3.7998 -2.09961 -7.19922 -5.7002 -8.2998
c-3.09961 -1 -7.2002 0 -9.2998 3.7002l-9.5 17c-7.7002 13.7002 -19.2002 21.5996 -31.5 21.5996s-23.7998 -7.89941 -31.5 -21.5996l-9.5 -17c-1.90039 -3.2002 -5.7998 -4.7998 -9.2998 -3.7002z" />
<glyph glyph-name="grin-beam-sweat" unicode="&#xf583;" horiz-adv-x="496"
d="M440 288c-29.5 0 -53.2998 26.2998 -53.2998 58.7002c0 25 31.7002 75.5 46.2002 97.2998c3.5 5.2998 10.5996 5.2998 14.1992 0c14.5 -21.7998 46.2002 -72.2998 46.2002 -97.2998c0 -32.4004 -23.7998 -58.7002 -53.2998 -58.7002zM248 48
c-51.9004 0 -115.3 32.9004 -123.3 80c-1.7002 10 7.89941 18.4004 17.7002 15.2998c26 -8.2998 64.3994 -13.0996 105.6 -13.0996s79.7002 4.7998 105.6 13.0996c10 3.2002 19.4004 -5.39941 17.7002 -15.2998c-8 -47.0996 -71.3994 -80 -123.3 -80zM378.3 216.3
c-3.09961 -0.899414 -7.2002 0.100586 -9.2998 3.7002l-9.5 17c-7.7002 13.7002 -19.2002 21.5996 -31.5 21.5996s-23.7998 -7.89941 -31.5 -21.5996l-9.5 -17c-1.90039 -3.2002 -5.7998 -4.7998 -9.2998 -3.7002c-3.60059 1.10059 -6 4.60059 -5.7002 8.2998
c3.2998 42.1006 32.2002 71.4004 56 71.4004s52.7002 -29.2998 56 -71.4004c0.299805 -3.7998 -2.09961 -7.19922 -5.7002 -8.2998zM483.6 269.2c8 -24.2998 12.4004 -50.2002 12.4004 -77.2002c0 -137 -111 -248 -248 -248s-248 111 -248 248s111 248 248 248
c45.7002 0 88.4004 -12.5996 125.2 -34.2002c-10.9004 -21.5996 -15.5 -36.2002 -17.2002 -45.7002c-31.2002 20.1006 -68.2002 31.9004 -108 31.9004c-110.3 0 -200 -89.7002 -200 -200s89.7002 -200 200 -200s200 89.7002 200 200
c0 22.5 -3.90039 44.0996 -10.7998 64.2998c0.399414 0 21.7998 -2.7998 46.3994 12.9004zM168 258.6c-12.2998 0 -23.7998 -7.7998 -31.5 -21.5996l-9.5 -17c-1.90039 -3.2002 -5.7998 -4.7998 -9.2998 -3.7002c-3.60059 1.10059 -6 4.60059 -5.7002 8.2998
c3.2998 42.1006 32.2002 71.4004 56 71.4004s52.7002 -29.2998 56 -71.4004c0.299805 -3.7998 -2.09961 -7.19922 -5.7002 -8.2998c-3.09961 -1 -7.2002 0 -9.2998 3.7002l-9.5 17c-7.7002 13.7002 -19.2002 21.5996 -31.5 21.5996z" />
<glyph glyph-name="grin-hearts" unicode="&#xf584;" horiz-adv-x="496"
d="M353.6 143.4c10 3.09961 19.3008 -5.5 17.7002 -15.3008c-8 -47.0996 -71.2998 -80 -123.3 -80s-115.4 32.8008 -123.3 80c-1.7002 10 7.89941 18.4004 17.7002 15.3008c26 -8.30078 64.3994 -13.1006 105.6 -13.1006s79.7002 4.7998 105.6 13.1006zM200.8 192.3
l-70.2002 18.1006c-20.3994 5.2998 -31.8994 27 -24.1992 47.1992c6.69922 17.7002 26.6992 26.7002 44.8994 22l7.10059 -1.89941l2 7.09961c5.09961 18.1006 22.8994 30.9004 41.5 27.9004c21.3994 -3.40039 34.3994 -24.2002 28.7998 -44.5l-19.4004 -69.9004
c-1.2998 -4.5 -6 -7.2002 -10.5 -6zM389.6 257.6c7.7002 -20.1992 -3.7998 -41.7998 -24.1992 -47.0996l-70.2002 -18.2002c-4.60059 -1.2002 -9.2998 1.5 -10.5 6l-19.4004 69.9004c-5.59961 20.2998 7.40039 41.0996 28.7998 44.5c18.7002 3 36.5 -9.7998 41.5 -27.9004
l2 -7.09961l7.10059 1.89941c18.2002 4.7002 38.2002 -4.39941 44.8994 -22zM248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200
s89.7002 -200 200 -200z" />
<glyph glyph-name="grin-squint" unicode="&#xf585;" horiz-adv-x="496"
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM353.6 143.4c10 3.09961 19.3008 -5.5 17.7002 -15.3008
c-8 -47.0996 -71.2998 -80 -123.3 -80s-115.4 32.9004 -123.3 80c-1.7002 9.90039 7.7998 18.4004 17.7002 15.3008c26 -8.30078 64.3994 -13.1006 105.6 -13.1006s79.7002 4.7998 105.6 13.1006zM118.9 184.2c-3.80078 4.39941 -3.90039 11 -0.100586 15.5l33.6006 40.2998
l-33.6006 40.2998c-3.7002 4.5 -3.7002 11 0.100586 15.5c3.89941 4.40039 10.1992 5.5 15.2998 2.5l80 -48c3.59961 -2.2002 5.7998 -6.09961 5.7998 -10.2998s-2.2002 -8.09961 -5.7998 -10.2998l-80 -48c-5.40039 -3.2002 -11.7002 -1.7002 -15.2998 2.5zM361.8 181.7
l-80 48c-3.59961 2.2002 -5.7998 6.09961 -5.7998 10.2998s2.2002 8.09961 5.7998 10.2998l80 48c5.10059 2.90039 11.5 1.90039 15.2998 -2.5c3.80078 -4.5 3.90039 -11 0.100586 -15.5l-33.6006 -40.2998l33.6006 -40.2998c3.7002 -4.5 3.7002 -11 -0.100586 -15.5
c-3.59961 -4.2002 -9.89941 -5.7002 -15.2998 -2.5z" />
<glyph glyph-name="grin-squint-tears" unicode="&#xf586;"
d="M117.1 63.9004c6.30078 0.899414 11.7002 -4.5 10.9004 -10.9004c-3.7002 -25.7998 -13.7002 -84 -30.5996 -100.9c-22 -21.8994 -57.9004 -21.5 -80.3008 0.900391c-22.3994 22.4004 -22.7998 58.4004 -0.899414 80.2998
c16.8994 16.9004 75.0996 26.9004 100.899 30.6006zM75.9004 105.6c-19.6006 -3.89941 -35.1006 -8.09961 -47.3008 -12.1992c-39.2998 90.5996 -22.0996 199.899 52 274c48.5 48.3994 111.9 72.5996 175.4 72.5996c38.9004 0 77.7998 -9.2002 113.2 -27.4004
c-4 -12.1992 -8.2002 -28 -12 -48.2998c-30.4004 17.9004 -65 27.7002 -101.2 27.7002c-53.4004 0 -103.6 -20.7998 -141.4 -58.5996c-61.5996 -61.5 -74.2998 -153.4 -38.6992 -227.801zM428.2 293.2c20.2998 3.89941 36.2002 8 48.5 12
c47.8994 -93.2002 32.8994 -210.5 -45.2002 -288.601c-48.5 -48.3994 -111.9 -72.5996 -175.4 -72.5996c-33.6992 0 -67.2998 7 -98.6992 20.5996c4.19922 12.2002 8.2998 27.7002 12.1992 47.2002c26.6006 -12.7998 55.9004 -19.7998 86.4004 -19.7998
c53.4004 0 103.6 20.7998 141.4 58.5996c65.6992 65.7002 75.7998 166 30.7998 242.601zM394.9 320.1c-6.30078 -0.899414 -11.7002 4.5 -10.9004 10.9004c3.7002 25.7998 13.7002 84 30.5996 100.9c22 21.8994 57.9004 21.5 80.3008 -0.900391
c22.3994 -22.4004 22.7998 -58.4004 0.899414 -80.2998c-16.8994 -16.9004 -75.0996 -26.9004 -100.899 -30.6006zM207.9 211.8c3 -3 4.19922 -7.2998 3.19922 -11.5l-22.5996 -90.5c-1.40039 -5.39941 -6.2002 -9.09961 -11.7002 -9.09961h-0.899414
c-5.80078 0.5 -10.5 5.09961 -11 10.8994l-4.80078 52.3008l-52.2998 4.7998c-5.7998 0.5 -10.3994 5.2002 -10.8994 11c-0.400391 5.89941 3.39941 11.2002 9.09961 12.5996l90.5 22.7002c4.2002 1 8.40039 -0.200195 11.4004 -3.2002zM247.6 236.9
c-0.0996094 0 -6.39941 -1.80078 -11.3994 3.19922c-3 3 -4.2002 7.30078 -3.2002 11.4004l22.5996 90.5c1.40039 5.7002 7 9.2002 12.6006 9.09961c5.7998 -0.5 10.5 -5.09961 11 -10.8994l4.7998 -52.2998l52.2998 -4.80078c5.7998 -0.5 10.4004 -5.19922 10.9004 -11
c0.399414 -5.89941 -3.40039 -11.1992 -9.10059 -12.5996zM299.6 148.4c29.1006 29.0996 53 59.5996 65.3008 83.7998c4.89941 9.2998 17.5996 9.89941 23.3994 1.7002c27.7002 -38.9004 6.10059 -106.9 -30.5996 -143.7s-104.8 -58.2998 -143.7 -30.6006
c-8.2998 5.90039 -7.5 18.6006 1.7002 23.4004c24.2002 12.5 54.7998 36.2998 83.8994 65.4004z" />
<glyph glyph-name="grin-stars" unicode="&#xf587;" horiz-adv-x="496"
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM353.6 143.4c10 3.09961 19.3008 -5.5 17.7002 -15.3008
c-8 -47.0996 -71.2998 -80 -123.3 -80s-115.4 32.8008 -123.3 80c-1.7002 10 7.89941 18.4004 17.7002 15.3008c26 -8.30078 64.3994 -13.1006 105.6 -13.1006s79.7002 4.7998 105.6 13.1006zM125.7 200.9l6.09961 34.8994l-25.3994 24.6006
c-4.60059 4.59961 -1.90039 12.2998 4.2998 13.1992l34.8994 5l15.5 31.6006c2.90039 5.7998 11 5.7998 13.9004 0l15.5 -31.6006l34.9004 -5c6.19922 -1 8.7998 -8.69922 4.2998 -13.1992l-25.4004 -24.6006l6 -34.8994c1 -6.2002 -5.39941 -11 -11 -7.90039
l-31.2998 16.2998l-31.2998 -16.2998c-5.60059 -3.09961 -12 1.7002 -11 7.90039zM385.4 273.6c6.19922 -1 8.89941 -8.59961 4.39941 -13.1992l-25.3994 -24.6006l6 -34.8994c1 -6.2002 -5.40039 -11 -11 -7.90039l-31.3008 16.2998l-31.2998 -16.2998
c-5.59961 -3.09961 -12 1.7002 -11 7.90039l6 34.8994l-25.3994 24.6006c-4.60059 4.59961 -1.90039 12.2998 4.2998 13.1992l34.8994 5l15.5 31.6006c2.90039 5.7998 11 5.7998 13.9004 0l15.5 -31.6006z" />
<glyph glyph-name="grin-tears" unicode="&#xf588;" horiz-adv-x="640"
d="M117.1 191.9c6.30078 0.899414 11.7002 -4.5 10.9004 -10.9004c-3.7002 -25.7998 -13.7002 -84 -30.5996 -100.9c-22 -21.8994 -57.9004 -21.5 -80.3008 0.900391c-22.3994 22.4004 -22.7998 58.4004 -0.899414 80.2998c16.8994 16.9004 75.0996 26.9004 100.899 30.6006
zM623.8 161.3c21.9004 -21.8994 21.5 -57.8994 -0.799805 -80.2002c-22.4004 -22.3994 -58.4004 -22.7998 -80.2998 -0.899414c-16.9004 16.8994 -26.9004 75.0996 -30.6006 100.899c-0.899414 6.30078 4.5 11.7002 10.8008 10.8008
c25.7998 -3.7002 84 -13.7002 100.899 -30.6006zM497.2 99.5996c12.3994 -37.2998 25.0996 -43.7998 28.2998 -46.5c-44.5996 -65.7998 -120 -109.1 -205.5 -109.1s-160.9 43.2998 -205.5 109.1c3.09961 2.60059 15.7998 9.10059 28.2998 46.5
c33.4004 -63.8994 100.3 -107.6 177.2 -107.6s143.8 43.7002 177.2 107.6zM122.7 223.5c-2.40039 0.299805 -5 2.5 -49.5 -6.90039c12.3994 125.4 118.1 223.4 246.8 223.4s234.4 -98 246.8 -223.5c-44.2998 9.40039 -47.3994 7.2002 -49.5 7
c-15.2002 95.2998 -97.7998 168.5 -197.3 168.5s-182.1 -73.2002 -197.3 -168.5zM320 48c-51.9004 0 -115.3 32.9004 -123.3 80c-1.7002 10 7.89941 18.4004 17.7002 15.2998c26 -8.2998 64.3994 -13.0996 105.6 -13.0996s79.7002 4.7998 105.6 13.0996
c10 3.2002 19.4004 -5.39941 17.7002 -15.2998c-8 -47.0996 -71.3994 -80 -123.3 -80zM450.3 216.3c-3.09961 -0.899414 -7.2002 0.100586 -9.2998 3.7002l-9.5 17c-7.7002 13.7002 -19.2002 21.5996 -31.5 21.5996s-23.7998 -7.89941 -31.5 -21.5996l-9.5 -17
c-1.90039 -3.2002 -5.7998 -4.7998 -9.2998 -3.7002c-3.60059 1.10059 -6 4.60059 -5.7002 8.2998c3.2998 42.1006 32.2002 71.4004 56 71.4004s52.7002 -29.2998 56 -71.4004c0.299805 -3.7998 -2.09961 -7.19922 -5.7002 -8.2998zM240 258.6
c-12.2998 0 -23.7998 -7.7998 -31.5 -21.5996l-9.5 -17c-1.90039 -3.2002 -5.7998 -4.7998 -9.2998 -3.7002c-3.60059 1.10059 -6 4.60059 -5.7002 8.2998c3.2998 42.1006 32.2002 71.4004 56 71.4004s52.7002 -29.2998 56 -71.4004
c0.299805 -3.7998 -2.09961 -7.19922 -5.7002 -8.2998c-3.09961 -1 -7.2002 0 -9.2998 3.7002l-9.5 17c-7.7002 13.7002 -19.2002 21.5996 -31.5 21.5996z" />
<glyph glyph-name="grin-tongue" unicode="&#xf589;" horiz-adv-x="496"
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM312 40h0.0996094v43.7998l-17.6992 8.7998c-15.1006 7.60059 -31.5 -1.69922 -34.9004 -16.5l-2.7998 -12.0996c-2.10059 -9.2002 -15.2002 -9.2002 -17.2998 0
l-2.80078 12.0996c-3.39941 14.8008 -19.8994 24 -34.8994 16.5l-17.7002 -8.7998v-42.7998c0 -35.2002 28 -64.5 63.0996 -65c35.8008 -0.5 64.9004 28.4004 64.9004 64zM340.2 14.7002c64 33.3994 107.8 100.3 107.8 177.3c0 110.3 -89.7002 200 -200 200
s-200 -89.7002 -200 -200c0 -77 43.7998 -143.9 107.8 -177.3c-2.2002 8.09961 -3.7998 16.5 -3.7998 25.2998v43.5c-14.2002 12.4004 -24.4004 27.5 -27.2998 44.5c-1.7002 10 7.7998 18.4004 17.7002 15.2998c26 -8.2998 64.3994 -13.0996 105.6 -13.0996
s79.7002 4.7998 105.6 13.0996c10 3.2002 19.4004 -5.39941 17.7002 -15.2998c-2.89941 -17 -13.0996 -32.0996 -27.2998 -44.5v-43.5c0 -8.7998 -1.59961 -17.2002 -3.7998 -25.2998zM168 272c17.7002 0 32 -14.2998 32 -32s-14.2998 -32 -32 -32s-32 14.2998 -32 32
s14.2998 32 32 32zM328 272c17.7002 0 32 -14.2998 32 -32s-14.2998 -32 -32 -32s-32 14.2998 -32 32s14.2998 32 32 32z" />
<glyph glyph-name="grin-tongue-squint" unicode="&#xf58a;" horiz-adv-x="496"
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM312 40h0.0996094v43.7998l-17.6992 8.7998c-15.1006 7.60059 -31.5 -1.69922 -34.9004 -16.5l-2.7998 -12.0996c-2.10059 -9.2002 -15.2002 -9.2002 -17.2998 0
l-2.80078 12.0996c-3.39941 14.8008 -19.8994 24 -34.8994 16.5l-17.7002 -8.7998v-42.7998c0 -35.2002 28 -64.5 63.0996 -65c35.8008 -0.5 64.9004 28.4004 64.9004 64zM340.2 14.7002c64 33.3994 107.8 100.3 107.8 177.3c0 110.3 -89.7002 200 -200 200
s-200 -89.7002 -200 -200c0 -77 43.7998 -143.9 107.8 -177.3c-2.2002 8.09961 -3.7998 16.5 -3.7998 25.2998v43.5c-14.2002 12.4004 -24.4004 27.5 -27.2998 44.5c-1.7002 10 7.7998 18.4004 17.7002 15.2998c26 -8.2998 64.3994 -13.0996 105.6 -13.0996
s79.7002 4.7998 105.6 13.0996c10 3.2002 19.4004 -5.39941 17.7002 -15.2998c-2.89941 -17 -13.0996 -32.0996 -27.2998 -44.5v-43.5c0 -8.7998 -1.59961 -17.2002 -3.7998 -25.2998zM377.1 295.8c3.80078 -4.39941 3.90039 -11 0.100586 -15.5l-33.6006 -40.2998
l33.6006 -40.2998c3.7002 -4.5 3.7002 -11 -0.100586 -15.5c-3.59961 -4.2002 -9.89941 -5.7002 -15.2998 -2.5l-80 48c-3.59961 2.2002 -5.7998 6.09961 -5.7998 10.2998s2.2002 8.09961 5.7998 10.2998l80 48c5 3 11.5 1.90039 15.2998 -2.5zM214.2 250.3
c3.59961 -2.2002 5.7998 -6.09961 5.7998 -10.2998s-2.2002 -8.09961 -5.7998 -10.2998l-80 -48c-5.40039 -3.2002 -11.7002 -1.7002 -15.2998 2.5c-3.80078 4.5 -3.90039 11 -0.100586 15.5l33.6006 40.2998l-33.6006 40.2998c-3.7002 4.5 -3.7002 11 0.100586 15.5
c3.89941 4.5 10.2998 5.5 15.2998 2.5z" />
<glyph glyph-name="grin-tongue-wink" unicode="&#xf58b;" horiz-adv-x="496"
d="M152 268c25.7002 0 55.9004 -16.9004 59.7998 -42.0996c0.799805 -5 -1.7002 -10 -6.09961 -12.4004c-5.7002 -3.09961 -11.2002 -0.599609 -13.7002 1.59961l-9.5 8.5c-14.7998 13.2002 -46.2002 13.2002 -61 0l-9.5 -8.5
c-3.7998 -3.39941 -9.2998 -4 -13.7002 -1.59961c-4.39941 2.40039 -6.89941 7.40039 -6.09961 12.4004c3.89941 25.1992 34.0996 42.0996 59.7998 42.0996zM328 320c44.2002 0 80 -35.7998 80 -80s-35.7998 -80 -80 -80s-80 35.7998 -80 80s35.7998 80 80 80zM328 192
c26.5 0 48 21.5 48 48s-21.5 48 -48 48s-48 -21.5 -48 -48s21.5 -48 48 -48zM328 264c13.2998 0 24 -10.7002 24 -24s-10.7002 -24 -24 -24s-24 10.7002 -24 24s10.7002 24 24 24zM248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248z
M312 40h0.0996094v43.7998l-17.6992 8.7998c-15.1006 7.60059 -31.5 -1.69922 -34.9004 -16.5l-2.7998 -12.0996c-2.10059 -9.2002 -15.2002 -9.2002 -17.2998 0l-2.80078 12.0996c-3.39941 14.8008 -19.8994 24 -34.8994 16.5l-17.7002 -8.7998v-42.7998
c0 -35.2002 28 -64.5 63.0996 -65c35.8008 -0.5 64.9004 28.4004 64.9004 64zM340.2 14.7002c64 33.3994 107.8 100.3 107.8 177.3c0 110.3 -89.7002 200 -200 200s-200 -89.7002 -200 -200c0 -77 43.7998 -143.9 107.8 -177.3
c-2.2002 8.09961 -3.7998 16.5 -3.7998 25.2998v43.5c-14.2002 12.4004 -24.4004 27.5 -27.2998 44.5c-1.7002 10 7.7998 18.4004 17.7002 15.2998c26 -8.2998 64.3994 -13.0996 105.6 -13.0996s79.7002 4.7998 105.6 13.0996c10 3.2002 19.4004 -5.39941 17.7002 -15.2998
c-2.89941 -17 -13.0996 -32.0996 -27.2998 -44.5v-43.5c0 -8.7998 -1.59961 -17.2002 -3.7998 -25.2998z" />
<glyph glyph-name="grin-wink" unicode="&#xf58c;" horiz-adv-x="496"
d="M328 268c25.6904 0 55.8799 -16.9199 59.8701 -42.1201c1.72949 -11.0898 -11.3506 -18.2695 -19.8301 -10.8398l-9.5498 8.47949c-14.8105 13.1904 -46.1602 13.1904 -60.9707 0l-9.5498 -8.47949c-8.33008 -7.40039 -21.5801 -0.379883 -19.8301 10.8398
c3.98047 25.2002 34.1699 42.1201 59.8604 42.1201zM168 208c-17.6699 0 -32 14.3301 -32 32s14.3301 32 32 32s32 -14.3301 32 -32s-14.3301 -32 -32 -32zM353.55 143.36c10.04 3.13965 19.3906 -5.4502 17.71 -15.3408
c-7.92969 -47.1494 -71.3193 -80.0195 -123.26 -80.0195s-115.33 32.8701 -123.26 80.0195c-1.69043 9.9707 7.76953 18.4707 17.71 15.3408c25.9297 -8.31055 64.3994 -13.0605 105.55 -13.0605s79.6201 4.75977 105.55 13.0605zM248 440c136.97 0 248 -111.03 248 -248
s-111.03 -248 -248 -248s-248 111.03 -248 248s111.03 248 248 248zM248 -8c110.28 0 200 89.7197 200 200s-89.7197 200 -200 200s-200 -89.7197 -200 -200s89.7197 -200 200 -200z" />
<glyph glyph-name="kiss" unicode="&#xf596;" horiz-adv-x="496"
d="M168 272c17.7002 0 32 -14.2998 32 -32s-14.2998 -32 -32 -32s-32 14.2998 -32 32s14.2998 32 32 32zM304 140c0 -13 -13.4004 -27.2998 -35.0996 -36.4004c21.7998 -8.69922 35.1992 -23 35.1992 -36c0 -19.1992 -28.6992 -41.5 -71.5 -44h-0.5
c-3.69922 0 -7 2.60059 -7.7998 6.2002c-0.899414 3.7998 1.10059 7.7002 4.7002 9.2002l17 7.2002c12.9004 5.5 20.7002 13.5 20.7002 21.5s-7.7998 16 -20.7998 21.5l-16.9004 7.2002c-6 2.59961 -5.7002 12.3994 0 14.7998l17 7.2002
c12.9004 5.5 20.7002 13.5 20.7002 21.5s-7.7998 16 -20.7998 21.5l-16.9004 7.19922c-3.59961 1.5 -5.59961 5.40039 -4.7002 9.2002c0.799805 3.7998 4.40039 6.60059 8.2002 6.2002c42.7002 -2.5 71.5 -24.7998 71.5 -44zM248 440c137 0 248 -111 248 -248
s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM328 272c17.7002 0 32 -14.2998 32 -32s-14.2998 -32 -32 -32s-32 14.2998 -32 32s14.2998 32 32 32z
" />
<glyph glyph-name="kiss-beam" unicode="&#xf597;" horiz-adv-x="496"
d="M168 296c23.7998 0 52.7002 -29.2998 55.7998 -71.4004c0.299805 -3.7998 -2 -7.19922 -5.59961 -8.2998c-3.10059 -1 -7.2002 0 -9.2998 3.7002l-9.5 17c-7.7002 13.7002 -19.2002 21.5996 -31.5 21.5996c-12.3008 0 -23.8008 -7.89941 -31.5 -21.5996l-9.5 -17
c-1.80078 -3.2002 -5.80078 -4.7002 -9.30078 -3.7002c-3.59961 1.10059 -5.89941 4.60059 -5.59961 8.2998c3.2998 42.1006 32.2002 71.4004 56 71.4004zM248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8
c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM304 140c0 -13 -13.4004 -27.2998 -35.0996 -36.4004c21.7998 -8.69922 35.1992 -23 35.1992 -36c0 -19.1992 -28.6992 -41.5 -71.5 -44h-0.5
c-3.69922 0 -7 2.60059 -7.7998 6.2002c-0.899414 3.7998 1.10059 7.7002 4.7002 9.2002l17 7.2002c12.9004 5.5 20.7002 13.5 20.7002 21.5s-7.7998 16 -20.7998 21.5l-16.9004 7.2002c-6 2.59961 -5.7002 12.3994 0 14.7998l17 7.2002
c12.9004 5.5 20.7002 13.5 20.7002 21.5s-7.7998 16 -20.7998 21.5l-16.9004 7.19922c-3.59961 1.5 -5.59961 5.40039 -4.7002 9.2002c0.799805 3.7998 4.40039 6.60059 8.2002 6.2002c42.7002 -2.5 71.5 -24.7998 71.5 -44zM328 296
c23.7998 0 52.7002 -29.2998 55.7998 -71.4004c0.299805 -3.7998 -2 -7.19922 -5.59961 -8.2998c-3.10059 -1 -7.2002 0 -9.2998 3.7002l-9.5 17c-7.7002 13.7002 -19.2002 21.5996 -31.5 21.5996c-12.3008 0 -23.8008 -7.89941 -31.5 -21.5996l-9.5 -17
c-1.80078 -3.2002 -5.80078 -4.7002 -9.30078 -3.7002c-3.59961 1.10059 -5.89941 4.60059 -5.59961 8.2998c3.2998 42.1006 32.2002 71.4004 56 71.4004z" />
<glyph glyph-name="kiss-wink-heart" unicode="&#xf598;" horiz-adv-x="504"
d="M304 139.5c0 -13 -13.4004 -27.2998 -35.0996 -36.4004c21.7998 -8.69922 35.1992 -23 35.1992 -36c0 -19.1992 -28.6992 -41.5 -71.5 -44h-0.5c-3.69922 0 -7 2.60059 -7.7998 6.2002c-0.899414 3.7998 1.10059 7.7002 4.7002 9.2002l17 7.2002
c12.9004 5.5 20.7002 13.5 20.7002 21.5s-7.7998 16 -20.7998 21.5l-16.9004 7.2002c-6 2.59961 -5.7002 12.3994 0 14.7998l17 7.2002c12.9004 5.5 20.7002 13.5 20.7002 21.5s-7.7998 16 -20.7998 21.5l-16.9004 7.19922c-3.59961 1.5 -5.59961 5.40039 -4.7002 9.2002
c0.799805 3.7998 4.40039 6.60059 8.2002 6.2002c42.7002 -2.5 71.5 -24.7998 71.5 -44zM374.5 223c-14.7998 13.2002 -46.2002 13.2002 -61 0l-9.5 -8.5c-2.5 -2.2998 -7.90039 -4.7002 -13.7002 -1.59961c-4.39941 2.39941 -6.89941 7.39941 -6.09961 12.3994
c3.89941 25.2002 34.2002 42.1006 59.7998 42.1006s55.7998 -16.9004 59.7998 -42.1006c0.799805 -5 -1.7002 -10 -6.09961 -12.3994c-4.40039 -2.40039 -9.90039 -1.7002 -13.7002 1.59961zM136 239.5c0 17.7002 14.2998 32 32 32s32 -14.2998 32 -32s-14.2998 -32 -32 -32
s-32 14.2998 -32 32zM501.1 45.5c9.2002 -23.9004 -4.39941 -49.4004 -28.5 -55.7002l-83 -21.5c-5.39941 -1.39941 -10.8994 1.7998 -12.3994 7.10059l-22.9004 82.5996c-6.59961 24 8.7998 48.5996 34 52.5996c22 3.5 43.1006 -11.5996 49 -33l2.2998 -8.39941
l8.40039 2.2002c21.5996 5.59961 45.0996 -5.10059 53.0996 -25.9004zM334 11.7002c17.7002 -64 10.9004 -39.5 13.4004 -46.7998c-30.5 -13.4004 -64 -20.9004 -99.4004 -20.9004c-137 0 -248 111 -248 248s111 248 248 248s248 -111 247.9 -248
c0 -31.7998 -6.2002 -62.0996 -17.1006 -90c-6 1.5 -12.2002 2.7998 -18.5996 2.90039c-5.60059 9.69922 -13.6006 17.5 -22.6006 23.8994c6.7002 19.9004 10.4004 41.1006 10.4004 63.2002c0 110.3 -89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200
c30.7998 0 59.9004 7.2002 86 19.7002z" />
<glyph glyph-name="laugh" unicode="&#xf599;" horiz-adv-x="496"
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM389.4 50.5996c37.7998 37.8008 58.5996 88 58.5996 141.4s-20.7998 103.6 -58.5996 141.4c-37.8008 37.7998 -88 58.5996 -141.4 58.5996s-103.6 -20.7998 -141.4 -58.5996
c-37.7998 -37.8008 -58.5996 -88 -58.5996 -141.4s20.7998 -103.6 58.5996 -141.4c37.8008 -37.7998 88 -58.5996 141.4 -58.5996s103.6 20.7998 141.4 58.5996zM328 224c-17.7002 0 -32 14.2998 -32 32s14.2998 32 32 32s32 -14.2998 32 -32s-14.2998 -32 -32 -32zM168 224
c-17.7002 0 -32 14.2998 -32 32s14.2998 32 32 32s32 -14.2998 32 -32s-14.2998 -32 -32 -32zM362.4 160c8.19922 0 14.5 -7 13.5 -15c-7.5 -59.2002 -58.9004 -105 -121.101 -105h-13.5996c-62.2002 0 -113.601 45.7998 -121.101 105c-1 8 5.30078 15 13.5 15h228.801z" />
<glyph glyph-name="laugh-beam" unicode="&#xf59a;" horiz-adv-x="496"
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM389.4 50.5996c37.7998 37.8008 58.5996 88 58.5996 141.4s-20.7998 103.6 -58.5996 141.4c-37.8008 37.7998 -88 58.5996 -141.4 58.5996s-103.6 -20.7998 -141.4 -58.5996
c-37.7998 -37.8008 -58.5996 -88 -58.5996 -141.4s20.7998 -103.6 58.5996 -141.4c37.8008 -37.7998 88 -58.5996 141.4 -58.5996s103.6 20.7998 141.4 58.5996zM328 296c23.7998 0 52.7002 -29.2998 55.7998 -71.4004c0.700195 -8.5 -10.7998 -11.8994 -14.8994 -4.5
l-9.5 17c-7.7002 13.7002 -19.2002 21.6006 -31.5 21.6006c-12.3008 0 -23.8008 -7.90039 -31.5 -21.6006l-9.5 -17c-4.10059 -7.39941 -15.6006 -4.09961 -14.9004 4.5c3.2998 42.1006 32.2002 71.4004 56 71.4004zM127 220.1c-4.2002 -7.39941 -15.7002 -4 -15.0996 4.5
c3.2998 42.1006 32.1992 71.4004 56 71.4004c23.7998 0 52.6992 -29.2998 56 -71.4004c0.699219 -8.5 -10.8008 -11.8994 -14.9004 -4.5l-9.5 17c-7.7002 13.7002 -19.2002 21.6006 -31.5 21.6006s-23.7998 -7.90039 -31.5 -21.6006zM362.4 160c8.19922 0 14.5 -7 13.5 -15
c-7.5 -59.2002 -58.9004 -105 -121.101 -105h-13.5996c-62.2002 0 -113.601 45.7998 -121.101 105c-1 8 5.30078 15 13.5 15h228.801z" />
<glyph glyph-name="laugh-squint" unicode="&#xf59b;" horiz-adv-x="496"
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM389.4 50.5996c37.7998 37.8008 58.5996 88 58.5996 141.4s-20.7998 103.6 -58.5996 141.4c-37.8008 37.7998 -88 58.5996 -141.4 58.5996s-103.6 -20.7998 -141.4 -58.5996
c-37.7998 -37.8008 -58.5996 -88 -58.5996 -141.4s20.7998 -103.6 58.5996 -141.4c37.8008 -37.7998 88 -58.5996 141.4 -58.5996s103.6 20.7998 141.4 58.5996zM343.6 252l33.6006 -40.2998c8.59961 -10.4004 -3.90039 -24.7998 -15.4004 -18l-80 48
c-7.7998 4.7002 -7.7998 15.8994 0 20.5996l80 48c11.6006 6.7998 24 -7.7002 15.4004 -18zM134.2 193.7c-11.6006 -6.7998 -24.1006 7.59961 -15.4004 18l33.6006 40.2998l-33.6006 40.2998c-8.59961 10.2998 3.7998 24.9004 15.4004 18l80 -48
c7.7998 -4.7002 7.7998 -15.8994 0 -20.5996zM362.4 160c8.19922 0 14.5 -7 13.5 -15c-7.5 -59.2002 -58.9004 -105 -121.101 -105h-13.5996c-62.2002 0 -113.601 45.7998 -121.101 105c-1 8 5.30078 15 13.5 15h228.801z" />
<glyph glyph-name="laugh-wink" unicode="&#xf59c;" horiz-adv-x="496"
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM389.4 50.5996c37.7998 37.8008 58.5996 88 58.5996 141.4s-20.7998 103.6 -58.5996 141.4c-37.8008 37.7998 -88 58.5996 -141.4 58.5996s-103.6 -20.7998 -141.4 -58.5996
c-37.7998 -37.8008 -58.5996 -88 -58.5996 -141.4s20.7998 -103.6 58.5996 -141.4c37.8008 -37.7998 88 -58.5996 141.4 -58.5996s103.6 20.7998 141.4 58.5996zM328 284c25.7002 0 55.9004 -16.9004 59.7002 -42.0996c1.7998 -11.1006 -11.2998 -18.2002 -19.7998 -10.8008
l-9.5 8.5c-14.8008 13.2002 -46.2002 13.2002 -61 0l-9.5 -8.5c-8.30078 -7.39941 -21.5 -0.399414 -19.8008 10.8008c4 25.1992 34.2002 42.0996 59.9004 42.0996zM168 224c-17.7002 0 -32 14.2998 -32 32s14.2998 32 32 32s32 -14.2998 32 -32s-14.2998 -32 -32 -32z
M362.4 160c8.19922 0 14.5 -7 13.5 -15c-7.5 -59.2002 -58.9004 -105 -121.101 -105h-13.5996c-62.2002 0 -113.601 45.7998 -121.101 105c-1 8 5.30078 15 13.5 15h228.801z" />
<glyph glyph-name="meh-blank" unicode="&#xf5a4;" horiz-adv-x="496"
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM168 272c17.7002 0 32 -14.2998 32 -32s-14.2998 -32 -32 -32
s-32 14.2998 -32 32s14.2998 32 32 32zM328 272c17.7002 0 32 -14.2998 32 -32s-14.2998 -32 -32 -32s-32 14.2998 -32 32s14.2998 32 32 32z" />
<glyph glyph-name="meh-rolling-eyes" unicode="&#xf5a5;" horiz-adv-x="496"
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM336 296c39.7998 0 72 -32.2002 72 -72s-32.2002 -72 -72 -72
s-72 32.2002 -72 72s32.2002 72 72 72zM336 184c22.0996 0 40 17.9004 40 40c0 13.5996 -7.2998 25.0996 -17.7002 32.2998c1 -2.59961 1.7002 -5.39941 1.7002 -8.2998c0 -13.2998 -10.7002 -24 -24 -24s-24 10.7002 -24 24c0 3 0.700195 5.7002 1.7002 8.2998
c-10.4004 -7.2002 -17.7002 -18.7002 -17.7002 -32.2998c0 -22.0996 17.9004 -40 40 -40zM232 224c0 -39.7998 -32.2002 -72 -72 -72s-72 32.2002 -72 72s32.2002 72 72 72s72 -32.2002 72 -72zM120 224c0 -22.0996 17.9004 -40 40 -40s40 17.9004 40 40
c0 13.5996 -7.2998 25.0996 -17.7002 32.2998c1 -2.59961 1.7002 -5.39941 1.7002 -8.2998c0 -13.2998 -10.7002 -24 -24 -24s-24 10.7002 -24 24c0 3 0.700195 5.7002 1.7002 8.2998c-10.4004 -7.2002 -17.7002 -18.7002 -17.7002 -32.2998zM312 96
c13.2002 0 24 -10.7998 24 -24s-10.7998 -24 -24 -24h-128c-13.2002 0 -24 10.7998 -24 24s10.7998 24 24 24h128z" />
<glyph glyph-name="sad-cry" unicode="&#xf5b3;" horiz-adv-x="496"
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM392 53.5996c34.5996 35.9004 56 84.7002 56 138.4c0 110.3 -89.7002 200 -200 200s-200 -89.7002 -200 -200c0 -53.7002 21.4004 -102.4 56 -138.4v114.4
c0 13.2002 10.7998 24 24 24s24 -10.7998 24 -24v-151.4c28.5 -15.5996 61.2002 -24.5996 96 -24.5996s67.5 9 96 24.5996v151.4c0 13.2002 10.7998 24 24 24s24 -10.7998 24 -24v-114.4zM205.8 213.5c-5.7998 -3.2002 -11.2002 -0.700195 -13.7002 1.59961l-9.5 8.5
c-14.7998 13.2002 -46.1992 13.2002 -61 0l-9.5 -8.5c-3.7998 -3.39941 -9.2998 -4 -13.6992 -1.59961c-4.40039 2.40039 -6.90039 7.40039 -6.10059 12.4004c3.90039 25.1992 34.2002 42.0996 59.7998 42.0996c25.6006 0 55.8008 -16.9004 59.8008 -42.0996
c0.799805 -5 -1.7002 -10 -6.10059 -12.4004zM344 268c25.7002 0 55.9004 -16.9004 59.7998 -42.0996c0.799805 -5 -1.7002 -10 -6.09961 -12.4004c-5.7002 -3.09961 -11.2002 -0.599609 -13.7002 1.59961l-9.5 8.5c-14.7998 13.2002 -46.2002 13.2002 -61 0l-9.5 -8.5
c-3.7998 -3.39941 -9.2002 -4 -13.7002 -1.59961c-4.39941 2.40039 -6.89941 7.40039 -6.09961 12.4004c3.89941 25.1992 34.0996 42.0996 59.7998 42.0996zM248 176c30.9004 0 56 -28.7002 56 -64s-25.0996 -64 -56 -64s-56 28.7002 -56 64s25.0996 64 56 64z" />
<glyph glyph-name="sad-tear" unicode="&#xf5b4;" horiz-adv-x="496"
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM256 144c38.0996 0 74 -16.7998 98.5 -46.0996
c8.5 -10.2002 7.09961 -25.3008 -3.09961 -33.8008c-10.6006 -8.7998 -25.7002 -6.69922 -33.8008 3.10059c-15.2998 18.2998 -37.7998 28.7998 -61.5996 28.7998c-13.2002 0 -24 10.7998 -24 24s10.7998 24 24 24zM168 208c-17.7002 0 -32 14.2998 -32 32s14.2998 32 32 32
s32 -14.2998 32 -32s-14.2998 -32 -32 -32zM328 272c17.7002 0 32 -14.2998 32 -32s-14.2998 -32 -32 -32s-32 14.2998 -32 32s14.2998 32 32 32zM162.4 173.2c2.7998 3.7002 8.39941 3.7002 11.1992 0c11.4004 -15.2998 36.4004 -50.6006 36.4004 -68.1006
c0 -22.6992 -18.7998 -41.0996 -42 -41.0996s-42 18.4004 -42 41.0996c0 17.5 25 52.8008 36.4004 68.1006z" />
<glyph glyph-name="smile-beam" unicode="&#xf5b8;" horiz-adv-x="496"
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM332 135.4c8.5 10.1992 23.5996 11.5 33.7998 3.09961
c10.2002 -8.5 11.6006 -23.5996 3.10059 -33.7998c-30 -36 -74.1006 -56.6006 -120.9 -56.6006s-90.9004 20.6006 -120.9 56.6006c-8.39941 10.2002 -7.09961 25.2998 3.10059 33.7998c10.2002 8.40039 25.2998 7.09961 33.7998 -3.09961
c20.7998 -25.1006 51.5 -39.4004 84 -39.4004s63.2002 14.4004 84 39.4004zM136.5 237l-9.5 -17c-1.90039 -3.2002 -5.90039 -4.7998 -9.2998 -3.7002c-3.60059 1.10059 -6 4.60059 -5.7002 8.2998c3.2998 42.1006 32.2002 71.4004 56 71.4004s52.7002 -29.2998 56 -71.4004
c0.299805 -3.7998 -2.09961 -7.19922 -5.7002 -8.2998c-3.09961 -1 -7.2002 0 -9.2998 3.7002l-9.5 17c-7.7002 13.7002 -19.2002 21.5996 -31.5 21.5996s-23.7998 -7.89941 -31.5 -21.5996zM328 296c23.7998 0 52.7002 -29.2998 56 -71.4004
c0.299805 -3.7998 -2.09961 -7.19922 -5.7002 -8.2998c-3.09961 -1 -7.2002 0 -9.2998 3.7002l-9.5 17c-7.7002 13.7002 -19.2002 21.5996 -31.5 21.5996s-23.7998 -7.89941 -31.5 -21.5996l-9.5 -17c-1.90039 -3.2002 -5.7998 -4.7998 -9.2998 -3.7002
c-3.60059 1.10059 -6 4.60059 -5.7002 8.2998c3.2998 42.1006 32.2002 71.4004 56 71.4004z" />
<glyph glyph-name="surprise" unicode="&#xf5c2;" horiz-adv-x="496"
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM248 168c35.2998 0 64 -28.7002 64 -64s-28.7002 -64 -64 -64
s-64 28.7002 -64 64s28.7002 64 64 64zM200 240c0 -17.7002 -14.2998 -32 -32 -32s-32 14.2998 -32 32s14.2998 32 32 32s32 -14.2998 32 -32zM328 272c17.7002 0 32 -14.2998 32 -32s-14.2998 -32 -32 -32s-32 14.2998 -32 32s14.2998 32 32 32z" />
<glyph glyph-name="tired" unicode="&#xf5c8;" horiz-adv-x="496"
d="M248 440c137 0 248 -111 248 -248s-111 -248 -248 -248s-248 111 -248 248s111 248 248 248zM248 -8c110.3 0 200 89.7002 200 200s-89.7002 200 -200 200s-200 -89.7002 -200 -200s89.7002 -200 200 -200zM377.1 295.8c3.80078 -4.39941 3.90039 -11 0.100586 -15.5
l-33.6006 -40.2998l33.6006 -40.2998c3.7998 -4.5 3.7002 -11 -0.100586 -15.5c-3.5 -4.10059 -9.89941 -5.7002 -15.2998 -2.5l-80 48c-3.59961 2.2002 -5.7998 6.09961 -5.7998 10.2998s2.2002 8.09961 5.7998 10.2998l80 48c5 2.90039 11.5 1.90039 15.2998 -2.5z
M220 240c0 -4.2002 -2.2002 -8.09961 -5.7998 -10.2998l-80 -48c-5.40039 -3.2002 -11.7998 -1.60059 -15.2998 2.5c-3.80078 4.5 -3.90039 11 -0.100586 15.5l33.6006 40.2998l-33.6006 40.2998c-3.7998 4.5 -3.7002 11 0.100586 15.5
c3.7998 4.40039 10.2998 5.5 15.2998 2.5l80 -48c3.59961 -2.2002 5.7998 -6.09961 5.7998 -10.2998zM248 176c45.4004 0 100.9 -38.2998 107.8 -93.2998c1.5 -11.9004 -7 -21.6006 -15.5 -17.9004c-22.7002 9.7002 -56.2998 15.2002 -92.2998 15.2002
s-69.5996 -5.5 -92.2998 -15.2002c-8.60059 -3.7002 -17 6.10059 -15.5 17.9004c6.89941 55 62.3994 93.2998 107.8 93.2998z" />
</font>
</defs></svg>

Before

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 876 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,408 +0,0 @@
/*global mock, converse */
const _ = converse.env._;
const $msg = converse.env.$msg;
const u = converse.env.utils;
const Strophe = converse.env.Strophe;
const sizzle = converse.env.sizzle;
describe("The Controlbox", function () {
it("can be opened by clicking a DOM element with class 'toggle-controlbox'",
mock.initConverse(
['rosterGroupsFetched'], {},
function (done, _converse) {
// This spec will only pass if the controlbox is not currently
// open yet.
let el = document.querySelector("div#controlbox");
expect(_.isElement(el)).toBe(true);
expect(u.isVisible(el)).toBe(false);
spyOn(_converse.controlboxtoggle, 'onClick').and.callThrough();
spyOn(_converse.controlboxtoggle, 'showControlBox').and.callThrough();
spyOn(_converse.api, "trigger").and.callThrough();
// Redelegate so that the spies are now registered as the event handlers (specifically for 'onClick')
_converse.controlboxtoggle.delegateEvents();
document.querySelector('.toggle-controlbox').click();
expect(_converse.controlboxtoggle.onClick).toHaveBeenCalled();
expect(_converse.controlboxtoggle.showControlBox).toHaveBeenCalled();
expect(_converse.api.trigger).toHaveBeenCalledWith('controlBoxOpened', jasmine.any(Object));
el = document.querySelector("div#controlbox");
expect(u.isVisible(el)).toBe(true);
done();
}));
it("can be closed by clicking a DOM element with class 'close-chatbox-button'",
mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
await mock.openControlBox(_converse);
const controlview = _converse.chatboxviews.get('controlbox');
spyOn(controlview, 'close').and.callThrough();
spyOn(_converse.api, "trigger").and.callThrough();
// We need to rebind all events otherwise our spy won't be called
controlview.delegateEvents();
controlview.el.querySelector('.close-chatbox-button').click();
expect(controlview.close).toHaveBeenCalled();
await new Promise(resolve => _converse.api.listen.once('chatBoxClosed', resolve));
expect(_converse.api.trigger).toHaveBeenCalledWith('chatBoxClosed', jasmine.any(Object));
done();
}));
describe("The \"Contacts\" section", function () {
it("can be used to add contact and it checks for case-sensivity",
mock.initConverse(
['rosterGroupsFetched'], {},
async function (done, _converse) {
spyOn(_converse.api, "trigger").and.callThrough();
spyOn(_converse.rosterview, 'update').and.callThrough();
await mock.openControlBox(_converse);
// Adding two contacts one with Capital initials and one with small initials of same JID (Case sensitive check)
_converse.roster.create({
jid: mock.pend_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit',
subscription: 'none',
ask: 'subscribe',
fullname: mock.pend_names[0]
});
_converse.roster.create({
jid: mock.pend_names[0].replace(/ /g,'.') + '@montague.lit',
subscription: 'none',
ask: 'subscribe',
fullname: mock.pend_names[0]
});
await u.waitUntil(() => _.filter(_converse.rosterview.el.querySelectorAll('.roster-group li'), u.isVisible).length, 700);
// Checking that only one entry is created because both JID is same (Case sensitive check)
expect(_.filter(_converse.rosterview.el.querySelectorAll('li'), u.isVisible).length).toBe(1);
expect(_converse.rosterview.update).toHaveBeenCalled();
done();
}));
it("shows the number of unread mentions received",
mock.initConverse(
['rosterGroupsFetched', 'chatBoxesFetched'], {},
async function (done, _converse) {
await mock.waitForRoster(_converse, 'all');
await mock.openControlBox(_converse);
const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
await mock.openChatBoxFor(_converse, sender_jid);
await u.waitUntil(() => _converse.chatboxes.length);
const chatview = _converse.chatboxviews.get(sender_jid);
chatview.model.set({'minimized': true});
expect(_converse.chatboxviews.el.querySelector('.restore-chat .message-count') === null).toBeTruthy();
expect(_converse.rosterview.el.querySelector('.msgs-indicator') === null).toBeTruthy();
let msg = $msg({
from: sender_jid,
to: _converse.connection.jid,
type: 'chat',
id: u.getUniqueId()
}).c('body').t('hello').up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree();
_converse.handleMessageStanza(msg);
await u.waitUntil(() => _converse.rosterview.el.querySelectorAll(".msgs-indicator").length);
spyOn(chatview.model, 'handleUnreadMessage').and.callThrough();
await u.waitUntil(() => _converse.chatboxviews.el.querySelector('.restore-chat .message-count')?.textContent === '1');
expect(_converse.rosterview.el.querySelector('.msgs-indicator').textContent).toBe('1');
msg = $msg({
from: sender_jid,
to: _converse.connection.jid,
type: 'chat',
id: u.getUniqueId()
}).c('body').t('hello again').up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree();
_converse.handleMessageStanza(msg);
await u.waitUntil(() => chatview.model.handleUnreadMessage.calls.count());
await u.waitUntil(() => _converse.chatboxviews.el.querySelector('.restore-chat .message-count')?.textContent === '2');
expect(_converse.rosterview.el.querySelector('.msgs-indicator').textContent).toBe('2');
chatview.model.set({'minimized': false});
expect(_converse.chatboxviews.el.querySelector('.restore-chat .message-count')).toBe(null);
await u.waitUntil(() => _converse.rosterview.el.querySelector('.msgs-indicator') === null);
done();
}));
});
describe("The Status Widget", function () {
it("shows the user's chat status, which is online by default",
mock.initConverse(
['rosterGroupsFetched'], {},
function (done, _converse) {
mock.openControlBox(_converse);
var view = _converse.xmppstatusview;
expect(u.hasClass('online', view.el.querySelector('.xmpp-status span:first-child'))).toBe(true);
expect(view.el.querySelector('.xmpp-status span.online').textContent.trim()).toBe('I am online');
done();
}));
it("can be used to set the current user's chat status",
mock.initConverse(
['rosterGroupsFetched'], {},
async function (done, _converse) {
await mock.openControlBox(_converse);
var cbview = _converse.chatboxviews.get('controlbox');
cbview.el.querySelector('.change-status').click()
var modal = _converse.xmppstatusview.status_modal;
await u.waitUntil(() => u.isVisible(modal.el), 1000);
const view = _converse.xmppstatusview;
modal.el.querySelector('label[for="radio-busy"]').click(); // Change status to "dnd"
modal.el.querySelector('[type="submit"]').click();
const sent_stanzas = _converse.connection.sent_stanzas;
const sent_presence = await u.waitUntil(() => sent_stanzas.filter(s => Strophe.serialize(s).match('presence')).pop());
expect(Strophe.serialize(sent_presence)).toBe(
`<presence xmlns="jabber:client">`+
`<show>dnd</show>`+
`<priority>0</priority>`+
`<c hash="sha-1" node="https://conversejs.org" ver="PxXfr6uz8ClMWIga0OB/MhKNH/M=" xmlns="http://jabber.org/protocol/caps"/>`+
`</presence>`);
const first_child = view.el.querySelector('.xmpp-status span:first-child');
expect(u.hasClass('online', first_child)).toBe(false);
expect(u.hasClass('dnd', first_child)).toBe(true);
expect(view.el.querySelector('.xmpp-status span:first-child').textContent.trim()).toBe('I am busy');
done();
}));
it("can be used to set a custom status message",
mock.initConverse(
['rosterGroupsFetched'], {},
async function (done, _converse) {
await mock.openControlBox(_converse);
const cbview = _converse.chatboxviews.get('controlbox');
cbview.el.querySelector('.change-status').click()
const modal = _converse.xmppstatusview.status_modal;
await u.waitUntil(() => u.isVisible(modal.el), 1000);
const view = _converse.xmppstatusview;
const msg = 'I am happy';
modal.el.querySelector('input[name="status_message"]').value = msg;
modal.el.querySelector('[type="submit"]').click();
const sent_stanzas = _converse.connection.sent_stanzas;
const sent_presence = await u.waitUntil(() => sent_stanzas.filter(s => Strophe.serialize(s).match('presence')).pop());
expect(Strophe.serialize(sent_presence)).toBe(
`<presence xmlns="jabber:client">`+
`<status>I am happy</status>`+
`<priority>0</priority>`+
`<c hash="sha-1" node="https://conversejs.org" ver="PxXfr6uz8ClMWIga0OB/MhKNH/M=" xmlns="http://jabber.org/protocol/caps"/>`+
`</presence>`);
const first_child = view.el.querySelector('.xmpp-status span:first-child');
expect(u.hasClass('online', first_child)).toBe(true);
expect(view.el.querySelector('.xmpp-status span:first-child').textContent.trim()).toBe(msg);
done();
}));
});
});
describe("The 'Add Contact' widget", function () {
it("opens up an add modal when you click on it",
mock.initConverse(
['rosterGroupsFetched'], {},
async function (done, _converse) {
await mock.waitForRoster(_converse, 'all');
await mock.openControlBox(_converse);
const cbview = _converse.chatboxviews.get('controlbox');
cbview.el.querySelector('.add-contact').click()
const modal = _converse.rosterview.add_contact_modal;
await u.waitUntil(() => u.isVisible(modal.el), 1000);
expect(modal.el.querySelector('form.add-xmpp-contact')).not.toBe(null);
const input_jid = modal.el.querySelector('input[name="jid"]');
const input_name = modal.el.querySelector('input[name="name"]');
input_jid.value = 'someone@';
const evt = new Event('input');
input_jid.dispatchEvent(evt);
expect(modal.el.querySelector('.suggestion-box li').textContent).toBe('someone@montague.lit');
input_jid.value = 'someone@montague.lit';
input_name.value = 'Someone';
modal.el.querySelector('button[type="submit"]').click();
const sent_IQs = _converse.connection.IQ_stanzas;
const sent_stanza = await u.waitUntil(() => sent_IQs.filter(iq => iq.querySelector(`iq[type="set"] query[xmlns="${Strophe.NS.ROSTER}"]`)).pop());
expect(Strophe.serialize(sent_stanza)).toEqual(
`<iq id="${sent_stanza.getAttribute('id')}" type="set" xmlns="jabber:client">`+
`<query xmlns="jabber:iq:roster"><item jid="someone@montague.lit" name="Someone"/></query>`+
`</iq>`);
done();
}));
it("can be configured to not provide search suggestions",
mock.initConverse(
['rosterGroupsFetched'], {'autocomplete_add_contact': false},
async function (done, _converse) {
await mock.waitForRoster(_converse, 'all', 0);
mock.openControlBox(_converse);
const cbview = _converse.chatboxviews.get('controlbox');
cbview.el.querySelector('.add-contact').click()
const modal = _converse.rosterview.add_contact_modal;
expect(modal.jid_auto_complete).toBe(undefined);
expect(modal.name_auto_complete).toBe(undefined);
await u.waitUntil(() => u.isVisible(modal.el), 1000);
expect(modal.el.querySelector('form.add-xmpp-contact')).not.toBe(null);
const input_jid = modal.el.querySelector('input[name="jid"]');
input_jid.value = 'someone@montague.lit';
modal.el.querySelector('button[type="submit"]').click();
const IQ_stanzas = _converse.connection.IQ_stanzas;
const sent_stanza = await u.waitUntil(
() => IQ_stanzas.filter(s => sizzle(`iq[type="set"] query[xmlns="${Strophe.NS.ROSTER}"]`, s).length).pop()
);
expect(Strophe.serialize(sent_stanza)).toEqual(
`<iq id="${sent_stanza.getAttribute('id')}" type="set" xmlns="jabber:client">`+
`<query xmlns="jabber:iq:roster"><item jid="someone@montague.lit"/></query>`+
`</iq>`
);
done();
}));
it("integrates with xhr_user_search_url to search for contacts",
mock.initConverse(
['rosterGroupsFetched'],
{ 'xhr_user_search_url': 'http://example.org/?' },
async function (done, _converse) {
await mock.waitForRoster(_converse, 'all', 0);
const xhr = {
'open': function open () {},
'send': function () {
xhr.responseText = JSON.stringify([
{"jid": "marty@mcfly.net", "fullname": "Marty McFly"},
{"jid": "doc@brown.com", "fullname": "Doc Brown"}
]);
xhr.onload();
}
};
const XMLHttpRequestBackup = window.XMLHttpRequest;
window.XMLHttpRequest = jasmine.createSpy('XMLHttpRequest');
XMLHttpRequest.and.callFake(() => xhr);
const cbview = _converse.chatboxviews.get('controlbox');
cbview.el.querySelector('.add-contact').click()
const modal = _converse.rosterview.add_contact_modal;
await u.waitUntil(() => u.isVisible(modal.el), 1000);
// We only have autocomplete for the name input
expect(modal.jid_auto_complete).toBe(undefined);
expect(modal.name_auto_complete instanceof _converse.AutoComplete).toBe(true);
const input_el = modal.el.querySelector('input[name="name"]');
input_el.value = 'marty';
input_el.dispatchEvent(new Event('input'));
await u.waitUntil(() => modal.el.querySelector('.suggestion-box li'), 1000);
expect(modal.el.querySelectorAll('.suggestion-box li').length).toBe(1);
const suggestion = modal.el.querySelector('.suggestion-box li');
expect(suggestion.textContent).toBe('Marty McFly');
// Mock selection
modal.name_auto_complete.select(suggestion);
expect(input_el.value).toBe('Marty McFly');
expect(modal.el.querySelector('input[name="jid"]').value).toBe('marty@mcfly.net');
modal.el.querySelector('button[type="submit"]').click();
const sent_IQs = _converse.connection.IQ_stanzas;
const sent_stanza = await u.waitUntil(() => sent_IQs.filter(iq => iq.querySelector(`iq[type="set"] query[xmlns="${Strophe.NS.ROSTER}"]`)).pop());
expect(Strophe.serialize(sent_stanza)).toEqual(
`<iq id="${sent_stanza.getAttribute('id')}" type="set" xmlns="jabber:client">`+
`<query xmlns="jabber:iq:roster"><item jid="marty@mcfly.net" name="Marty McFly"/></query>`+
`</iq>`);
window.XMLHttpRequest = XMLHttpRequestBackup;
done();
}));
it("can be configured to not provide search suggestions for XHR search results",
mock.initConverse(
['rosterGroupsFetched'],
{ 'autocomplete_add_contact': false,
'xhr_user_search_url': 'http://example.org/?' },
async function (done, _converse) {
await mock.waitForRoster(_converse, 'all');
await mock.openControlBox(_converse);
var modal;
const xhr = {
'open': function open () {},
'send': function () {
const value = modal.el.querySelector('input[name="name"]').value;
if (value === 'existing') {
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
xhr.responseText = JSON.stringify([{"jid": contact_jid, "fullname": mock.cur_names[0]}]);
} else if (value === 'romeo') {
xhr.responseText = JSON.stringify([{"jid": "romeo@montague.lit", "fullname": "Romeo Montague"}]);
} else if (value === 'ambiguous') {
xhr.responseText = JSON.stringify([
{"jid": "marty@mcfly.net", "fullname": "Marty McFly"},
{"jid": "doc@brown.com", "fullname": "Doc Brown"}
]);
} else if (value === 'insufficient') {
xhr.responseText = JSON.stringify([]);
} else {
xhr.responseText = JSON.stringify([{"jid": "marty@mcfly.net", "fullname": "Marty McFly"}]);
}
xhr.onload();
}
};
const XMLHttpRequestBackup = window.XMLHttpRequest;
window.XMLHttpRequest = jasmine.createSpy('XMLHttpRequest');
XMLHttpRequest.and.callFake(() => xhr);
const cbview = _converse.chatboxviews.get('controlbox');
cbview.el.querySelector('.add-contact').click()
modal = _converse.rosterview.add_contact_modal;
await u.waitUntil(() => u.isVisible(modal.el), 1000);
expect(modal.jid_auto_complete).toBe(undefined);
expect(modal.name_auto_complete).toBe(undefined);
const input_el = modal.el.querySelector('input[name="name"]');
input_el.value = 'ambiguous';
modal.el.querySelector('button[type="submit"]').click();
let feedback_el = modal.el.querySelector('.invalid-feedback');
expect(feedback_el.textContent).toBe('Sorry, could not find a contact with that name');
feedback_el.textContent = '';
input_el.value = 'insufficient';
modal.el.querySelector('button[type="submit"]').click();
feedback_el = modal.el.querySelector('.invalid-feedback');
expect(feedback_el.textContent).toBe('Sorry, could not find a contact with that name');
feedback_el.textContent = '';
input_el.value = 'existing';
modal.el.querySelector('button[type="submit"]').click();
feedback_el = modal.el.querySelector('.invalid-feedback');
expect(feedback_el.textContent).toBe('This contact has already been added');
input_el.value = 'Marty McFly';
modal.el.querySelector('button[type="submit"]').click();
const sent_IQs = _converse.connection.IQ_stanzas;
const sent_stanza = await u.waitUntil(() => sent_IQs.filter(iq => iq.querySelector(`iq[type="set"] query[xmlns="${Strophe.NS.ROSTER}"]`)).pop());
expect(Strophe.serialize(sent_stanza)).toEqual(
`<iq id="${sent_stanza.getAttribute('id')}" type="set" xmlns="jabber:client">`+
`<query xmlns="jabber:iq:roster"><item jid="marty@mcfly.net" name="Marty McFly"/></query>`+
`</iq>`);
window.XMLHttpRequest = XMLHttpRequestBackup;
done();
}));
});

View File

@ -1,624 +0,0 @@
/*global mock, converse */
const { Promise, $msg, $pres, Strophe, sizzle } = converse.env;
const u = converse.env.utils;
describe("A Chat Message", function () {
it("can be sent as a correction by using the up arrow",
mock.initConverse(
['rosterGroupsFetched', 'chatBoxesFetched'], {},
async function (done, _converse) {
await mock.waitForRoster(_converse, 'current', 1);
await mock.openControlBox(_converse);
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
await mock.openChatBoxFor(_converse, contact_jid)
const view = _converse.api.chatviews.get(contact_jid);
const textarea = view.el.querySelector('textarea.chat-textarea');
expect(textarea.value).toBe('');
view.onKeyDown({
target: textarea,
keyCode: 38 // Up arrow
});
expect(textarea.value).toBe('');
textarea.value = 'But soft, what light through yonder airlock breaks?';
view.onKeyDown({
target: textarea,
preventDefault: function preventDefault () {},
keyCode: 13 // Enter
});
await new Promise(resolve => view.model.messages.once('rendered', resolve));
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
expect(view.el.querySelector('.chat-msg__text').textContent)
.toBe('But soft, what light through yonder airlock breaks?');
const first_msg = view.model.messages.findWhere({'message': 'But soft, what light through yonder airlock breaks?'});
expect(textarea.value).toBe('');
view.onKeyDown({
target: textarea,
keyCode: 38 // Up arrow
});
expect(textarea.value).toBe('But soft, what light through yonder airlock breaks?');
expect(view.model.messages.at(0).get('correcting')).toBe(true);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
await u.waitUntil(() => u.hasClass('correcting', view.el.querySelector('.chat-msg')), 500);
spyOn(_converse.connection, 'send');
textarea.value = 'But soft, what light through yonder window breaks?';
view.onKeyDown({
target: textarea,
preventDefault: function preventDefault () {},
keyCode: 13 // Enter
});
expect(_converse.connection.send).toHaveBeenCalled();
await new Promise(resolve => view.model.messages.once('rendered', resolve));
const msg = _converse.connection.send.calls.all()[0].args[0];
expect(msg.toLocaleString())
.toBe(`<message from="romeo@montague.lit/orchard" id="${msg.nodeTree.getAttribute("id")}" `+
`to="mercutio@montague.lit" type="chat" `+
`xmlns="jabber:client">`+
`<body>But soft, what light through yonder window breaks?</body>`+
`<active xmlns="http://jabber.org/protocol/chatstates"/>`+
`<request xmlns="urn:xmpp:receipts"/>`+
`<replace id="${first_msg.get("msgid")}" xmlns="urn:xmpp:message-correct:0"/>`+
`<origin-id id="${msg.nodeTree.querySelector('origin-id').getAttribute("id")}" xmlns="urn:xmpp:sid:0"/>`+
`</message>`);
expect(view.model.messages.models.length).toBe(1);
const corrected_message = view.model.messages.at(0);
expect(corrected_message.get('msgid')).toBe(first_msg.get('msgid'));
expect(corrected_message.get('correcting')).toBe(false);
const older_versions = corrected_message.get('older_versions');
const keys = Object.keys(older_versions);
expect(keys.length).toBe(1);
expect(older_versions[keys[0]]).toBe('But soft, what light through yonder airlock breaks?');
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
await u.waitUntil(() => (u.hasClass('correcting', view.el.querySelector('.chat-msg')) === false), 500);
// Test that pressing the down arrow cancels message correction
expect(textarea.value).toBe('');
view.onKeyDown({
target: textarea,
keyCode: 38 // Up arrow
});
expect(textarea.value).toBe('But soft, what light through yonder window breaks?');
expect(view.model.messages.at(0).get('correcting')).toBe(true);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
await u.waitUntil(() => u.hasClass('correcting', view.el.querySelector('.chat-msg')), 500);
expect(textarea.value).toBe('But soft, what light through yonder window breaks?');
view.onKeyDown({
target: textarea,
keyCode: 40 // Down arrow
});
expect(textarea.value).toBe('');
expect(view.model.messages.at(0).get('correcting')).toBe(false);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
await u.waitUntil(() => (u.hasClass('correcting', view.el.querySelector('.chat-msg')) === false), 500);
textarea.value = 'It is the east, and Juliet is the one.';
view.onKeyDown({
target: textarea,
preventDefault: function preventDefault () {},
keyCode: 13 // Enter
});
await new Promise(resolve => view.model.messages.once('rendered', resolve));
expect(view.el.querySelectorAll('.chat-msg').length).toBe(2);
textarea.value = 'Arise, fair sun, and kill the envious moon';
view.onKeyDown({
target: textarea,
preventDefault: function preventDefault () {},
keyCode: 13 // Enter
});
await new Promise(resolve => view.model.messages.once('rendered', resolve));
expect(view.el.querySelectorAll('.chat-msg').length).toBe(3);
view.onKeyDown({
target: textarea,
keyCode: 38 // Up arrow
});
expect(textarea.value).toBe('Arise, fair sun, and kill the envious moon');
expect(view.model.messages.at(0).get('correcting')).toBeFalsy();
expect(view.model.messages.at(1).get('correcting')).toBeFalsy();
expect(view.model.messages.at(2).get('correcting')).toBe(true);
await u.waitUntil(() => u.hasClass('correcting', sizzle('.chat-msg:last', view.el).pop()), 500);
textarea.selectionEnd = 0; // Happens by pressing up,
// but for some reason not in tests, so we set it manually.
view.onKeyDown({
target: textarea,
keyCode: 38 // Up arrow
});
expect(textarea.value).toBe('It is the east, and Juliet is the one.');
expect(view.model.messages.at(0).get('correcting')).toBeFalsy();
expect(view.model.messages.at(1).get('correcting')).toBe(true);
expect(view.model.messages.at(2).get('correcting')).toBeFalsy();
await u.waitUntil(() => u.hasClass('correcting', sizzle('.chat-msg', view.el)[1]), 500);
textarea.value = 'It is the east, and Juliet is the sun.';
view.onKeyDown({
target: textarea,
preventDefault: function preventDefault () {},
keyCode: 13 // Enter
});
await new Promise(resolve => view.model.messages.once('rendered', resolve));
await u.waitUntil(() => textarea.value === '');
const messages = view.el.querySelectorAll('.chat-msg');
expect(messages.length).toBe(3);
expect(messages[0].querySelector('.chat-msg__text').textContent)
.toBe('But soft, what light through yonder window breaks?');
expect(messages[1].querySelector('.chat-msg__text').textContent)
.toBe('It is the east, and Juliet is the sun.');
expect(messages[2].querySelector('.chat-msg__text').textContent)
.toBe('Arise, fair sun, and kill the envious moon');
expect(view.model.messages.at(0).get('correcting')).toBeFalsy();
expect(view.model.messages.at(1).get('correcting')).toBeFalsy();
expect(view.model.messages.at(2).get('correcting')).toBeFalsy();
done();
}));
it("can be sent as a correction by clicking the pencil icon",
mock.initConverse(
['rosterGroupsFetched', 'chatBoxesFetched'], {},
async function (done, _converse) {
await mock.waitForRoster(_converse, 'current', 1);
await mock.openControlBox(_converse);
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
await mock.openChatBoxFor(_converse, contact_jid);
const view = _converse.api.chatviews.get(contact_jid);
const textarea = view.el.querySelector('textarea.chat-textarea');
textarea.value = 'But soft, what light through yonder airlock breaks?';
view.onKeyDown({
target: textarea,
preventDefault: function preventDefault () {},
keyCode: 13 // Enter
});
await new Promise(resolve => view.model.messages.once('rendered', resolve));
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
expect(view.el.querySelector('.chat-msg__text').textContent)
.toBe('But soft, what light through yonder airlock breaks?');
expect(textarea.value).toBe('');
const first_msg = view.model.messages.findWhere({'message': 'But soft, what light through yonder airlock breaks?'});
await u.waitUntil(() => view.el.querySelectorAll('.chat-msg .chat-msg__action').length === 2);
let action = view.el.querySelector('.chat-msg .chat-msg__action');
expect(action.textContent.trim()).toBe('Edit');
action.style.opacity = 1;
action.click();
expect(textarea.value).toBe('But soft, what light through yonder airlock breaks?');
expect(view.model.messages.at(0).get('correcting')).toBe(true);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
await u.waitUntil(() => u.hasClass('correcting', view.el.querySelector('.chat-msg')));
spyOn(_converse.connection, 'send');
textarea.value = 'But soft, what light through yonder window breaks?';
view.onKeyDown({
target: textarea,
preventDefault: function preventDefault () {},
keyCode: 13 // Enter
});
expect(_converse.connection.send).toHaveBeenCalled();
const msg = _converse.connection.send.calls.all()[0].args[0];
expect(msg.toLocaleString())
.toBe(`<message from="romeo@montague.lit/orchard" id="${msg.nodeTree.getAttribute("id")}" `+
`to="mercutio@montague.lit" type="chat" `+
`xmlns="jabber:client">`+
`<body>But soft, what light through yonder window breaks?</body>`+
`<active xmlns="http://jabber.org/protocol/chatstates"/>`+
`<request xmlns="urn:xmpp:receipts"/>`+
`<replace id="${first_msg.get("msgid")}" xmlns="urn:xmpp:message-correct:0"/>`+
`<origin-id id="${msg.nodeTree.querySelector('origin-id').getAttribute("id")}" xmlns="urn:xmpp:sid:0"/>`+
`</message>`);
expect(view.model.messages.models.length).toBe(1);
const corrected_message = view.model.messages.at(0);
expect(corrected_message.get('msgid')).toBe(first_msg.get('msgid'));
expect(corrected_message.get('correcting')).toBe(false);
const older_versions = corrected_message.get('older_versions');
const keys = Object.keys(older_versions);
expect(keys.length).toBe(1);
expect(older_versions[keys[0]]).toBe('But soft, what light through yonder airlock breaks?');
await u.waitUntil(() => u.hasClass('correcting', view.el.querySelector('.chat-msg')) === false);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
// Test that clicking the pencil icon a second time cancels editing.
action = view.el.querySelector('.chat-msg .chat-msg__action');
action.style.opacity = 1;
action.click();
expect(textarea.value).toBe('But soft, what light through yonder window breaks?');
expect(view.model.messages.at(0).get('correcting')).toBe(true);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
await u.waitUntil(() => u.hasClass('correcting', view.el.querySelector('.chat-msg')) === true);
action = view.el.querySelector('.chat-msg .chat-msg__action');
action.style.opacity = 1;
action.click();
expect(textarea.value).toBe('');
expect(view.model.messages.at(0).get('correcting')).toBe(false);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
await u.waitUntil(() => (u.hasClass('correcting', view.el.querySelector('.chat-msg')) === false), 500);
// Test that messages from other users don't have the pencil icon
_converse.handleMessageStanza(
$msg({
'from': contact_jid,
'to': _converse.connection.jid,
'type': 'chat',
'id': u.getUniqueId()
}).c('body').t('Hello').up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree()
);
await new Promise(resolve => view.model.messages.once('rendered', resolve));
expect(view.el.querySelectorAll('.chat-msg .chat-msg__action').length).toBe(2);
// Test confirmation dialog
spyOn(window, 'confirm').and.returnValue(true);
textarea.value = 'But soft, what light through yonder airlock breaks?';
action = view.el.querySelector('.chat-msg .chat-msg__action');
action.style.opacity = 1;
action.click();
expect(window.confirm).toHaveBeenCalledWith(
'You have an unsent message which will be lost if you continue. Are you sure?');
expect(view.model.messages.at(0).get('correcting')).toBe(true);
expect(textarea.value).toBe('But soft, what light through yonder window breaks?');
textarea.value = 'But soft, what light through yonder airlock breaks?'
action.click();
expect(view.model.messages.at(0).get('correcting')).toBe(false);
expect(window.confirm.calls.count()).toBe(2);
expect(window.confirm.calls.argsFor(0)).toEqual(
['You have an unsent message which will be lost if you continue. Are you sure?']);
expect(window.confirm.calls.argsFor(1)).toEqual(
['You have an unsent message which will be lost if you continue. Are you sure?']);
done();
}));
describe("when received from someone else", function () {
it("can be replaced with a correction",
mock.initConverse(
['rosterGroupsFetched', 'chatBoxesFetched'], {},
async function (done, _converse) {
await mock.waitForRoster(_converse, 'current', 1);
await mock.openControlBox(_converse);
const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
const msg_id = u.getUniqueId();
const view = await mock.openChatBoxFor(_converse, sender_jid);
_converse.handleMessageStanza($msg({
'from': sender_jid,
'to': _converse.connection.jid,
'type': 'chat',
'id': msg_id,
}).c('body').t('But soft, what light through yonder airlock breaks?').tree());
await new Promise(resolve => view.model.messages.once('rendered', resolve));
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
expect(view.el.querySelector('.chat-msg__text').textContent)
.toBe('But soft, what light through yonder airlock breaks?');
_converse.handleMessageStanza($msg({
'from': sender_jid,
'to': _converse.connection.jid,
'type': 'chat',
'id': u.getUniqueId(),
}).c('body').t('But soft, what light through yonder chimney breaks?').up()
.c('replace', {'id': msg_id, 'xmlns': 'urn:xmpp:message-correct:0'}).tree());
await new Promise(resolve => view.model.messages.once('rendered', resolve));
expect(view.el.querySelector('.chat-msg__text').textContent)
.toBe('But soft, what light through yonder chimney breaks?');
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
expect(view.el.querySelectorAll('.chat-msg__content .fa-edit').length).toBe(1);
expect(view.model.messages.models.length).toBe(1);
_converse.handleMessageStanza($msg({
'from': sender_jid,
'to': _converse.connection.jid,
'type': 'chat',
'id': u.getUniqueId(),
}).c('body').t('But soft, what light through yonder window breaks?').up()
.c('replace', {'id': msg_id, 'xmlns': 'urn:xmpp:message-correct:0'}).tree());
await new Promise(resolve => view.model.messages.once('rendered', resolve));
expect(view.el.querySelector('.chat-msg__text').textContent)
.toBe('But soft, what light through yonder window breaks?');
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
expect(view.el.querySelectorAll('.chat-msg__content .fa-edit').length).toBe(1);
view.el.querySelector('.chat-msg__content .fa-edit').click();
const modal = await u.waitUntil(() => view.el.querySelector('converse-chat-message').message_versions_modal);
await u.waitUntil(() => u.isVisible(modal.el), 1000);
const older_msgs = modal.el.querySelectorAll('.older-msg');
expect(older_msgs.length).toBe(2);
expect(older_msgs[0].childNodes[0].nodeName).toBe('TIME');
expect(older_msgs[0].childNodes[2].textContent).toBe('But soft, what light through yonder airlock breaks?');
expect(view.model.messages.models.length).toBe(1);
done();
}));
});
});
describe("A Groupchat Message", function () {
it("can be replaced with a correction",
mock.initConverse(
['rosterGroupsFetched'], {},
async function (done, _converse) {
const muc_jid = 'lounge@montague.lit';
await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
const view = _converse.api.chatviews.get(muc_jid);
const stanza = $pres({
to: 'romeo@montague.lit/_converse.js-29092160',
from: 'coven@chat.shakespeare.lit/newguy'
})
.c('x', {xmlns: Strophe.NS.MUC_USER})
.c('item', {
'affiliation': 'none',
'jid': 'newguy@montague.lit/_converse.js-290929789',
'role': 'participant'
}).tree();
_converse.connection._dataRecv(mock.createRequest(stanza));
const msg_id = u.getUniqueId();
await view.model.handleMessageStanza($msg({
'from': 'lounge@montague.lit/newguy',
'to': _converse.connection.jid,
'type': 'groupchat',
'id': msg_id,
}).c('body').t('But soft, what light through yonder airlock breaks?').tree());
await u.waitUntil(() => view.el.querySelectorAll('.chat-msg').length);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
expect(view.el.querySelector('.chat-msg__text').textContent)
.toBe('But soft, what light through yonder airlock breaks?');
await view.model.handleMessageStanza($msg({
'from': 'lounge@montague.lit/newguy',
'to': _converse.connection.jid,
'type': 'groupchat',
'id': u.getUniqueId(),
}).c('body').t('But soft, what light through yonder chimney breaks?').up()
.c('replace', {'id': msg_id, 'xmlns': 'urn:xmpp:message-correct:0'}).tree());
await u.waitUntil(() => view.el.querySelector('.chat-msg__text').textContent ===
'But soft, what light through yonder chimney breaks?', 500);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
await u.waitUntil(() => view.el.querySelector('.chat-msg__content .fa-edit'));
await view.model.handleMessageStanza($msg({
'from': 'lounge@montague.lit/newguy',
'to': _converse.connection.jid,
'type': 'groupchat',
'id': u.getUniqueId(),
}).c('body').t('But soft, what light through yonder window breaks?').up()
.c('replace', {'id': msg_id, 'xmlns': 'urn:xmpp:message-correct:0'}).tree());
await u.waitUntil(() => view.el.querySelector('.chat-msg__text').textContent ===
'But soft, what light through yonder window breaks?', 500);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
expect(view.el.querySelectorAll('.chat-msg__content .fa-edit').length).toBe(1);
const edit = await u.waitUntil(() => view.el.querySelector('.chat-msg__content .fa-edit'));
edit.click();
const modal = await u.waitUntil(() => view.el.querySelector('converse-chat-message').message_versions_modal);
await u.waitUntil(() => u.isVisible(modal.el), 1000);
const older_msgs = modal.el.querySelectorAll('.older-msg');
expect(older_msgs.length).toBe(2);
expect(older_msgs[0].childNodes[2].textContent).toBe('But soft, what light through yonder airlock breaks?');
expect(older_msgs[0].childNodes[0].nodeName).toBe('TIME');
expect(older_msgs[1].childNodes[0].nodeName).toBe('TIME');
expect(older_msgs[1].childNodes[2].textContent).toBe('But soft, what light through yonder chimney breaks?');
done();
}));
it("keeps the same position in history after a correction",
mock.initConverse(
['rosterGroupsFetched'], {},
async function (done, _converse) {
const muc_jid = 'lounge@montague.lit';
await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
const view = _converse.api.chatviews.get(muc_jid);
const stanza = $pres({
to: 'romeo@montague.lit/_converse.js-29092160',
from: 'coven@chat.shakespeare.lit/newguy'
})
.c('x', {xmlns: Strophe.NS.MUC_USER})
.c('item', {
'affiliation': 'none',
'jid': 'newguy@montague.lit/_converse.js-290929789',
'role': 'participant'
}).tree();
_converse.connection._dataRecv(mock.createRequest(stanza));
const msg_id = u.getUniqueId();
// Receiving the first message
await view.model.handleMessageStanza($msg({
'from': 'lounge@montague.lit/newguy',
'to': _converse.connection.jid,
'type': 'groupchat',
'id': msg_id,
}).c('body').t('But soft, what light through yonder airlock breaks?').tree());
// Receiving own message to check order against
await view.model.handleMessageStanza($msg({
'from': 'lounge@montague.lit/romeo',
'to': _converse.connection.jid,
'type': 'groupchat',
'id': msg_id,
}).c('body').t('But soft, what light through yonder airlock breaks?').tree());
await u.waitUntil(() => view.el.querySelectorAll('.chat-msg').length === 2);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(2);
expect(view.el.querySelectorAll('.chat-msg__text')[0].textContent)
.toBe('But soft, what light through yonder airlock breaks?');
expect(view.el.querySelectorAll('.chat-msg__text')[1].textContent)
.toBe('But soft, what light through yonder airlock breaks?');
// First message correction
await view.model.handleMessageStanza($msg({
'from': 'lounge@montague.lit/newguy',
'to': _converse.connection.jid,
'type': 'groupchat',
'id': u.getUniqueId(),
}).c('body').t('But soft, what light through yonder chimney breaks?').up()
.c('replace', {'id': msg_id, 'xmlns': 'urn:xmpp:message-correct:0'}).tree());
await u.waitUntil(() => view.el.querySelector('.chat-msg__text').textContent ===
'But soft, what light through yonder chimney breaks?', 500);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(2);
await u.waitUntil(() => view.el.querySelector('.chat-msg__content .fa-edit'));
// Second message correction
await view.model.handleMessageStanza($msg({
'from': 'lounge@montague.lit/newguy',
'to': _converse.connection.jid,
'type': 'groupchat',
'id': u.getUniqueId(),
}).c('body').t('But soft, what light through yonder window breaks?').up()
.c('replace', {'id': msg_id, 'xmlns': 'urn:xmpp:message-correct:0'}).tree());
// Second own message
await view.model.handleMessageStanza($msg({
'from': 'lounge@montague.lit/romeo',
'to': _converse.connection.jid,
'type': 'groupchat',
'id': u.getUniqueId(),
}).c('body').t('But soft, what light through yonder window breaks?').tree());
await u.waitUntil(() => view.el.querySelectorAll('.chat-msg__text')[0].textContent ===
'But soft, what light through yonder window breaks?', 500);
await u.waitUntil(() => view.el.querySelectorAll('.chat-msg__text').length === 3);
await u.waitUntil(() => view.el.querySelectorAll('.chat-msg__text')[2].textContent ===
'But soft, what light through yonder window breaks?', 500);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(3);
expect(view.el.querySelectorAll('.chat-msg__content .fa-edit').length).toBe(1);
const edit = await u.waitUntil(() => view.el.querySelector('.chat-msg__content .fa-edit'));
edit.click();
const modal = await u.waitUntil(() => view.el.querySelectorAll('converse-chat-message')[0].message_versions_modal);
await u.waitUntil(() => u.isVisible(modal.el), 1000);
const older_msgs = modal.el.querySelectorAll('.older-msg');
expect(older_msgs.length).toBe(2);
expect(older_msgs[0].childNodes[2].textContent).toBe('But soft, what light through yonder airlock breaks?');
expect(older_msgs[0].childNodes[0].nodeName).toBe('TIME');
expect(older_msgs[1].childNodes[0].nodeName).toBe('TIME');
expect(older_msgs[1].childNodes[2].textContent).toBe('But soft, what light through yonder chimney breaks?');
done();
}));
it("can be sent as a correction by using the up arrow",
mock.initConverse(
['rosterGroupsFetched'], {},
async function (done, _converse) {
const muc_jid = 'lounge@montague.lit';
await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
const view = _converse.api.chatviews.get(muc_jid);
const textarea = view.el.querySelector('textarea.chat-textarea');
expect(textarea.value).toBe('');
view.onKeyDown({
target: textarea,
keyCode: 38 // Up arrow
});
expect(textarea.value).toBe('');
textarea.value = 'But soft, what light through yonder airlock breaks?';
view.onKeyDown({
target: textarea,
preventDefault: function preventDefault () {},
keyCode: 13 // Enter
});
await u.waitUntil(() => view.el.querySelectorAll('.chat-msg').length === 1);
expect(view.el.querySelector('.chat-msg__text').textContent)
.toBe('But soft, what light through yonder airlock breaks?');
const first_msg = view.model.messages.findWhere({'message': 'But soft, what light through yonder airlock breaks?'});
expect(textarea.value).toBe('');
view.onKeyDown({
target: textarea,
keyCode: 38 // Up arrow
});
expect(textarea.value).toBe('But soft, what light through yonder airlock breaks?');
expect(view.model.messages.at(0).get('correcting')).toBe(true);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
await u.waitUntil(() => u.hasClass('correcting', view.el.querySelector('.chat-msg')));
spyOn(_converse.connection, 'send');
textarea.value = 'But soft, what light through yonder window breaks?';
view.onKeyDown({
target: textarea,
preventDefault: function preventDefault () {},
keyCode: 13 // Enter
});
expect(_converse.connection.send).toHaveBeenCalled();
await new Promise(resolve => view.model.messages.once('rendered', resolve));
const msg = _converse.connection.send.calls.all()[0].args[0];
expect(msg.toLocaleString())
.toBe(`<message from="romeo@montague.lit/orchard" id="${msg.nodeTree.getAttribute("id")}" `+
`to="lounge@montague.lit" type="groupchat" `+
`xmlns="jabber:client">`+
`<body>But soft, what light through yonder window breaks?</body>`+
`<active xmlns="http://jabber.org/protocol/chatstates"/>`+
`<replace id="${first_msg.get("msgid")}" xmlns="urn:xmpp:message-correct:0"/>`+
`<origin-id id="${msg.nodeTree.querySelector('origin-id').getAttribute("id")}" xmlns="urn:xmpp:sid:0"/>`+
`</message>`);
expect(view.model.messages.models.length).toBe(1);
const corrected_message = view.model.messages.at(0);
expect(corrected_message.get('msgid')).toBe(first_msg.get('msgid'));
expect(corrected_message.get('correcting')).toBe(false);
const older_versions = corrected_message.get('older_versions');
const keys = Object.keys(older_versions);
expect(keys.length).toBe(1);
expect(older_versions[keys[0]]).toBe('But soft, what light through yonder airlock breaks?');
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
expect(u.hasClass('correcting', view.el.querySelector('.chat-msg'))).toBe(false);
// Check that messages from other users are skipped
await view.model.handleMessageStanza($msg({
'from': muc_jid+'/someone-else',
'id': u.getUniqueId(),
'to': 'romeo@montague.lit',
'type': 'groupchat'
}).c('body').t('Hello world').tree());
await new Promise(resolve => view.model.messages.once('rendered', resolve));
expect(view.el.querySelectorAll('.chat-msg').length).toBe(2);
// Test that pressing the down arrow cancels message correction
expect(textarea.value).toBe('');
view.onKeyDown({
target: textarea,
keyCode: 38 // Up arrow
});
expect(textarea.value).toBe('But soft, what light through yonder window breaks?');
expect(view.model.messages.at(0).get('correcting')).toBe(true);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(2);
await u.waitUntil(() => u.hasClass('correcting', view.el.querySelector('.chat-msg')), 500);
expect(textarea.value).toBe('But soft, what light through yonder window breaks?');
view.onKeyDown({
target: textarea,
keyCode: 40 // Down arrow
});
expect(textarea.value).toBe('');
expect(view.model.messages.at(0).get('correcting')).toBe(false);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(2);
await u.waitUntil(() => !u.hasClass('correcting', view.el.querySelector('.chat-msg')), 500);
done();
}));
});

View File

@ -1,431 +0,0 @@
/*global mock, converse */
const { Promise, $msg, $pres, sizzle } = converse.env;
const u = converse.env.utils;
const original_timeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
describe("Emojis", function () {
describe("The emoji picker", function () {
beforeEach(() => (jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000));
afterEach(() => (jasmine.DEFAULT_TIMEOUT_INTERVAL = original_timeout));
it("can be opened by clicking a button in the chat toolbar",
mock.initConverse(
['rosterGroupsFetched', 'chatBoxesFetched'], {},
async function (done, _converse) {
const contact_jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@montague.lit';
await mock.waitForRoster(_converse, 'current');
await mock.openControlBox(_converse);
await mock.openChatBoxFor(_converse, contact_jid);
const view = _converse.chatboxviews.get(contact_jid);
const toolbar = await u.waitUntil(() => view.el.querySelector('converse-chat-toolbar'));
toolbar.querySelector('.toggle-emojis').click();
await u.waitUntil(() => u.isVisible(view.el.querySelector('.emoji-picker__lists')), 1000);
const item = view.el.querySelector('.emoji-picker li.insert-emoji a');
item.click()
expect(view.el.querySelector('textarea.chat-textarea').value).toBe(':smiley: ');
toolbar.querySelector('.toggle-emojis').click(); // Close the panel again
done();
}));
it("is opened to autocomplete emojis in the textarea",
mock.initConverse(
['rosterGroupsFetched', 'chatBoxesFetched'], {},
async function (done, _converse) {
const muc_jid = 'lounge@montague.lit';
await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
const view = _converse.chatboxviews.get(muc_jid);
await u.waitUntil(() => view.el.querySelector('converse-emoji-dropdown'));
const textarea = view.el.querySelector('textarea.chat-textarea');
textarea.value = ':gri';
// Press tab
const tab_event = {
'target': textarea,
'preventDefault': function preventDefault () {},
'stopPropagation': function stopPropagation () {},
'keyCode': 9,
'key': 'Tab'
}
view.onKeyDown(tab_event);
await u.waitUntil(() => view.el.querySelector('converse-emoji-picker .emoji-search').value === ':gri');
await u.waitUntil(() => sizzle('.emojis-lists__container--search .insert-emoji', view.el).length === 3, 1000);
let visible_emojis = sizzle('.emojis-lists__container--search .insert-emoji', view.el);
expect(visible_emojis[0].getAttribute('data-emoji')).toBe(':grimacing:');
expect(visible_emojis[1].getAttribute('data-emoji')).toBe(':grin:');
expect(visible_emojis[2].getAttribute('data-emoji')).toBe(':grinning:');
const picker = view.el.querySelector('converse-emoji-picker');
const input = picker.querySelector('.emoji-search');
// Test that TAB autocompletes the to first match
input.dispatchEvent(new KeyboardEvent('keydown', tab_event));
await u.waitUntil(() => sizzle(".emojis-lists__container--search .insert-emoji:not('.hidden')", picker).length === 1, 1000);
visible_emojis = sizzle(".emojis-lists__container--search .insert-emoji:not('.hidden')", picker);
expect(visible_emojis[0].getAttribute('data-emoji')).toBe(':grimacing:');
expect(input.value).toBe(':grimacing:');
// Check that ENTER now inserts the match
const enter_event = Object.assign({}, tab_event, {'keyCode': 13, 'key': 'Enter', 'target': input});
input.dispatchEvent(new KeyboardEvent('keydown', enter_event));
await u.waitUntil(() => input.value === '');
await u.waitUntil(() => textarea.value === ':grimacing: ');
// Test that username starting with : doesn't cause issues
const presence = $pres({
'from': `${muc_jid}/:username`,
'id': '27C55F89-1C6A-459A-9EB5-77690145D624',
'to': _converse.jid
})
.c('x', { 'xmlns': 'http://jabber.org/protocol/muc#user'})
.c('item', {
'jid': 'some1@montague.lit',
'affiliation': 'member',
'role': 'participant'
});
_converse.connection._dataRecv(mock.createRequest(presence));
textarea.value = ':use';
view.onKeyDown(tab_event);
await u.waitUntil(() => u.isVisible(view.el.querySelector('.emoji-picker__lists')));
await u.waitUntil(() => input.value === ':use');
visible_emojis = sizzle('.insert-emoji:not(.hidden)', picker);
expect(visible_emojis.length).toBe(0);
done();
}));
it("is focused to autocomplete emojis in the textarea",
mock.initConverse(
['rosterGroupsFetched', 'chatBoxesFetched'], {},
async function (done, _converse) {
const muc_jid = 'lounge@montague.lit';
await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
const view = _converse.chatboxviews.get(muc_jid);
await u.waitUntil(() => view.el.querySelector('converse-emoji-dropdown'));
const textarea = view.el.querySelector('textarea.chat-textarea');
textarea.value = ':';
// Press tab
const tab_event = {
'target': textarea,
'preventDefault': function preventDefault () {},
'stopPropagation': function stopPropagation () {},
'keyCode': 9,
'key': 'Tab'
}
view.onKeyDown(tab_event);
await u.waitUntil(() => u.isVisible(view.el.querySelector('.emoji-picker__lists')));
const picker = view.el.querySelector('converse-emoji-picker');
const input = picker.querySelector('.emoji-search');
expect(input.value).toBe(':');
input.value = ':gri';
const event = {
'target': input,
'preventDefault': function preventDefault () {},
'stopPropagation': function stopPropagation () {}
};
input.dispatchEvent(new KeyboardEvent('keydown', event));
await u.waitUntil(() => sizzle('.emojis-lists__container--search .insert-emoji', view.el).length === 3, 1000);
let emoji = sizzle('.emojis-lists__container--search .insert-emoji:not(.hidden) a', view.el).pop();
emoji.click();
await u.waitUntil(() => textarea.value === ':grinning: ');
textarea.value = ':grinning: :';
view.onKeyDown(tab_event);
await u.waitUntil(() => input.value === ':');
input.value = ':grimacing';
input.dispatchEvent(new KeyboardEvent('keydown', event));
await u.waitUntil(() => sizzle('.emojis-lists__container--search .insert-emoji', view.el).length === 1, 1000);
emoji = sizzle('.emojis-lists__container--search .insert-emoji:not(.hidden) a', view.el).pop();
emoji.click();
await u.waitUntil(() => textarea.value === ':grinning: :grimacing: ');
done();
}));
it("properly inserts emojis into the chat textarea",
mock.initConverse(
['rosterGroupsFetched', 'chatBoxesFetched'], {},
async function (done, _converse) {
const muc_jid = 'lounge@montague.lit';
await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
const view = _converse.chatboxviews.get(muc_jid);
await u.waitUntil(() => view.el.querySelector('converse-emoji-dropdown'));
const textarea = view.el.querySelector('textarea.chat-textarea');
textarea.value = ':gri';
// Press tab
const tab_event = {
'target': textarea,
'preventDefault': function preventDefault () {},
'stopPropagation': function stopPropagation () {},
'keyCode': 9,
'key': 'Tab'
}
textarea.value = ':';
view.onKeyDown(tab_event);
await u.waitUntil(() => u.isVisible(view.el.querySelector('.emoji-picker__lists')));
const picker = view.el.querySelector('converse-emoji-picker');
const input = picker.querySelector('.emoji-search');
input.dispatchEvent(new KeyboardEvent('keydown', tab_event));
await u.waitUntil(() => input.value === ':100:');
const enter_event = Object.assign({}, tab_event, {'keyCode': 13, 'key': 'Enter', 'target': input});
input.dispatchEvent(new KeyboardEvent('keydown', enter_event));
expect(textarea.value).toBe(':100: ');
textarea.value = ':';
view.onKeyDown(tab_event);
await u.waitUntil(() => u.isVisible(view.el.querySelector('.emoji-picker__lists')));
await u.waitUntil(() => input.value === ':');
input.dispatchEvent(new KeyboardEvent('keydown', tab_event));
await u.waitUntil(() => input.value === ':100:');
await u.waitUntil(() => sizzle('.emojis-lists__container--search .insert-emoji:not(.hidden)', view.el).length === 1, 1000);
const emoji = sizzle('.emojis-lists__container--search .insert-emoji:not(.hidden) a', view.el).pop();
emoji.click();
expect(textarea.value).toBe(':100: ');
done();
}));
it("allows you to search for particular emojis",
mock.initConverse(
['rosterGroupsFetched', 'chatBoxesFetched'], {},
async function (done, _converse) {
const muc_jid = 'lounge@montague.lit';
await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
const view = _converse.chatboxviews.get(muc_jid);
await u.waitUntil(() => view.el.querySelector('converse-emoji-dropdown'));
const toolbar = view.el.querySelector('converse-chat-toolbar');
toolbar.querySelector('.toggle-emojis').click();
await u.waitUntil(() => u.isVisible(view.el.querySelector('.emoji-picker__lists')));
await u.waitUntil(() => sizzle('converse-chat-toolbar .insert-emoji:not(.hidden)', view.el).length === 1589);
const input = view.el.querySelector('.emoji-search');
input.value = 'smiley';
const event = {
'target': input,
'preventDefault': function preventDefault () {},
'stopPropagation': function stopPropagation () {}
};
input.dispatchEvent(new KeyboardEvent('keydown', event));
await u.waitUntil(() => sizzle('.emojis-lists__container--search .insert-emoji:not(.hidden)', view.el).length === 2, 1000);
let visible_emojis = sizzle('.emojis-lists__container--search .insert-emoji:not(.hidden)', view.el);
expect(visible_emojis[0].getAttribute('data-emoji')).toBe(':smiley:');
expect(visible_emojis[1].getAttribute('data-emoji')).toBe(':smiley_cat:');
// Check that pressing enter without an unambiguous match does nothing
const enter_event = Object.assign({}, event, {'keyCode': 13});
input.dispatchEvent(new KeyboardEvent('keydown', enter_event));
expect(input.value).toBe('smiley');
// Check that search results update when chars are deleted
input.value = 'sm';
input.dispatchEvent(new KeyboardEvent('keydown', event));
await u.waitUntil(() => sizzle('.emojis-lists__container--search .insert-emoji:not(.hidden)', view.el).length === 25, 1000);
input.value = 'smiley';
input.dispatchEvent(new KeyboardEvent('keydown', event));
await u.waitUntil(() => sizzle('.emojis-lists__container--search .insert-emoji:not(.hidden)', view.el).length === 2, 1000);
// Test that TAB autocompletes the to first match
const tab_event = Object.assign({}, event, {'keyCode': 9, 'key': 'Tab'});
input.dispatchEvent(new KeyboardEvent('keydown', tab_event));
await u.waitUntil(() => input.value === ':smiley:');
await u.waitUntil(() => sizzle(".emojis-lists__container--search .insert-emoji:not('.hidden')", view.el).length === 1, 1000);
visible_emojis = sizzle(".emojis-lists__container--search .insert-emoji:not('.hidden')", view.el);
expect(visible_emojis[0].getAttribute('data-emoji')).toBe(':smiley:');
// Check that ENTER now inserts the match
input.dispatchEvent(new KeyboardEvent('keydown', enter_event));
await u.waitUntil(() => input.value === '');
expect(view.el.querySelector('textarea.chat-textarea').value).toBe(':smiley: ');
done();
}));
});
describe("A Chat Message", function () {
it("will display larger if it's only emojis",
mock.initConverse(
['rosterGroupsFetched', 'chatBoxesFetched'], {'use_system_emojis': true},
async function (done, _converse) {
await mock.waitForRoster(_converse, 'current');
const sender_jid = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@montague.lit';
_converse.handleMessageStanza($msg({
'from': sender_jid,
'to': _converse.connection.jid,
'type': 'chat',
'id': _converse.connection.getUniqueId()
}).c('body').t('😇').up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
await new Promise(resolve => _converse.on('chatBoxViewInitialized', resolve));
const view = _converse.api.chatviews.get(sender_jid);
await new Promise(resolve => view.model.messages.once('rendered', resolve));
await u.waitUntil(() => u.hasClass('chat-msg__text--larger', view.content.querySelector('.chat-msg__text')));
_converse.handleMessageStanza($msg({
'from': sender_jid,
'to': _converse.connection.jid,
'type': 'chat',
'id': _converse.connection.getUniqueId()
}).c('body').t('😇 Hello world! 😇 😇').up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
await new Promise(resolve => view.model.messages.once('rendered', resolve));
let sel = '.message:last-child .chat-msg__text';
await u.waitUntil(() => u.hasClass('chat-msg__text--larger', view.content.querySelector(sel)));
// Test that a modified message that no longer contains only
// emojis now renders normally again.
const textarea = view.el.querySelector('textarea.chat-textarea');
textarea.value = ':poop: :innocent:';
view.onKeyDown({
target: textarea,
preventDefault: function preventDefault () {},
keyCode: 13 // Enter
});
await new Promise(resolve => view.model.messages.once('rendered', resolve));
expect(view.el.querySelectorAll('.chat-msg').length).toBe(3);
const last_msg_sel = 'converse-chat-message:last-child .chat-msg__text';
await u.waitUntil(() => view.content.querySelector(last_msg_sel).textContent === '💩 😇');
expect(textarea.value).toBe('');
view.onKeyDown({
target: textarea,
keyCode: 38 // Up arrow
});
expect(textarea.value).toBe('💩 😇');
expect(view.model.messages.at(2).get('correcting')).toBe(true);
sel = 'converse-chat-message:last-child .chat-msg'
await u.waitUntil(() => u.hasClass('correcting', view.el.querySelector(sel)), 500);
textarea.value = textarea.value += 'This is no longer an emoji-only message';
view.onKeyDown({
target: textarea,
preventDefault: function preventDefault () {},
keyCode: 13 // Enter
});
await new Promise(resolve => view.model.messages.once('rendered', resolve));
expect(view.model.messages.models.length).toBe(3);
let message = view.content.querySelector(last_msg_sel);
expect(u.hasClass('chat-msg__text--larger', message)).toBe(false);
textarea.value = ':smile: Hello world!';
view.onKeyDown({
target: textarea,
preventDefault: function preventDefault () {},
keyCode: 13 // Enter
});
await new Promise(resolve => view.model.messages.once('rendered', resolve));
textarea.value = ':smile: :smiley: :imp:';
view.onKeyDown({
target: textarea,
preventDefault: function preventDefault () {},
keyCode: 13 // Enter
});
await new Promise(resolve => view.model.messages.once('rendered', resolve));
message = view.content.querySelector('.message:last-child .chat-msg__text');
expect(u.hasClass('chat-msg__text--larger', message)).toBe(true);
done()
}));
it("can render emojis as images",
mock.initConverse(
['rosterGroupsFetched', 'chatBoxesFetched'], {'use_system_emojis': false},
async function (done, _converse) {
await mock.waitForRoster(_converse, 'current');
const sender_jid = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@montague.lit';
_converse.handleMessageStanza($msg({
'from': sender_jid,
'to': _converse.connection.jid,
'type': 'chat',
'id': _converse.connection.getUniqueId()
}).c('body').t('😇').up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
await new Promise(resolve => _converse.on('chatBoxViewInitialized', resolve));
const view = _converse.api.chatviews.get(sender_jid);
await new Promise(resolve => view.model.messages.once('rendered', resolve));
await u.waitUntil(() => u.hasClass('chat-msg__text--larger', view.content.querySelector('.chat-msg__text')));
const last_msg_sel = 'converse-chat-message:last-child .chat-msg__text';
let message = view.content.querySelector(last_msg_sel);
await u.waitUntil(() => u.isVisible(message.querySelector('.emoji')), 1000);
let imgs = message.querySelectorAll('.emoji');
expect(imgs.length).toBe(1);
expect(imgs[0].src).toBe(_converse.api.settings.get('emoji_image_path')+'/72x72/1f607.png');
const textarea = view.el.querySelector('textarea.chat-textarea');
textarea.value = ':poop: :innocent:';
view.onKeyDown({
target: textarea,
preventDefault: function preventDefault () {},
keyCode: 13 // Enter
});
await new Promise(resolve => view.model.messages.once('rendered', resolve));
message = view.content.querySelector(last_msg_sel);
await u.waitUntil(() => u.isVisible(message.querySelector('.emoji')), 1000);
imgs = message.querySelectorAll('.emoji');
expect(imgs.length).toBe(2);
expect(imgs[0].src).toBe(_converse.api.settings.get('emoji_image_path')+'/72x72/1f4a9.png');
expect(imgs[1].src).toBe(_converse.api.settings.get('emoji_image_path')+'/72x72/1f607.png');
done()
}));
it("can show custom emojis",
mock.initConverse(
['rosterGroupsFetched', 'chatBoxesFetched'],
{ emoji_categories: {
"smileys": ":grinning:",
"people": ":thumbsup:",
"activity": ":soccer:",
"travel": ":motorcycle:",
"objects": ":bomb:",
"nature": ":rainbow:",
"food": ":hotdog:",
"symbols": ":musical_note:",
"flags": ":flag_ac:",
"custom": ':xmpp:'
} },
async function (done, _converse) {
await mock.waitForRoster(_converse, 'current', 1);
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
await mock.openChatBoxFor(_converse, contact_jid);
const view = _converse.api.chatviews.get(contact_jid);
const toolbar = await u.waitUntil(() => view.el.querySelector('.chat-toolbar'));
toolbar.querySelector('.toggle-emojis').click();
await u.waitUntil(() => u.isVisible(view.el.querySelector('.emoji-picker__lists')), 1000);
const picker = await u.waitUntil(() => view.el.querySelector('converse-emoji-picker'), 1000);
const custom_category = picker.querySelector('.pick-category[data-category="custom"]');
expect(custom_category.innerHTML.replace(/<!---->/g, '').trim()).toBe(
'<img class="emoji" draggable="false" title=":xmpp:" alt=":xmpp:" src="/dist/images/custom_emojis/xmpp.png">');
const textarea = view.el.querySelector('textarea.chat-textarea');
textarea.value = 'Running tests for :converse:';
view.onKeyDown({
target: textarea,
preventDefault: function preventDefault () {},
keyCode: 13 // Enter
});
await new Promise(resolve => view.model.messages.once('rendered', resolve));
const body = view.el.querySelector('converse-chat-message-body');
await u.waitUntil(() => body.innerHTML.replace(/<!---->/g, '').trim() ===
'Running tests for <img class="emoji" draggable="false" title=":converse:" alt=":converse:" src="/dist/images/custom_emojis/converse.png">');
done();
}));
});
});

View File

@ -1,61 +0,0 @@
/*global mock */
describe("The _converse Event Emitter", function() {
it("allows you to subscribe to emitted events", mock.initConverse((done, _converse) => {
this.callback = function () {};
spyOn(this, 'callback');
_converse.on('connected', this.callback);
_converse.api.trigger('connected');
expect(this.callback).toHaveBeenCalled();
_converse.api.trigger('connected');
expect(this.callback.calls.count(), 2);
_converse.api.trigger('connected');
expect(this.callback.calls.count(), 3);
done();
}));
it("allows you to listen once for an emitted event", mock.initConverse((done, _converse) => {
this.callback = function () {};
spyOn(this, 'callback');
_converse.once('connected', this.callback);
_converse.api.trigger('connected');
expect(this.callback).toHaveBeenCalled();
_converse.api.trigger('connected');
expect(this.callback.calls.count(), 1);
_converse.api.trigger('connected');
expect(this.callback.calls.count(), 1);
done();
}));
it("allows you to stop listening or subscribing to an event", mock.initConverse((done, _converse) => {
this.callback = function () {};
this.anotherCallback = function () {};
this.neverCalled = function () {};
spyOn(this, 'callback');
spyOn(this, 'anotherCallback');
spyOn(this, 'neverCalled');
_converse.on('connected', this.callback);
_converse.on('connected', this.anotherCallback);
_converse.api.trigger('connected');
expect(this.callback).toHaveBeenCalled();
expect(this.anotherCallback).toHaveBeenCalled();
_converse.off('connected', this.callback);
_converse.api.trigger('connected');
expect(this.callback.calls.count(), 1);
expect(this.anotherCallback.calls.count(), 2);
_converse.once('connected', this.neverCalled);
_converse.off('connected', this.neverCalled);
_converse.api.trigger('connected');
expect(this.callback.calls.count(), 1);
expect(this.anotherCallback.calls.count(), 3);
expect(this.neverCalled).not.toHaveBeenCalled();
done();
}));
});

View File

@ -1,683 +0,0 @@
/*global converse */
const mock = {};
window.mock = mock;
let _converse, initConverse;
const converseLoaded = new Promise(resolve => window.addEventListener('converse-loaded', resolve));
jasmine.DEFAULT_TIMEOUT_INTERVAL = 7000;
mock.initConverse = function (promise_names=[], settings=null, func) {
if (typeof promise_names === "function") {
func = promise_names;
promise_names = []
settings = null;
}
return async done => {
if (_converse && _converse.api.connection.connected()) {
await _converse.api.user.logout();
}
const el = document.querySelector('#conversejs');
if (el) {
el.parentElement.removeChild(el);
}
document.title = "Converse Tests";
await converseLoaded;
await initConverse(settings);
await Promise.all((promise_names || []).map(_converse.api.waitUntil));
try {
await func(done, _converse);
} catch(e) {
console.error(e);
fail(e);
await done();
}
}
};
window.addEventListener('converse-loaded', () => {
const { u, sizzle, Strophe, dayjs, $iq, $msg, $pres } = converse.env;
mock.waitUntilDiscoConfirmed = async function (_converse, entity_jid, identities, features=[], items=[], type='info') {
const iq = await u.waitUntil(() => {
return _converse.connection.IQ_stanzas.filter(
iq => sizzle(`iq[to="${entity_jid}"] query[xmlns="http://jabber.org/protocol/disco#${type}"]`, iq).length
).pop();
}, 300);
const stanza = $iq({
'type': 'result',
'from': entity_jid,
'to': 'romeo@montague.lit/orchard',
'id': iq.getAttribute('id'),
}).c('query', {'xmlns': 'http://jabber.org/protocol/disco#'+type});
identities?.forEach(identity => stanza.c('identity', {'category': identity.category, 'type': identity.type}).up());
features?.forEach(feature => stanza.c('feature', {'var': feature}).up());
items?.forEach(item => stanza.c('item', {'jid': item}).up());
_converse.connection._dataRecv(mock.createRequest(stanza));
}
mock.createRequest = function (iq) {
iq = typeof iq.tree == "function" ? iq.tree() : iq;
var req = new Strophe.Request(iq, function() {});
req.getResponse = function () {
var env = new Strophe.Builder('env', {type: 'mock'}).tree();
env.appendChild(iq);
return env;
};
return req;
};
mock.closeAllChatBoxes = function (_converse) {
return Promise.all(_converse.chatboxviews.map(view => view.close()));
};
mock.toggleControlBox = function () {
const toggle = document.querySelector(".toggle-controlbox");
if (!u.isVisible(document.querySelector("#controlbox"))) {
if (!u.isVisible(toggle)) {
u.removeClass('hidden', toggle);
}
toggle.click();
}
}
mock.openControlBox = async function (_converse) {
const model = await _converse.api.controlbox.open();
await u.waitUntil(() => model.get('connected'));
mock.toggleControlBox();
return this;
};
mock.closeControlBox = function () {
const controlbox = document.querySelector("#controlbox");
if (u.isVisible(controlbox)) {
const button = controlbox.querySelector(".close-chatbox-button");
(button !== null) && button.click();
}
return this;
};
mock.waitUntilBookmarksReturned = async function (_converse, bookmarks=[]) {
await mock.waitUntilDiscoConfirmed(
_converse, _converse.bare_jid,
[{'category': 'pubsub', 'type': 'pep'}],
['http://jabber.org/protocol/pubsub#publish-options']
);
const IQ_stanzas = _converse.connection.IQ_stanzas;
const sent_stanza = await u.waitUntil(
() => IQ_stanzas.filter(s => sizzle('items[node="storage:bookmarks"]', s).length).pop()
);
const stanza = $iq({
'to': _converse.connection.jid,
'type':'result',
'id':sent_stanza.getAttribute('id')
}).c('pubsub', {'xmlns': Strophe.NS.PUBSUB})
.c('items', {'node': 'storage:bookmarks'})
.c('item', {'id': 'current'})
.c('storage', {'xmlns': 'storage:bookmarks'});
bookmarks.forEach(bookmark => {
stanza.c('conference', {
'name': bookmark.name,
'autojoin': bookmark.autojoin,
'jid': bookmark.jid
}).c('nick').t(bookmark.nick).up().up()
});
_converse.connection._dataRecv(mock.createRequest(stanza));
await _converse.api.waitUntil('bookmarksInitialized');
};
mock.openChatBoxes = function (converse, amount) {
for (let i=0; i<amount; i++) {
const jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@montague.lit';
converse.roster.get(jid).openChat();
}
};
mock.openChatBoxFor = async function (_converse, jid) {
await _converse.api.waitUntil('rosterContactsFetched');
_converse.roster.get(jid).openChat();
return u.waitUntil(() => _converse.chatboxviews.get(jid), 1000);
};
mock.openChatRoomViaModal = async function (_converse, jid, nick='') {
// Opens a new chatroom
const model = await _converse.api.controlbox.open('controlbox');
await u.waitUntil(() => model.get('connected'));
await mock.openControlBox(_converse);
const view = await _converse.chatboxviews.get('controlbox');
const roomspanel = view.roomspanel;
roomspanel.el.querySelector('.show-add-muc-modal').click();
mock.closeControlBox(_converse);
const modal = roomspanel.add_room_modal;
await u.waitUntil(() => u.isVisible(modal.el), 1500)
modal.el.querySelector('input[name="chatroom"]').value = jid;
if (nick) {
modal.el.querySelector('input[name="nickname"]').value = nick;
}
modal.el.querySelector('form input[type="submit"]').click();
await u.waitUntil(() => _converse.chatboxviews.get(jid), 1000);
return _converse.chatboxviews.get(jid);
};
mock.openChatRoom = function (_converse, room, server) {
return _converse.api.rooms.open(`${room}@${server}`);
};
mock.getRoomFeatures = async function (_converse, muc_jid, features=[]) {
const room = Strophe.getNodeFromJid(muc_jid);
muc_jid = muc_jid.toLowerCase();
const stanzas = _converse.connection.IQ_stanzas;
const stanza = await u.waitUntil(() => stanzas.filter(
iq => iq.querySelector(
`iq[to="${muc_jid}"] query[xmlns="http://jabber.org/protocol/disco#info"]`
)).pop()
);
const features_stanza = $iq({
'from': muc_jid,
'id': stanza.getAttribute('id'),
'to': 'romeo@montague.lit/desktop',
'type': 'result'
}).c('query', { 'xmlns': 'http://jabber.org/protocol/disco#info'})
.c('identity', {
'category': 'conference',
'name': room[0].toUpperCase() + room.slice(1),
'type': 'text'
}).up();
features = features.length ? features : mock.default_muc_features;
features.forEach(f => features_stanza.c('feature', {'var': f}).up());
features_stanza.c('x', { 'xmlns':'jabber:x:data', 'type':'result'})
.c('field', {'var':'FORM_TYPE', 'type':'hidden'})
.c('value').t('http://jabber.org/protocol/muc#roominfo').up().up()
.c('field', {'type':'text-single', 'var':'muc#roominfo_description', 'label':'Description'})
.c('value').t('This is the description').up().up()
.c('field', {'type':'text-single', 'var':'muc#roominfo_occupants', 'label':'Number of occupants'})
.c('value').t(0);
_converse.connection._dataRecv(mock.createRequest(features_stanza));
};
mock.waitForReservedNick = async function (_converse, muc_jid, nick) {
const stanzas = _converse.connection.IQ_stanzas;
const selector = `iq[to="${muc_jid.toLowerCase()}"] query[node="x-roomuser-item"]`;
const iq = await u.waitUntil(() => stanzas.filter(s => sizzle(selector, s).length).pop());
// We remove the stanza, otherwise we might get stale stanzas returned in our filter above.
stanzas.splice(stanzas.indexOf(iq), 1)
// The XMPP server returns the reserved nick for this user.
const IQ_id = iq.getAttribute('id');
const stanza = $iq({
'type': 'result',
'id': IQ_id,
'from': muc_jid,
'to': _converse.connection.jid
}).c('query', {'xmlns': 'http://jabber.org/protocol/disco#info', 'node': 'x-roomuser-item'});
if (nick) {
stanza.c('identity', {'category': 'conference', 'name': nick, 'type': 'text'});
}
_converse.connection._dataRecv(mock.createRequest(stanza));
if (nick) {
return u.waitUntil(() => nick);
}
};
mock.returnMemberLists = async function (_converse, muc_jid, members=[], affiliations=['member', 'owner', 'admin']) {
if (affiliations.length === 0) {
return;
}
const stanzas = _converse.connection.IQ_stanzas;
if (affiliations.includes('member')) {
const member_IQ = await u.waitUntil(() =>
stanzas.filter(s => sizzle(`iq[to="${muc_jid}"] query[xmlns="${Strophe.NS.MUC_ADMIN}"] item[affiliation="member"]`, s).length
).pop());
const member_list_stanza = $iq({
'from': 'coven@chat.shakespeare.lit',
'id': member_IQ.getAttribute('id'),
'to': 'romeo@montague.lit/orchard',
'type': 'result'
}).c('query', {'xmlns': Strophe.NS.MUC_ADMIN});
members.filter(m => m.affiliation === 'member').forEach(m => {
member_list_stanza.c('item', {
'affiliation': m.affiliation,
'jid': m.jid,
'nick': m.nick
});
});
_converse.connection._dataRecv(mock.createRequest(member_list_stanza));
}
if (affiliations.includes('admin')) {
const admin_IQ = await u.waitUntil(() => stanzas.filter(
s => sizzle(`iq[to="${muc_jid}"] query[xmlns="${Strophe.NS.MUC_ADMIN}"] item[affiliation="admin"]`, s).length
).pop());
const admin_list_stanza = $iq({
'from': 'coven@chat.shakespeare.lit',
'id': admin_IQ.getAttribute('id'),
'to': 'romeo@montague.lit/orchard',
'type': 'result'
}).c('query', {'xmlns': Strophe.NS.MUC_ADMIN});
members.filter(m => m.affiliation === 'admin').forEach(m => {
admin_list_stanza.c('item', {
'affiliation': m.affiliation,
'jid': m.jid,
'nick': m.nick
});
});
_converse.connection._dataRecv(mock.createRequest(admin_list_stanza));
}
if (affiliations.includes('owner')) {
const owner_IQ = await u.waitUntil(() => stanzas.filter(
s => sizzle(`iq[to="${muc_jid}"] query[xmlns="${Strophe.NS.MUC_ADMIN}"] item[affiliation="owner"]`, s).length
).pop());
const owner_list_stanza = $iq({
'from': 'coven@chat.shakespeare.lit',
'id': owner_IQ.getAttribute('id'),
'to': 'romeo@montague.lit/orchard',
'type': 'result'
}).c('query', {'xmlns': Strophe.NS.MUC_ADMIN});
members.filter(m => m.affiliation === 'owner').forEach(m => {
owner_list_stanza.c('item', {
'affiliation': m.affiliation,
'jid': m.jid,
'nick': m.nick
});
});
_converse.connection._dataRecv(mock.createRequest(owner_list_stanza));
}
return new Promise(resolve => _converse.api.listen.on('membersFetched', resolve));
};
mock.receiveOwnMUCPresence = async function (_converse, muc_jid, nick) {
const sent_stanzas = _converse.connection.sent_stanzas;
await u.waitUntil(() => sent_stanzas.filter(iq => sizzle('presence history', iq).length).pop());
const presence = $pres({
to: _converse.connection.jid,
from: `${muc_jid}/${nick}`,
id: u.getUniqueId()
}).c('x').attrs({xmlns:'http://jabber.org/protocol/muc#user'})
.c('item').attrs({
affiliation: 'owner',
jid: _converse.bare_jid,
role: 'moderator'
}).up()
.c('status').attrs({code:'110'});
_converse.connection._dataRecv(mock.createRequest(presence));
};
mock.openAndEnterChatRoom = async function (_converse, muc_jid, nick, features=[], members=[]) {
muc_jid = muc_jid.toLowerCase();
const room_creation_promise = _converse.api.rooms.open(muc_jid);
await mock.getRoomFeatures(_converse, muc_jid, features);
await mock.waitForReservedNick(_converse, muc_jid, nick);
// The user has just entered the room (because join was called)
// and receives their own presence from the server.
// See example 24: https://xmpp.org/extensions/xep-0045.html#enter-pres
await mock.receiveOwnMUCPresence(_converse, muc_jid, nick);
await room_creation_promise;
const view = _converse.chatboxviews.get(muc_jid);
await u.waitUntil(() => (view.model.session.get('connection_status') === converse.ROOMSTATUS.ENTERED));
const affs = _converse.muc_fetch_members;
const all_affiliations = Array.isArray(affs) ? affs : (affs ? ['member', 'admin', 'owner'] : []);
await mock.returnMemberLists(_converse, muc_jid, members, all_affiliations);
await view.model.messages.fetched;
};
mock.createContact = async function (_converse, name, ask, requesting, subscription) {
const jid = name.replace(/ /g,'.').toLowerCase() + '@montague.lit';
if (_converse.roster.get(jid)) {
return Promise.resolve();
}
const contact = await new Promise((success, error) => {
_converse.roster.create({
'ask': ask,
'fullname': name,
'jid': jid,
'requesting': requesting,
'subscription': subscription
}, {success, error});
});
return contact;
};
mock.createContacts = async function (_converse, type, length) {
/* Create current (as opposed to requesting or pending) contacts
* for the user's roster.
*
* These contacts are not grouped. See below.
*/
await _converse.api.waitUntil('rosterContactsFetched');
let names, subscription, requesting, ask;
if (type === 'requesting') {
names = mock.req_names;
subscription = 'none';
requesting = true;
ask = null;
} else if (type === 'pending') {
names = mock.pend_names;
subscription = 'none';
requesting = false;
ask = 'subscribe';
} else if (type === 'current') {
names = mock.cur_names;
subscription = 'both';
requesting = false;
ask = null;
} else if (type === 'all') {
await this.createContacts(_converse, 'current');
await this.createContacts(_converse, 'requesting')
await this.createContacts(_converse, 'pending');
return this;
} else {
throw Error("Need to specify the type of contact to create");
}
const promises = names.slice(0, length).map(n => this.createContact(_converse, n, ask, requesting, subscription));
await Promise.all(promises);
};
mock.waitForRoster = async function (_converse, type='current', length=-1, include_nick=true, grouped=true) {
const s = `iq[type="get"] query[xmlns="${Strophe.NS.ROSTER}"]`;
const iq = await u.waitUntil(() => _converse.connection.IQ_stanzas.filter(iq => sizzle(s, iq).length).pop());
const result = $iq({
'to': _converse.connection.jid,
'type': 'result',
'id': iq.getAttribute('id')
}).c('query', {
'xmlns': 'jabber:iq:roster'
});
if (type === 'pending' || type === 'all') {
const pend_names = (length > -1) ? mock.pend_names.slice(0, length) : mock.pend_names;
pend_names.map(name =>
result.c('item', {
jid: name.replace(/ /g,'.').toLowerCase() + '@montague.lit',
name: include_nick ? name : undefined,
subscription: 'none',
ask: 'subscribe'
}).up()
);
}
if (type === 'current' || type === 'all') {
const cur_names = Object.keys(mock.current_contacts_map);
const names = (length > -1) ? cur_names.slice(0, length) : cur_names;
names.forEach(name => {
result.c('item', {
jid: name.replace(/ /g,'.').toLowerCase() + '@montague.lit',
name: include_nick ? name : undefined,
subscription: 'both',
ask: null
});
if (grouped) {
mock.current_contacts_map[name].forEach(g => result.c('group').t(g).up());
}
result.up();
});
}
_converse.connection._dataRecv(mock.createRequest(result));
await _converse.api.waitUntil('rosterContactsFetched');
};
mock.createChatMessage = function (_converse, sender_jid, message) {
return $msg({
from: sender_jid,
to: _converse.connection.jid,
type: 'chat',
id: (new Date()).getTime()
})
.c('body').t(message).up()
.c('markable', {'xmlns': Strophe.NS.MARKERS}).up()
.c('active', {'xmlns': Strophe.NS.CHATSTATES}).tree();
}
mock.sendMessage = function (view, message) {
const promise = new Promise(resolve => view.model.messages.once('rendered', resolve));
view.el.querySelector('.chat-textarea').value = message;
view.onKeyDown({
target: view.el.querySelector('textarea.chat-textarea'),
preventDefault: () => {},
keyCode: 13
});
return promise;
};
window.libsignal = {
'SignalProtocolAddress': function (name, device_id) {
this.name = name;
this.deviceId = device_id;
},
'SessionCipher': function (storage, remote_address) {
this.remoteAddress = remote_address;
this.storage = storage;
this.encrypt = () => Promise.resolve({
'type': 1,
'body': 'c1ph3R73X7',
'registrationId': '1337'
});
this.decryptPreKeyWhisperMessage = (key_and_tag) => {
return Promise.resolve(key_and_tag);
};
this.decryptWhisperMessage = (key_and_tag) => {
return Promise.resolve(key_and_tag);
}
},
'SessionBuilder': function (storage, remote_address) { // eslint-disable-line no-unused-vars
this.processPreKey = function () {
return Promise.resolve();
}
},
'KeyHelper': {
'generateIdentityKeyPair': function () {
return Promise.resolve({
'pubKey': new TextEncoder('utf-8').encode('1234'),
'privKey': new TextEncoder('utf-8').encode('4321')
});
},
'generateRegistrationId': function () {
return '123456789';
},
'generatePreKey': function (keyid) {
return Promise.resolve({
'keyId': keyid,
'keyPair': {
'pubKey': new TextEncoder('utf-8').encode('1234'),
'privKey': new TextEncoder('utf-8').encode('4321')
}
});
},
'generateSignedPreKey': function (identity_keypair, keyid) {
return Promise.resolve({
'signature': new TextEncoder('utf-8').encode('11112222333344445555'),
'keyId': keyid,
'keyPair': {
'pubKey': new TextEncoder('utf-8').encode('1234'),
'privKey': new TextEncoder('utf-8').encode('4321')
}
});
}
}
};
mock.default_muc_features = [
'http://jabber.org/protocol/muc',
'jabber:iq:register',
Strophe.NS.SID,
Strophe.NS.MAM,
'muc_passwordprotected',
'muc_hidden',
'muc_temporary',
'muc_open',
'muc_unmoderated',
'muc_anonymous'
];
mock.view_mode = 'overlayed';
// Names from http://www.fakenamegenerator.com/
mock.req_names = [
'Escalus, prince of Verona', 'The Nurse', 'Paris'
];
mock.pend_names = [
'Lord Capulet', 'Guard', 'Servant'
];
mock.current_contacts_map = {
'Mercutio': ['Colleagues', 'friends & acquaintences'],
'Juliet Capulet': ['friends & acquaintences'],
'Lady Montague': ['Colleagues', 'Family'],
'Lord Montague': ['Family'],
'Friar Laurence': ['friends & acquaintences'],
'Tybalt': ['friends & acquaintences'],
'Lady Capulet': ['ænemies'],
'Benviolo': ['friends & acquaintences'],
'Balthasar': ['Colleagues'],
'Peter': ['Colleagues'],
'Abram': ['Colleagues'],
'Sampson': ['Colleagues'],
'Gregory': ['friends & acquaintences'],
'Potpan': [],
'Friar John': []
};
const map = mock.current_contacts_map;
const groups_map = {};
Object.keys(map).forEach(k => {
const groups = map[k].length ? map[k] : ["Ungrouped"];
Object.values(groups).forEach(g => {
groups_map[g] = groups_map[g] ? [...groups_map[g], k] : [k]
});
});
mock.groups_map = groups_map;
mock.cur_names = Object.keys(mock.current_contacts_map);
mock.num_contacts = mock.req_names.length + mock.pend_names.length + mock.cur_names.length;
mock.groups = {
'colleagues': 3,
'friends & acquaintences': 3,
'Family': 4,
'ænemies': 3,
'Ungrouped': 2
};
mock.chatroom_names = [
'Dyon van de Wege',
'Thomas Kalb',
'Dirk Theissen',
'Felix Hofmann',
'Ka Lek',
'Anne Ebersbacher'
];
// TODO: need to also test other roles and affiliations
mock.chatroom_roles = {
'Anne Ebersbacher': { affiliation: "owner", role: "moderator" },
'Dirk Theissen': { affiliation: "admin", role: "moderator" },
'Dyon van de Wege': { affiliation: "member", role: "occupant" },
'Felix Hofmann': { affiliation: "member", role: "occupant" },
'Ka Lek': { affiliation: "member", role: "occupant" },
'Thomas Kalb': { affiliation: "member", role: "occupant" }
};
mock.event = {
'preventDefault': function () {}
};
function clearIndexedDB () {
const promise = u.getResolveablePromise();
const db_request = window.indexedDB.open("converse-test-persistent");
db_request.onsuccess = function () {
const db = db_request.result;
const bare_jid = "romeo@montague.lit";
let store;
try {
store= db.transaction([bare_jid], "readwrite").objectStore(bare_jid);
} catch (e) {
return promise.resolve();
}
const request = store.clear();
request.onsuccess = promise.resolve();
request.onerror = promise.resolve();
};
db_request.onerror = function (ev) {
return promise.reject(ev.target.error);
}
return promise;
}
function clearStores () {
[localStorage, sessionStorage].forEach(
s => Object.keys(s).forEach(k => k.match(/^converse-test-/) && s.removeItem(k))
);
const cache_key = `converse.room-bookmarksromeo@montague.lit`;
window.sessionStorage.removeItem(cache_key+'fetched');
}
initConverse = async (settings) => {
clearStores();
await clearIndexedDB();
_converse = await converse.initialize(Object.assign({
'animate': false,
'auto_subscribe': false,
'bosh_service_url': 'montague.lit/http-bind',
'discover_connection_methods': false,
'enable_smacks': false,
'i18n': 'en',
// 'persistent_store': 'IndexedDB',
'loglevel': 'warn',
'no_trimming': true,
'play_sounds': false,
'use_emojione': false,
'view_mode': mock.view_mode
}, settings || {}));
_converse.ChatBoxViews.prototype.trimChat = function () {};
_converse.api.vcard.get = function (model, force) {
let jid;
if (typeof model === 'string' || model instanceof String) {
jid = model;
} else if (!model.get('vcard_updated') || force) {
jid = model.get('jid') || model.get('muc_jid');
}
let fullname;
if (!jid || jid == 'romeo@montague.lit') {
jid = 'romeo@montague.lit';
fullname = 'Romeo Montague' ;
} else {
const name = jid.split('@')[0].replace(/\./g, ' ').split(' ');
const last = name.length-1;
name[0] = name[0].charAt(0).toUpperCase()+name[0].slice(1);
name[last] = name[last].charAt(0).toUpperCase()+name[last].slice(1);
fullname = name.join(' ');
}
const vcard = $iq().c('vCard').c('FN').t(fullname).nodeTree;
return {
'vcard': vcard,
'fullname': vcard.querySelector('FN')?.textContent,
'image': vcard.querySelector('PHOTO BINVAL')?.textContent,
'image_type': vcard.querySelector('PHOTO TYPE')?.textContent,
'url': vcard.querySelector('URL')?.textContent,
'vcard_updated': dayjs().format(),
'vcard_error': undefined
};
};
if (settings?.auto_login !== false) {
_converse.api.user.login('romeo@montague.lit/orchard', 'secret');
await _converse.api.waitUntil('afterResourceBinding');
}
window.converse_disable_effects = true;
return _converse;
}
});
converse.load();

View File

@ -1,705 +0,0 @@
/*global mock, converse */
const { Promise, Strophe, $msg, $pres, sizzle, stanza_utils } = converse.env;
const u = converse.env.utils;
const original_timeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
describe("A Groupchat Message", function () {
beforeEach(() => (jasmine.DEFAULT_TIMEOUT_INTERVAL = 7000));
afterEach(() => (jasmine.DEFAULT_TIMEOUT_INTERVAL = original_timeout));
describe("which is succeeded by an error message", function () {
it("will have the error displayed below it",
mock.initConverse(
['rosterGroupsFetched'], {},
async function (done, _converse) {
const muc_jid = 'lounge@montague.lit';
await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
const view = _converse.api.chatviews.get(muc_jid);
const textarea = view.el.querySelector('textarea.chat-textarea');
textarea.value = 'hello world'
const enter_event = {
'target': textarea,
'preventDefault': function preventDefault () {},
'stopPropagation': function stopPropagation () {},
'keyCode': 13 // Enter
}
view.onKeyDown(enter_event);
await new Promise(resolve => view.model.messages.once('rendered', resolve));
const msg = view.model.messages.at(0);
const err_msg_text = "Message rejected because you're sending messages too quickly";
const error = u.toStanza(`
<message xmlns="jabber:client" id="${msg.get('msgid')}" from="${muc_jid}" to="${_converse.jid}" type="error">
<error type="wait">
<policy-violation xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
<text xmlns="urn:ietf:params:xml:ns:xmpp-stanzas">${err_msg_text}</text>
</error>
<body>hello world</body>
</message>
`);
_converse.connection._dataRecv(mock.createRequest(error));
expect(await u.waitUntil(() => view.el.querySelector('.chat-msg__error')?.textContent?.trim())).toBe(err_msg_text);
expect(view.model.messages.length).toBe(1);
const message = view.model.messages.at(0);
expect(message.get('received')).toBeUndefined();
expect(message.get('body')).toBe('hello world');
expect(message.get('error_text')).toBe(err_msg_text);
expect(message.get('editable')).toBe(false);
done();
}));
});
describe("an info message", function () {
it("is not rendered as a followup message",
mock.initConverse(
['rosterGroupsFetched', 'chatBoxesFetched'], {},
async function (done, _converse) {
const muc_jid = 'lounge@montague.lit';
await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
const view = _converse.api.chatviews.get(muc_jid);
let presence = u.toStanza(`
<presence xmlns="jabber:client" to="${_converse.jid}" from="${muc_jid}/romeo">
<x xmlns="http://jabber.org/protocol/muc#user">
<status code="201"/>
<item role="moderator" affiliation="owner" jid="${_converse.jid}"/>
<status code="110"/>
</x>
</presence>
`);
_converse.connection._dataRecv(mock.createRequest(presence));
await u.waitUntil(() => view.el.querySelectorAll('.chat-info').length === 1);
presence = u.toStanza(`
<presence xmlns="jabber:client" to="${_converse.jid}" from="${muc_jid}/romeo1">
<x xmlns="http://jabber.org/protocol/muc#user">
<status code="210"/>
<item role="moderator" affiliation="owner" jid="${_converse.jid}"/>
<status code="110"/>
</x>
</presence>
`);
_converse.connection._dataRecv(mock.createRequest(presence));
await u.waitUntil(() => view.el.querySelectorAll('.chat-info').length === 2);
const messages = view.el.querySelectorAll('.chat-info');
expect(u.hasClass('chat-msg--followup', messages[0])).toBe(false);
expect(u.hasClass('chat-msg--followup', messages[1])).toBe(false);
done();
}));
it("is not shown if its a duplicate",
mock.initConverse(
['rosterGroupsFetched', 'chatBoxesFetched'], {},
async function (done, _converse) {
const muc_jid = 'lounge@montague.lit';
await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
const view = _converse.api.chatviews.get(muc_jid);
const presence = u.toStanza(`
<presence xmlns="jabber:client" to="${_converse.jid}" from="${muc_jid}/romeo">
<x xmlns="http://jabber.org/protocol/muc#user">
<status code="201"/>
<item role="moderator" affiliation="owner" jid="${_converse.jid}"/>
<status code="110"/>
</x>
</presence>
`);
// XXX: We wait for createInfoMessages to complete, if we don't
// we still get two info messages due to messages
// created from presences not being queued and run
// sequentially (i.e. by waiting for promises to resolve)
// like we do with message stanzas.
spyOn(view.model, 'createInfoMessages').and.callThrough();
_converse.connection._dataRecv(mock.createRequest(presence));
await u.waitUntil(() => view.model.createInfoMessages.calls.count());
await u.waitUntil(() => view.el.querySelectorAll('.chat-info').length === 1);
_converse.connection._dataRecv(mock.createRequest(presence));
await u.waitUntil(() => view.model.createInfoMessages.calls.count() === 2);
expect(view.el.querySelectorAll('.chat-info').length).toBe(1);
done();
}));
});
it("is rejected if it's an unencapsulated forwarded message",
mock.initConverse(
['rosterGroupsFetched', 'chatBoxesFetched'], {},
async function (done, _converse) {
const muc_jid = 'lounge@montague.lit';
await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
const impersonated_jid = `${muc_jid}/alice`;
const received_stanza = u.toStanza(`
<message to='${_converse.jid}' from='${muc_jid}/mallory' type='groupchat' id='${_converse.connection.getUniqueId()}'>
<forwarded xmlns='urn:xmpp:forward:0'>
<delay xmlns='urn:xmpp:delay' stamp='2019-07-10T23:08:25Z'/>
<message from='${impersonated_jid}'
id='0202197'
to='${_converse.bare_jid}'
type='groupchat'
xmlns='jabber:client'>
<body>Yet I should kill thee with much cherishing.</body>
</message>
</forwarded>
</message>
`);
const view = _converse.api.chatviews.get(muc_jid);
spyOn(view.model, 'onMessage').and.callThrough();
spyOn(converse.env.log, 'error');
_converse.connection._dataRecv(mock.createRequest(received_stanza));
await u.waitUntil(() => view.model.onMessage.calls.count() === 1);
expect(converse.env.log.error).toHaveBeenCalledWith(
`Ignoring unencapsulated forwarded message from ${muc_jid}/mallory`
);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(0);
expect(view.model.messages.length).toBe(0);
done();
}));
it("can contain a chat state notification and will still be shown",
mock.initConverse(
['rosterGroupsFetched', 'chatBoxesFetched'], {},
async function (done, _converse) {
const muc_jid = 'lounge@montague.lit';
await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
const view = _converse.api.chatviews.get(muc_jid);
if (!view.el.querySelectorAll('.chat-area').length) { view.renderChatArea(); }
const message = 'romeo: Your attention is required';
const nick = mock.chatroom_names[0],
msg = $msg({
from: 'lounge@montague.lit/'+nick,
id: u.getUniqueId(),
to: 'romeo@montague.lit',
type: 'groupchat'
}).c('body').t(message)
.c('active', {'xmlns': "http://jabber.org/protocol/chatstates"})
.tree();
await view.model.handleMessageStanza(msg);
await new Promise(resolve => view.model.messages.once('rendered', resolve));
expect(view.el.querySelector('.chat-msg')).not.toBe(null);
done();
}));
it("can not be expected to have a unique id attribute",
mock.initConverse(
['rosterGroupsFetched', 'chatBoxesFetched'], {},
async function (done, _converse) {
const muc_jid = 'lounge@montague.lit';
await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
const view = _converse.api.chatviews.get(muc_jid);
if (!view.el.querySelectorAll('.chat-area').length) { view.renderChatArea(); }
const id = u.getUniqueId();
let msg = $msg({
from: 'lounge@montague.lit/some1',
id: id,
to: 'romeo@montague.lit',
type: 'groupchat'
}).c('body').t('First message').tree();
await view.model.handleMessageStanza(msg);
await u.waitUntil(() => view.el.querySelectorAll('.chat-msg').length === 1);
msg = $msg({
from: 'lounge@montague.lit/some2',
id: id,
to: 'romeo@montague.lit',
type: 'groupchat'
}).c('body').t('Another message').tree();
await view.model.handleMessageStanza(msg);
await u.waitUntil(() => view.el.querySelectorAll('.chat-msg').length === 2);
expect(view.model.messages.length).toBe(2);
done();
}));
it("is ignored if it has the same archive-id of an already received one",
mock.initConverse(
['rosterGroupsFetched'], {},
async function (done, _converse) {
const muc_jid = 'room@muc.example.com';
await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
const view = _converse.api.chatviews.get(muc_jid);
spyOn(view.model, 'getDuplicateMessage').and.callThrough();
let stanza = u.toStanza(`
<message xmlns="jabber:client"
from="room@muc.example.com/some1"
to="${_converse.connection.jid}"
type="groupchat">
<body>Typical body text</body>
<stanza-id xmlns="urn:xmpp:sid:0"
id="5f3dbc5e-e1d3-4077-a492-693f3769c7ad"
by="room@muc.example.com"/>
</message>`);
_converse.connection._dataRecv(mock.createRequest(stanza));
await u.waitUntil(() => view.model.messages.length === 1);
await u.waitUntil(() => view.model.getDuplicateMessage.calls.count() === 1);
let result = await view.model.getDuplicateMessage.calls.all()[0].returnValue;
expect(result).toBe(undefined);
stanza = u.toStanza(`
<message xmlns="jabber:client"
to="${_converse.connection.jid}"
from="room@muc.example.com">
<result xmlns="urn:xmpp:mam:2" queryid="82d9db27-6cf8-4787-8c2c-5a560263d823" id="5f3dbc5e-e1d3-4077-a492-693f3769c7ad">
<forwarded xmlns="urn:xmpp:forward:0">
<delay xmlns="urn:xmpp:delay" stamp="2018-01-09T06:17:23Z"/>
<message from="room@muc.example.com/some1" type="groupchat">
<body>Typical body text</body>
</message>
</forwarded>
</result>
</message>`);
spyOn(view.model, 'updateMessage');
view.model.handleMAMResult({ 'messages': [stanza] });
await u.waitUntil(() => view.model.getDuplicateMessage.calls.count() === 2);
result = await view.model.getDuplicateMessage.calls.all()[1].returnValue;
expect(result instanceof _converse.Message).toBe(true);
expect(view.model.messages.length).toBe(1);
await u.waitUntil(() => view.model.updateMessage.calls.count());
done();
}));
it("is ignored if it has the same stanza-id of an already received one",
mock.initConverse(
['rosterGroupsFetched'], {},
async function (done, _converse) {
const muc_jid = 'room@muc.example.com';
await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
const view = _converse.api.chatviews.get(muc_jid);
spyOn(view.model, 'getStanzaIdQueryAttrs').and.callThrough();
let stanza = u.toStanza(`
<message xmlns="jabber:client"
from="room@muc.example.com/some1"
to="${_converse.connection.jid}"
type="groupchat">
<body>Typical body text</body>
<stanza-id xmlns="urn:xmpp:sid:0"
id="5f3dbc5e-e1d3-4077-a492-693f3769c7ad"
by="room@muc.example.com"/>
</message>`);
_converse.connection._dataRecv(mock.createRequest(stanza));
await u.waitUntil(() => view.model.messages.length === 1);
await u.waitUntil(() => view.model.getStanzaIdQueryAttrs.calls.count() === 1);
let result = await view.model.getStanzaIdQueryAttrs.calls.all()[0].returnValue;
expect(result instanceof Array).toBe(true);
expect(result[0] instanceof Object).toBe(true);
expect(result[0]['stanza_id room@muc.example.com']).toBe("5f3dbc5e-e1d3-4077-a492-693f3769c7ad");
stanza = u.toStanza(`
<message xmlns="jabber:client"
from="room@muc.example.com/some1"
to="${_converse.connection.jid}"
type="groupchat">
<body>Typical body text</body>
<stanza-id xmlns="urn:xmpp:sid:0"
id="5f3dbc5e-e1d3-4077-a492-693f3769c7ad"
by="room@muc.example.com"/>
</message>`);
spyOn(view.model, 'updateMessage');
spyOn(view.model, 'getDuplicateMessage').and.callThrough();
_converse.connection._dataRecv(mock.createRequest(stanza));
await u.waitUntil(() => view.model.getDuplicateMessage.calls.count());
result = await view.model.getDuplicateMessage.calls.all()[0].returnValue;
expect(result instanceof _converse.Message).toBe(true);
expect(view.model.messages.length).toBe(1);
await u.waitUntil(() => view.model.updateMessage.calls.count());
done();
}));
it("will be discarded if it's a malicious message meant to look like a carbon copy",
mock.initConverse(
['rosterGroupsFetched'], {},
async function (done, _converse) {
await mock.waitForRoster(_converse, 'current');
await mock.openControlBox(_converse);
const muc_jid = 'xsf@muc.xmpp.org';
const sender_jid = `${muc_jid}/romeo`;
const impersonated_jid = `${muc_jid}/i_am_groot`
await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
const stanza = $pres({
to: 'romeo@montague.lit/_converse.js-29092160',
from: sender_jid
})
.c('x', {xmlns: Strophe.NS.MUC_USER})
.c('item', {
'affiliation': 'owner',
'jid': 'newguy@montague.lit/_converse.js-290929789',
'role': 'participant'
}).tree();
_converse.connection._dataRecv(mock.createRequest(stanza));
/*
* <message to="romeo@montague.im/poezio" id="718d40df-3948-4798-a99b-35cc9f03cc4f-641" type="groupchat" from="xsf@muc.xmpp.org/romeo">
* <received xmlns="urn:xmpp:carbons:2">
* <forwarded xmlns="urn:xmpp:forward:0">
* <message xmlns="jabber:client" to="xsf@muc.xmpp.org" type="groupchat" from="xsf@muc.xmpp.org/i_am_groot">
* <body>I am groot.</body>
* </message>
* </forwarded>
* </received>
* </message>
*/
const msg = $msg({
'from': sender_jid,
'id': _converse.connection.getUniqueId(),
'to': _converse.connection.jid,
'type': 'groupchat',
'xmlns': 'jabber:client'
}).c('received', {'xmlns': 'urn:xmpp:carbons:2'})
.c('forwarded', {'xmlns': 'urn:xmpp:forward:0'})
.c('message', {
'xmlns': 'jabber:client',
'from': impersonated_jid,
'to': muc_jid,
'type': 'groupchat'
}).c('body').t('I am groot').tree();
const view = _converse.api.chatviews.get(muc_jid);
spyOn(converse.env.log, 'error');
await view.model.handleMAMResult({ 'messages': [msg] });
await u.waitUntil(() => converse.env.log.error.calls.count());
expect(converse.env.log.error).toHaveBeenCalledWith(
'Invalid Stanza: MUC messages SHOULD NOT be XEP-0280 carbon copied'
);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(0);
expect(view.model.messages.length).toBe(0);
done();
}));
it("keeps track of the sender's role and affiliation",
mock.initConverse(
['rosterGroupsFetched'], {},
async function (done, _converse) {
const muc_jid = 'lounge@montague.lit';
await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
const view = _converse.api.chatviews.get(muc_jid);
let msg = $msg({
from: 'lounge@montague.lit/romeo',
id: u.getUniqueId(),
to: 'romeo@montague.lit',
type: 'groupchat'
}).c('body').t('I wrote this message!').tree();
await view.model.handleMessageStanza(msg);
await u.waitUntil(() => view.el.querySelectorAll('.chat-msg').length);
expect(view.model.messages.last().occupant.get('affiliation')).toBe('owner');
expect(view.model.messages.last().occupant.get('role')).toBe('moderator');
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
expect(sizzle('.chat-msg', view.el).pop().classList.value.trim()).toBe('message chat-msg groupchat chat-msg--with-avatar moderator owner');
let presence = $pres({
to:'romeo@montague.lit/orchard',
from:'lounge@montague.lit/romeo',
id: u.getUniqueId()
}).c('x').attrs({xmlns:'http://jabber.org/protocol/muc#user'})
.c('item').attrs({
affiliation: 'member',
jid: 'romeo@montague.lit/orchard',
role: 'participant'
}).up()
.c('status').attrs({code:'110'}).up()
.c('status').attrs({code:'210'}).nodeTree;
_converse.connection._dataRecv(mock.createRequest(presence));
msg = $msg({
from: 'lounge@montague.lit/romeo',
id: u.getUniqueId(),
to: 'romeo@montague.lit',
type: 'groupchat'
}).c('body').t('Another message!').tree();
await view.model.handleMessageStanza(msg);
await new Promise(resolve => view.model.messages.once('rendered', resolve));
expect(view.model.messages.last().occupant.get('affiliation')).toBe('member');
expect(view.model.messages.last().occupant.get('role')).toBe('participant');
expect(view.el.querySelectorAll('.chat-msg').length).toBe(2);
expect(sizzle('.chat-msg', view.el).pop().classList.value.trim()).toBe('message chat-msg groupchat chat-msg--with-avatar participant member');
presence = $pres({
to:'romeo@montague.lit/orchard',
from:'lounge@montague.lit/romeo',
id: u.getUniqueId()
}).c('x').attrs({xmlns:'http://jabber.org/protocol/muc#user'})
.c('item').attrs({
affiliation: 'owner',
jid: 'romeo@montague.lit/orchard',
role: 'moderator'
}).up()
.c('status').attrs({code:'110'}).up()
.c('status').attrs({code:'210'}).nodeTree;
_converse.connection._dataRecv(mock.createRequest(presence));
view.model.sendMessage('hello world');
await u.waitUntil(() => view.el.querySelectorAll('.chat-msg').length === 3);
const occupant = await u.waitUntil(() => view.model.messages.filter(m => m.get('type') === 'groupchat')[2].occupant);
expect(occupant.get('affiliation')).toBe('owner');
expect(occupant.get('role')).toBe('moderator');
expect(view.el.querySelectorAll('.chat-msg').length).toBe(3);
await u.waitUntil(() => sizzle('.chat-msg', view.el).pop().classList.value.trim() === 'message chat-msg groupchat chat-msg--with-avatar moderator owner');
const add_events = view.model.occupants._events.add.length;
msg = $msg({
from: 'lounge@montague.lit/some1',
id: u.getUniqueId(),
to: 'romeo@montague.lit',
type: 'groupchat'
}).c('body').t('Message from someone not in the MUC right now').tree();
await view.model.handleMessageStanza(msg);
await new Promise(resolve => view.model.messages.once('rendered', resolve));
expect(view.model.messages.last().occupant).toBeUndefined();
// Check that there's a new "add" event handler, for when the occupant appears.
expect(view.model.occupants._events.add.length).toBe(add_events+1);
// Check that the occupant gets added/removed to the message as it
// gets removed or added.
presence = $pres({
to:'romeo@montague.lit/orchard',
from:'lounge@montague.lit/some1',
id: u.getUniqueId()
}).c('x').attrs({xmlns:'http://jabber.org/protocol/muc#user'})
.c('item').attrs({jid: 'some1@montague.lit/orchard'});
_converse.connection._dataRecv(mock.createRequest(presence));
await u.waitUntil(() => view.model.messages.last().occupant);
expect(view.model.messages.last().get('message')).toBe('Message from someone not in the MUC right now');
expect(view.model.messages.last().occupant.get('nick')).toBe('some1');
// Check that the "add" event handler was removed.
expect(view.model.occupants._events.add.length).toBe(add_events);
presence = $pres({
to:'romeo@montague.lit/orchard',
type: 'unavailable',
from:'lounge@montague.lit/some1',
id: u.getUniqueId()
}).c('x').attrs({xmlns:'http://jabber.org/protocol/muc#user'})
.c('item').attrs({jid: 'some1@montague.lit/orchard'});
_converse.connection._dataRecv(mock.createRequest(presence));
await u.waitUntil(() => !view.model.messages.last().occupant);
expect(view.model.messages.last().get('message')).toBe('Message from someone not in the MUC right now');
expect(view.model.messages.last().occupant).toBeUndefined();
// Check that there's a new "add" event handler, for when the occupant appears.
expect(view.model.occupants._events.add.length).toBe(add_events+1);
presence = $pres({
to:'romeo@montague.lit/orchard',
from:'lounge@montague.lit/some1',
id: u.getUniqueId()
}).c('x').attrs({xmlns:'http://jabber.org/protocol/muc#user'})
.c('item').attrs({jid: 'some1@montague.lit/orchard'});
_converse.connection._dataRecv(mock.createRequest(presence));
await u.waitUntil(() => view.model.messages.last().occupant);
expect(view.model.messages.last().get('message')).toBe('Message from someone not in the MUC right now');
expect(view.model.messages.last().occupant.get('nick')).toBe('some1');
// Check that the "add" event handler was removed.
expect(view.model.occupants._events.add.length).toBe(add_events);
done();
}));
it("keeps track whether you are the sender or not",
mock.initConverse(
['rosterGroupsFetched'], {},
async function (done, _converse) {
const muc_jid = 'lounge@montague.lit';
await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
const view = _converse.api.chatviews.get(muc_jid);
const msg = $msg({
from: 'lounge@montague.lit/romeo',
id: u.getUniqueId(),
to: 'romeo@montague.lit',
type: 'groupchat'
}).c('body').t('I wrote this message!').tree();
await view.model.handleMessageStanza(msg);
expect(view.model.messages.last().get('sender')).toBe('me');
done();
}));
it("will be shown as received upon MUC reflection",
mock.initConverse(
['rosterGroupsFetched'], {},
async function (done, _converse) {
await mock.waitForRoster(_converse, 'current');
const muc_jid = 'lounge@montague.lit';
await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
const view = _converse.api.chatviews.get(muc_jid);
const textarea = view.el.querySelector('textarea.chat-textarea');
textarea.value = 'But soft, what light through yonder airlock breaks?';
view.onKeyDown({
target: textarea,
preventDefault: function preventDefault () {},
keyCode: 13 // Enter
});
await new Promise(resolve => view.model.messages.once('rendered', resolve));
expect(view.el.querySelectorAll('.chat-msg__body.chat-msg__body--received').length).toBe(0);
const msg_obj = view.model.messages.at(0);
const stanza = u.toStanza(`
<message xmlns="jabber:client"
from="${msg_obj.get('from')}"
to="${_converse.connection.jid}"
type="groupchat">
<body>${msg_obj.get('message')}</body>
<stanza-id xmlns="urn:xmpp:sid:0"
id="5f3dbc5e-e1d3-4077-a492-693f3769c7ad"
by="lounge@montague.lit"/>
<origin-id xmlns="urn:xmpp:sid:0" id="${msg_obj.get('origin_id')}"/>
</message>`);
await view.model.handleMessageStanza(stanza);
await u.waitUntil(() => view.el.querySelectorAll('.chat-msg__body.chat-msg__body--received').length, 500);
expect(view.el.querySelectorAll('.chat-msg__receipt').length).toBe(0);
expect(view.el.querySelectorAll('.chat-msg__body.chat-msg__body--received').length).toBe(1);
expect(view.model.messages.length).toBe(1);
const message = view.model.messages.at(0);
expect(message.get('stanza_id lounge@montague.lit')).toBe('5f3dbc5e-e1d3-4077-a492-693f3769c7ad');
expect(message.get('origin_id')).toBe(msg_obj.get('origin_id'));
done();
}));
it("gets updated with its stanza-id upon MUC reflection",
mock.initConverse(
['rosterGroupsFetched'], {},
async function (done, _converse) {
const muc_jid = 'room@muc.example.com';
await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
const view = _converse.api.chatviews.get(muc_jid);
view.model.sendMessage('hello world');
await u.waitUntil(() => view.model.messages.length === 1);
const msg = view.model.messages.at(0);
expect(msg.get('stanza_id')).toBeUndefined();
expect(msg.get('origin_id')).toBe(msg.get('origin_id'));
const stanza = u.toStanza(`
<message xmlns="jabber:client"
from="room@muc.example.com/romeo"
to="${_converse.connection.jid}"
type="groupchat">
<body>Hello world</body>
<stanza-id xmlns="urn:xmpp:sid:0"
id="5f3dbc5e-e1d3-4077-a492-693f3769c7ad"
by="room@muc.example.com"/>
<origin-id xmlns="urn:xmpp:sid:0" id="${msg.get('origin_id')}"/>
</message>`);
spyOn(view.model, 'updateMessage').and.callThrough();
_converse.connection._dataRecv(mock.createRequest(stanza));
await u.waitUntil(() => view.model.updateMessage.calls.count() === 1);
expect(view.model.messages.length).toBe(1);
expect(view.model.messages.at(0).get('stanza_id room@muc.example.com')).toBe("5f3dbc5e-e1d3-4077-a492-693f3769c7ad");
expect(view.model.messages.at(0).get('origin_id')).toBe(msg.get('origin_id'));
done();
}));
it("can cause a delivery receipt to be returned",
mock.initConverse(
['rosterGroupsFetched'], {},
async function (done, _converse) {
await mock.waitForRoster(_converse, 'current');
const muc_jid = 'lounge@montague.lit';
await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
const view = _converse.api.chatviews.get(muc_jid);
const textarea = view.el.querySelector('textarea.chat-textarea');
textarea.value = 'But soft, what light through yonder airlock breaks?';
view.onKeyDown({
target: textarea,
preventDefault: function preventDefault () {},
keyCode: 13 // Enter
});
await new Promise(resolve => view.model.messages.once('rendered', resolve));
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
const msg_obj = view.model.messages.at(0);
const stanza = u.toStanza(`
<message xml:lang="en" to="romeo@montague.lit/orchard"
from="lounge@montague.lit/some1" type="groupchat" xmlns="jabber:client">
<received xmlns="urn:xmpp:receipts" id="${msg_obj.get('msgid')}"/>
<origin-id xmlns="urn:xmpp:sid:0" id="CE08D448-5ED8-4B6A-BB5B-07ED9DFE4FF0"/>
</message>`);
spyOn(stanza_utils, "parseMUCMessage").and.callThrough();
_converse.connection._dataRecv(mock.createRequest(stanza));
await u.waitUntil(() => stanza_utils.parseMUCMessage.calls.count() === 1);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
expect(view.el.querySelectorAll('.chat-msg__receipt').length).toBe(0);
done();
}));
it("can cause a chat marker to be returned",
mock.initConverse(
['rosterGroupsFetched'], {},
async function (done, _converse) {
await mock.waitForRoster(_converse, 'current');
const muc_jid = 'lounge@montague.lit';
await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
const view = _converse.api.chatviews.get(muc_jid);
const textarea = view.el.querySelector('textarea.chat-textarea');
textarea.value = 'But soft, what light through yonder airlock breaks?';
view.onKeyDown({
target: textarea,
preventDefault: function preventDefault () {},
keyCode: 13 // Enter
});
await new Promise(resolve => view.model.messages.once('rendered', resolve));
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
expect(view.el.querySelector('.chat-msg .chat-msg__body').textContent.trim())
.toBe("But soft, what light through yonder airlock breaks?");
const msg_obj = view.model.messages.at(0);
let stanza = u.toStanza(`
<message xml:lang="en" to="romeo@montague.lit/orchard"
from="lounge@montague.lit/some1" type="groupchat" xmlns="jabber:client">
<received xmlns="urn:xmpp:chat-markers:0" id="${msg_obj.get('msgid')}"/>
</message>`);
const stanza_utils = converse.env.stanza_utils;
spyOn(stanza_utils, "getChatMarker").and.callThrough();
_converse.connection._dataRecv(mock.createRequest(stanza));
await u.waitUntil(() => stanza_utils.getChatMarker.calls.count() === 1);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
expect(view.el.querySelectorAll('.chat-msg__receipt').length).toBe(0);
stanza = u.toStanza(`
<message xml:lang="en" to="romeo@montague.lit/orchard"
from="lounge@montague.lit/some1" type="groupchat" xmlns="jabber:client">
<displayed xmlns="urn:xmpp:chat-markers:0" id="${msg_obj.get('msgid')}"/>
</message>`);
_converse.connection._dataRecv(mock.createRequest(stanza));
await u.waitUntil(() => stanza_utils.getChatMarker.calls.count() === 2);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
expect(view.el.querySelectorAll('.chat-msg__receipt').length).toBe(0);
stanza = u.toStanza(`
<message xml:lang="en" to="romeo@montague.lit/orchard"
from="lounge@montague.lit/some1" type="groupchat" xmlns="jabber:client">
<acknowledged xmlns="urn:xmpp:chat-markers:0" id="${msg_obj.get('msgid')}"/>
</message>`);
_converse.connection._dataRecv(mock.createRequest(stanza));
await u.waitUntil(() => stanza_utils.getChatMarker.calls.count() === 3);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
expect(view.el.querySelectorAll('.chat-msg__receipt').length).toBe(0);
stanza = u.toStanza(`
<message xml:lang="en" to="romeo@montague.lit/orchard"
from="lounge@montague.lit/some1" type="groupchat" xmlns="jabber:client">
<body>'tis I!</body>
<markable xmlns="urn:xmpp:chat-markers:0"/>
</message>`);
_converse.connection._dataRecv(mock.createRequest(stanza));
await u.waitUntil(() => stanza_utils.getChatMarker.calls.count() === 4);
await u.waitUntil(() => view.el.querySelectorAll('.chat-msg').length === 2);
expect(view.el.querySelectorAll('.chat-msg__receipt').length).toBe(0);
done();
}));
});

View File

@ -1,119 +0,0 @@
/*global mock */
const _ = converse.env._,
$iq = converse.env.$iq,
Strophe = converse.env.Strophe,
sizzle = converse.env.sizzle,
u = converse.env.utils;
describe("Chatrooms", function () {
describe("The /register commmand", function () {
it("allows you to register your nickname in a room",
mock.initConverse(
['rosterGroupsFetched', 'chatBoxesFetched'], {'auto_register_muc_nickname': true},
async function (done, _converse) {
const muc_jid = 'coven@chat.shakespeare.lit';
await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo')
const view = _converse.chatboxviews.get(muc_jid);
const textarea = view.el.querySelector('.chat-textarea')
textarea.value = '/register';
view.onKeyDown({
target: textarea,
preventDefault: function preventDefault () {},
keyCode: 13
});
let stanza = await u.waitUntil(() => _.filter(
_converse.connection.IQ_stanzas,
iq => sizzle(`iq[to="${muc_jid}"][type="get"] query[xmlns="jabber:iq:register"]`, iq).length
).pop());
expect(Strophe.serialize(stanza))
.toBe(`<iq from="romeo@montague.lit/orchard" id="${stanza.getAttribute('id')}" to="coven@chat.shakespeare.lit" `+
`type="get" xmlns="jabber:client">`+
`<query xmlns="jabber:iq:register"/></iq>`);
const result = $iq({
'from': view.model.get('jid'),
'id': stanza.getAttribute('id'),
'to': _converse.bare_jid,
'type': 'result',
}).c('query', {'type': 'jabber:iq:register'})
.c('x', {'xmlns': 'jabber:x:data', 'type': 'form'})
.c('field', {
'label': 'Desired Nickname',
'type': 'text-single',
'var': 'muc#register_roomnick'
}).c('required');
_converse.connection._dataRecv(mock.createRequest(result));
stanza = await u.waitUntil(() => _.filter(
_converse.connection.IQ_stanzas,
iq => sizzle(`iq[to="${muc_jid}"][type="set"] query[xmlns="jabber:iq:register"]`, iq).length
).pop());
expect(Strophe.serialize(stanza)).toBe(
`<iq from="romeo@montague.lit/orchard" id="${stanza.getAttribute('id')}" to="coven@chat.shakespeare.lit" type="set" xmlns="jabber:client">`+
`<query xmlns="jabber:iq:register">`+
`<x type="submit" xmlns="jabber:x:data">`+
`<field var="FORM_TYPE"><value>http://jabber.org/protocol/muc#register</value></field>`+
`<field var="muc#register_roomnick"><value>romeo</value></field>`+
`</x>`+
`</query>`+
`</iq>`);
done();
}));
});
describe("The auto_register_muc_nickname option", function () {
it("allows you to automatically register your nickname when joining a room",
mock.initConverse(
['rosterGroupsFetched', 'chatBoxesFetched'], {'auto_register_muc_nickname': true},
async function (done, _converse) {
const muc_jid = 'coven@chat.shakespeare.lit';
await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
const view = _converse.chatboxviews.get(muc_jid);
let stanza = await u.waitUntil(() => _.filter(
_converse.connection.IQ_stanzas,
iq => sizzle(`iq[to="coven@chat.shakespeare.lit"][type="get"] query[xmlns="jabber:iq:register"]`, iq).length
).pop());
expect(Strophe.serialize(stanza))
.toBe(`<iq from="romeo@montague.lit/orchard" id="${stanza.getAttribute('id')}" to="coven@chat.shakespeare.lit" `+
`type="get" xmlns="jabber:client">`+
`<query xmlns="jabber:iq:register"/></iq>`);
const result = $iq({
'from': view.model.get('jid'),
'id': stanza.getAttribute('id'),
'to': _converse.bare_jid,
'type': 'result',
}).c('query', {'type': 'jabber:iq:register'})
.c('x', {'xmlns': 'jabber:x:data', 'type': 'form'})
.c('field', {
'label': 'Desired Nickname',
'type': 'text-single',
'var': 'muc#register_roomnick'
}).c('required');
_converse.connection._dataRecv(mock.createRequest(result));
stanza = await u.waitUntil(() => _.filter(
_converse.connection.IQ_stanzas,
iq => sizzle(`iq[to="coven@chat.shakespeare.lit"][type="set"] query[xmlns="jabber:iq:register"]`, iq).length
).pop());
expect(Strophe.serialize(stanza)).toBe(
`<iq from="romeo@montague.lit/orchard" id="${stanza.getAttribute('id')}" to="coven@chat.shakespeare.lit" type="set" xmlns="jabber:client">`+
`<query xmlns="jabber:iq:register">`+
`<x type="submit" xmlns="jabber:x:data">`+
`<field var="FORM_TYPE"><value>http://jabber.org/protocol/muc#register</value></field>`+
`<field var="muc#register_roomnick"><value>romeo</value></field>`+
`</x>`+
`</query>`+
`</iq>`);
done();
}));
});
});

View File

@ -1,246 +0,0 @@
import "./autocomplete.js"
import log from "@converse/headless/log";
import sizzle from "sizzle";
import { CustomElement } from './element.js';
import { __ } from '../i18n';
import { api, converse } from "@converse/headless/converse-core";
import { html } from "lit-html";
import { unsafeHTML } from 'lit-html/directives/unsafe-html.js';
const { Strophe, $iq } = converse.env;
const u = converse.env.utils;
const tpl_command_form = (o, command) => {
const i18n_hide = __('Hide');
const i18n_run = __('Execute');
return html`
<form @submit=${o.runCommand}>
${ command.alert ? html`<div class="alert alert-${command.alert_type}" role="alert">${command.alert}</div>` : '' }
<fieldset class="form-group">
<input type="hidden" name="command_node" value="${command.node}"/>
<input type="hidden" name="command_jid" value="${command.jid}"/>
<p class="form-help">${command.instructions}</p>
<!-- Fields are generated internally, with xForm2webForm -->
${ command.fields.map(field => unsafeHTML(field)) }
</fieldset>
<fieldset>
<input type="submit" class="btn btn-primary" value="${i18n_run}">
<input type="button" class="btn btn-secondary button-cancel" value="${i18n_hide}" @click=${o.hideCommandForm}>
</fieldset>
</form>
`;
}
const tpl_command = (o, command) => html`
<li class="room-item list-group-item">
<div class="available-chatroom d-flex flex-row">
<a class="open-room available-room w-100"
@click=${o.toggleCommandForm}
data-command-node="${command.node}"
data-command-jid="${command.jid}"
data-command-name="${command.name}"
title="${command.name}"
href="#">${command.name || command.jid}</a>
</div>
${ command.node === o.showform ? tpl_command_form(o, command) : '' }
</li>
`;
async function getAutoCompleteList () {
const models = [...(await api.rooms.get()), ...(await api.contacts.get())];
const jids = [...new Set(models.map(o => Strophe.getDomainFromJid(o.get('jid'))))];
return jids;
}
const tpl_adhoc = (o) => {
const i18n_choose_service = __('On which entity do you want to run commands?');
const i18n_choose_service_instructions = __(
'Certain XMPP services and entities allow privileged users to execute ad-hoc commands on them.');
const i18n_commands_found = __('Commands found');
const i18n_fetch_commands = __('List available commands');
const i18n_jid_placeholder = __('XMPP Address');
const i18n_no_commands_found = __('No commands found');
return html`
${ o.alert ? html`<div class="alert alert-${o.alert_type}" role="alert">${o.alert}</div>` : '' }
<form class="converse-form" @submit=${o.fetchCommands}>
<fieldset class="form-group">
<label>
${i18n_choose_service}
<p class="form-help">${i18n_choose_service_instructions}</p>
<converse-autocomplete
.getAutoCompleteList="${getAutoCompleteList}"
placeholder="${i18n_jid_placeholder}"
name="jid"/>
</label>
</fieldset>
<fieldset class="form-group">
<input type="submit" class="btn btn-primary" value="${i18n_fetch_commands}">
</fieldset>
${ o.view === 'list-commands' ? html`
<fieldset class="form-group">
<ul class="list-group">
<li class="list-group-item active">${ o.commands.length ? i18n_commands_found : i18n_no_commands_found }:</li>
${ o.commands.map(cmd => tpl_command(o, cmd)) }
</ul>
</fieldset>`
: '' }
</form>
`;
}
async function fetchCommandForm (command) {
const node = command.node;
const jid = command.jid;
const stanza = $iq({
'type': 'set',
'to': jid
}).c('command', {
'xmlns': Strophe.NS.ADHOC,
'node': node,
'action': 'execute'
});
try {
const iq = await api.sendIQ(stanza);
const cmd_el = sizzle(`command[xmlns="${Strophe.NS.ADHOC}"]`, iq).pop();
command.sessionid = cmd_el.getAttribute('sessionid');
command.instructions = sizzle('x[type="form"][xmlns="jabber:x:data"] instructions', cmd_el).pop()?.textContent;
command.fields = sizzle('x[type="form"][xmlns="jabber:x:data"] field', cmd_el)
.map(f => u.xForm2webForm(f, cmd_el));
} catch (e) {
if (e === null) {
log.error(`Error: timeout while trying to execute command for ${jid}`);
} else {
log.error(`Error while trying to execute command for ${jid}`);
log.error(e);
}
command.fields = [];
}
}
export default class AdHocCommands extends CustomElement {
static get properties () {
return {
'alert': { type: String },
'alert_type': { type: String },
'nonce': { type: String }, // Used to force re-rendering
'showform': { type: String },
'view': { type: String },
}
}
constructor () {
super();
this.view = 'choose-service';
this.showform = '';
this.commands = [];
}
render () {
return tpl_adhoc({
'alert': this.alert,
'alert_type': this.alert_type,
'commands': this.commands,
'fetchCommands': ev => this.fetchCommands(ev),
'hideCommandForm': ev => this.hideCommandForm(ev),
'runCommand': ev => this.runCommand(ev),
'showform': this.showform,
'toggleCommandForm': ev => this.toggleCommandForm(ev),
'view': this.view,
});
}
async fetchCommands (ev) {
ev.preventDefault();
delete this.alert_type;
delete this.alert;
const form_data = new FormData(ev.target);
const jid = form_data.get('jid').trim();
let supported;
try {
supported = await api.disco.supports(Strophe.NS.ADHOC, jid)
} catch (e) {
log.error(e);
}
if (supported) {
try {
this.commands = await api.adhoc.getCommands(jid);
this.view = 'list-commands';
} catch (e) {
log.error(e);
this.alert_type = 'danger';
this.alert = __('Sorry, an error occurred while looking for commands on that entity.');
this.commands = [];
log.error(e);
return;
}
} else {
this.alert_type = 'danger';
this.alert = __("The specified entity doesn't support ad-hoc commands");
}
}
async toggleCommandForm (ev) {
ev.preventDefault();
const node = ev.target.getAttribute('data-command-node');
const cmd = this.commands.filter(c => c.node === node)[0];
this.showform !== node && await fetchCommandForm(cmd);
this.showform = node;
}
hideCommandForm (ev) {
ev.preventDefault();
this.showform = ''
}
async runCommand (ev) {
ev.preventDefault();
const form_data = new FormData(ev.target);
const jid = form_data.get('command_jid').trim();
const node = form_data.get('command_node').trim();
const cmd = this.commands.filter(c => c.node === node)[0];
const inputs = sizzle(':input:not([type=button]):not([type=submit])', ev.target);
const config_array = inputs
.filter(i => !['command_jid', 'command_node'].includes(i.getAttribute('name')))
.map(u.webForm2xForm)
.filter(n => n);
const iq = $iq({to: jid, type: "set"})
.c("command", {
'sessionid': cmd.sessionid,
'node': cmd.node,
'xmlns': Strophe.NS.ADHOC
}).c("x", {xmlns: Strophe.NS.XFORM, type: "submit"});
config_array.forEach(node => iq.cnode(node).up());
let result;
try {
result = await api.sendIQ(iq);
} catch (e) {
cmd.alert_type = 'danger';
cmd.alert = __('Sorry, an error occurred while trying to execute the command. See the developer console for details');
log.error('Error while trying to execute an ad-hoc command');
log.error(e);
}
if (result) {
cmd.alert = result.querySelector('note')?.textContent;
} else {
cmd.alert = 'Done';
}
cmd.alert_type = 'primary';
this.nonce = u.getUniqueId();
}
}
api.elements.define('converse-adhoc-commands', AdHocCommands);

View File

@ -1,73 +0,0 @@
import { AutoComplete, FILTER_CONTAINS, FILTER_STARTSWITH } from "../converse-autocomplete.js";
import { CustomElement } from './element.js';
import { html } from 'lit-element';
import { api } from "@converse/headless/converse-core";
export default class AutoCompleteComponent extends CustomElement {
static get properties () {
return {
'getAutoCompleteList': { type: Function },
'auto_evaluate': { type: Boolean },
'auto_first': { type: Boolean }, // Should the first element be automatically selected?
'filter': { type: String },
'include_triggers': { type: String },
'min_chars': { type: Number },
'name': { type: String },
'placeholder': { type: String },
'triggers': { type: String },
}
}
constructor () {
super();
this.auto_evaluate = true; // Should evaluation happen automatically without any particular key as trigger?
this.auto_first = false; // Should the first element be automatically selected?
this.filter = 'contains';
this.include_triggers = ''; // Space separated chars which should be included in the returned value
this.match_current_word = false; // Match only the current word, otherwise all input is matched
this.max_items = 10;
this.min_chars = 1;
this.triggers = ''; // String of space separated chars
}
render () {
return html`
<div class="suggestion-box suggestion-box__name">
<ul class="suggestion-box__results suggestion-box__results--above" hidden=""></ul>
<input type="text" name="${this.name}"
autocomplete="off"
@keydown=${this.onKeyDown}
@keyup=${this.onKeyUp}
class="form-control suggestion-box__input"
placeholder="${this.placeholder}"/>
<span class="suggestion-box__additions visually-hidden" role="status" aria-live="assertive" aria-relevant="additions"></span>
</div>
`;
}
firstUpdated () {
this.auto_complete = new AutoComplete(this.firstElementChild, {
'ac_triggers': this.triggers.split(' '),
'auto_evaluate': this.auto_evaluate,
'auto_first': this.auto_first,
'filter': this.filter == 'contains' ? FILTER_CONTAINS : FILTER_STARTSWITH,
'include_triggers': [],
'list': () => this.getAutoCompleteList(),
'match_current_word': true,
'max_items': this.max_items,
'min_chars': this.min_chars,
});
this.auto_complete.on('suggestion-box-selectcomplete', () => (this.auto_completing = false));
}
onKeyDown (ev) {
this.auto_complete.onKeyDown(ev);
}
onKeyUp (ev) {
this.auto_complete.evaluate(ev);
}
}
api.elements.define('converse-autocomplete', AutoCompleteComponent);

View File

@ -1,42 +0,0 @@
import { api } from "@converse/headless/converse-core";
import { component } from 'haunted';
import { html } from 'lit-html';
export const ConverseBrandHeading = (o) => {
const is_fullscreen = api.settings.get('view_mode') === 'fullscreen';
return html`
<a class="brand-heading" href="https://conversejs.org" target="_blank" rel="noopener">
<span class="brand-name-wrapper ${is_fullscreen ? 'brand-name-wrapper--fullscreen' : '' }">
<svg class="converse-svg-logo"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 364 364">
<title>Converse</title>
<g class="cls-1" id="g904">
<g data-name="Layer 2">
<g data-name="Layer 7">
<path
class="cls-3"
d="M221.46,103.71c0,18.83-29.36,18.83-29.12,0C192.1,84.88,221.46,84.88,221.46,103.71Z" />
<path
class="cls-4"
d="M179.9,4.15A175.48,175.48,0,1,0,355.38,179.63,175.48,175.48,0,0,0,179.9,4.15Zm-40.79,264.5c-.23-17.82,27.58-17.82,27.58,0S138.88,286.48,139.11,268.65ZM218.6,168.24A79.65,79.65,0,0,1,205.15,174a12.76,12.76,0,0,0-6.29,4.65L167.54,222a1.36,1.36,0,0,1-2.46-.8v-35.8a2.58,2.58,0,0,0-3.06-2.53c-15.43,3-30.23,7.7-42.73,19.94-38.8,38-29.42,105.69,16.09,133.16a162.25,162.25,0,0,1-91.47-67.27C-3.86,182.26,34.5,47.25,138.37,25.66c46.89-9.75,118.25,5.16,123.73,62.83C265.15,120.64,246.56,152.89,218.6,168.24Z" />
</g>
</g>
</g>
</svg>
<span class="brand-name">
<span class="brand-name__text">converse<span class="subdued">.js</span></span>
${ is_fullscreen ? html`<p class="byline">messaging freedom</p>` : '' }
</span>
</span>
</a>
${ is_fullscreen ? html`
<p class="brand-subtitle">${o.version_name}</p>
<p class="brand-subtitle"><a target="_blank" rel="nofollow" href="https://conversejs.org">Open Source</a> XMPP chat client brought to you by <a target="_blank" rel="nofollow" href="https://opkode.com">Opkode</a> </p>
<p class="brand-subtitle"><a target="_blank" rel="nofollow" href="https://hosted.weblate.org/projects/conversejs/#languages">Translate</a> it into your own language</p>` : '' }
`;
}
api.elements.define('converse-brand-heading', component(ConverseBrandHeading, {'useShadowDOM': false}));

View File

@ -1,30 +0,0 @@
import "./message-history";
import xss from "xss/dist/xss";
import { CustomElement } from './element.js';
import { html } from 'lit-element';
import { unsafeHTML } from 'lit-html/directives/unsafe-html.js';
import { api } from "@converse/headless/converse-core";
export default class ChatContent extends CustomElement {
static get properties () {
return {
chatview: { type: Object},
messages: { type: Array},
notifications: { type: String }
}
}
render () {
const notifications = xss.filterXSS(this.notifications, {'whiteList': {}});
return html`
<converse-message-history
.chatview=${this.chatview}
.messages=${this.messages}>
</converse-message-history>
<div class="chat-content__notifications">${unsafeHTML(notifications)}</div>
`;
}
}
api.elements.define('converse-chat-content', ChatContent);

View File

@ -1,19 +0,0 @@
import { api, converse } from "@converse/headless/converse-core";
/**
* `converse-root` is an optional custom element which can be used to
* declaratively insert the Converse UI into the DOM.
*
* It can be inserted into the DOM before or after Converse has loaded or been
* initialized.
*/
class ConverseRoot extends HTMLElement {
async connectedCallback () {
await api.waitUntil('initialized');
converse.insertInto(this);
}
}
customElements.define('converse-root', ConverseRoot);

View File

@ -1,112 +0,0 @@
import DOMNavigator from "../dom-navigator";
import { CustomElement } from './element.js';
import { converse, api } from "@converse/headless/converse-core";
import { html } from 'lit-element';
import { until } from 'lit-html/directives/until.js';
const u = converse.env.utils;
export class BaseDropdown extends CustomElement {
firstUpdated () {
this.menu = this.querySelector('.dropdown-menu');
this.dropdown = this.firstElementChild;
this.button = this.dropdown.querySelector('button');
this.dropdown.addEventListener('click', ev => this.toggleMenu(ev));
this.dropdown.addEventListener('keyup', ev => this.handleKeyUp(ev));
document.addEventListener('click', ev => !this.contains(ev.composedPath()[0]) && this.hideMenu(ev));
}
hideMenu () {
u.removeClass('show', this.menu);
this.button?.setAttribute('aria-expanded', false);
this.button?.blur();
}
showMenu () {
u.addClass('show', this.menu);
this.button.setAttribute('aria-expanded', true);
}
toggleMenu (ev) {
ev.preventDefault();
if (u.hasClass('show', this.menu)) {
this.hideMenu();
} else {
this.showMenu();
}
}
handleKeyUp (ev) {
if (ev.keyCode === converse.keycodes.ESCAPE) {
this.hideMenu();
} else if (ev.keyCode === converse.keycodes.DOWN_ARROW && this.navigator && !this.navigator.enabled) {
this.enableArrowNavigation(ev);
}
}
}
export default class DropdownList extends BaseDropdown {
static get properties () {
return {
'icon_classes': { type: String },
'items': { type: Array }
}
}
render () {
const icon_classes = this.icon_classes || "fa fa-bars";
return html`
<div class="dropleft">
<button type="button" class="btn btn--transparent btn--standalone" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="${icon_classes} only-icon"></i>
</button>
<div class="dropdown-menu">
${ this.items.map(b => until(b, '')) }
</div>
</div>
`;
}
hideMenu () {
super.hideMenu();
this.navigator.disable();
}
firstUpdated () {
super.firstUpdated();
this.initArrowNavigation();
}
initArrowNavigation () {
if (!this.navigator) {
const options = {
'selector': '.dropdown-item',
'onSelected': el => el.focus()
};
this.navigator = new DOMNavigator(this.menu, options);
}
}
enableArrowNavigation (ev) {
if (ev) {
ev.preventDefault();
ev.stopPropagation();
}
this.navigator.enable();
this.navigator.select(this.menu.firstElementChild);
}
handleKeyUp (ev) {
super.handleKeyUp(ev);
if (ev.keyCode === converse.keycodes.DOWN_ARROW && !this.navigator.enabled) {
this.enableArrowNavigation(ev);
}
}
}
api.elements.define('converse-dropdown', DropdownList);

View File

@ -1,20 +0,0 @@
import { CustomElement } from './element.js';
import { html } from "lit-element";
import { unsafeSVG } from 'lit-html/directives/unsafe-svg.js';
import { until } from 'lit-html/directives/until.js';
export class FontAwesome extends CustomElement {
constructor () {
super();
const promise = import(/*webpackChunkName: "icons" */ '../../images/icons.svg');
this.data = promise.then(d => html`${unsafeSVG(d.default())}`);
}
render () { // eslint-disable-line class-methods-use-this
return html`${until(this.data, '')}`;
}
}
window.customElements.define('converse-fontawesome', FontAwesome);

Some files were not shown because too many files have changed in this diff Show More