Compare commits

...

708 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
626 changed files with 129092 additions and 116040 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": [],
"extends": ["eslint:recommended"],
"plugins": ["@typescript-eslint"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended"
],
"globals": {
"Uint8Array": true,
"Promise": true,

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'

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 @@
v14.17.0
v18.15.0

View File

@ -1,5 +1,4 @@
{
"arrowParens": "avoid",
"printWidth": 120,
"quoteProps": "preserve",
"singleQuote": 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,5 +1,179 @@
# 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
@ -13,7 +187,7 @@
- #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)
- #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'`.
@ -183,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: 8.0.0
* Version: 10.1.6
*
* Copyright: JC Brand 2013-2018
* Except for 3rd party dependencies.

View File

@ -1,17 +1,13 @@
# 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
ESLINT ?= ./node_modules/.bin/eslint
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
@ -62,13 +58,14 @@ 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=8.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 $$?;
@ -85,9 +82,9 @@ po:
########################################################################
## Release management
.PHONY: release
release:
$(SED) -i '/^_converse.VERSION_NAME =/s/=.*/= "v$(VERSION)";/' src/headless/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
@ -102,19 +99,33 @@ release:
make pot
make po
make dist
npm pack
cd src/headless && 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
@ -126,12 +137,9 @@ nvm: ${NVM_DIR}/nvm.sh
node: .nvmrc
. $(HOME)/.nvm/nvm.sh && nvm install
package-lock.json: package.json
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
.PHONY: clean
clean:
npm run clean
@ -148,11 +156,14 @@ 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 src/shared/styles/website.scss
$(SASS) --load-path=$(BOOTSTRAP) src/shared/styles/website.scss $@
@ -186,12 +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
@ -200,23 +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
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
@ -224,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
@ -245,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/*.js src/*.js src/**/*.js src/headless/**/*.js src/shared/**/*.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

@ -6,7 +6,7 @@
[![XMPP Chat](https://conference.conversejs.org/muc_badge/discuss@conference.conversejs.org)](https://inverse.chat/#converse/room?jid=discuss@conference.conversejs.org)
[![Travis](https://api.travis-ci.com/conversejs/converse.js.png?branch=master)](https://travis-ci.com/conversejs/converse.js)
[![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)
@ -46,7 +46,11 @@ In overlay mode, Converse appears overlayed chats on top of the website.
In fullpage mode, Converse behaves like a single-page app that covers the whole browser viewport.
![Screenshot of Converse in fullpage mode](https://conversejs.org/screenshots/Converse-fullscreen.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
@ -114,14 +118,20 @@ In embedded mode, Converse can be embedded into an element in the DOM.
## 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)
@ -156,14 +166,19 @@ We accept donations via [Patreon](https://www.patreon.com/jcbrand) and [Liberapa
## 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://www.codefirst.co.uk?utm_source=conversejs" target="_blank" rel="noopener">
<img alt="Codefirst" src="https://raw.githubusercontent.com/conversejs/converse.js/541613d1fea8aef364af00180f60e959162e5e4b/logo/codefirst.png" width="200">
<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>
@ -171,13 +186,3 @@ We accept donations via [Patreon](https://www.patreon.com/jcbrand) and [Liberapa
<img alt="KeyCDN" src="https://raw.githubusercontent.com/conversejs/converse.js/541613d1fea8aef364af00180f60e959162e5e4b/logo/keycdn.png" width="200">
</a>
</p>
<p>
<a href="https://www.pluckeye.net/?utm_source=conversejs" target="_blank" rel="noopener">
<img alt="Pluckeye" src="https://raw.githubusercontent.com/conversejs/converse.js/master/logo/pluckeye.svg" width="200">
</a>
</p>
<p>
<a href="https://originalenergie.de/?utm_source=conversejs" target="_blank" rel="noopener">
<img alt="Original Energie" src="https://raw.githubusercontent.com/conversejs/converse.js/master/logo/originalenergie-black.png" width="200">
</a>
</p>

View File

@ -1,20 +1,18 @@
# Release checklist
1. Check that weblate translations are all merged in
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 release VERSION=8.0.1`
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 8.0.1"`
7. `git tag -s v8.0.1 -m "Release 8.0.1"`
8. Run `git push && git push origin v8.0.1`
9. Update https://conversejs.org
* `cd /home/conversejs/converse.js`
* `git clone --branch v8.0.1 git@github.com:conversejs/converse.js.git 8.0.1`
* `cd 8.0.1 && ASSET_PATH=https://cdn.conversejs.org/8.0.1/dist/ make dist && make doc`
* `cd .. && git pull && ASSET_PATH=https://cdn.conversejs.org/dist/ make dist && make doc`
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
11. Run `npm pack && cd src/headless && npm pack` to generate tarballs. Then upload them to the Github release page
12. Run `npm publish && cd src/headless/ && npm publish`
13. Update the repository on weblate
14. Decide on next release number and run `make postrelease VERSION=7.0.3`
* Upload tar files
11. Update https://conversejs.org
* `cd /home/conversejs/converse.js`
* `make deploy VERSION=10.1.6`
12. Update the repository on weblate
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;
});

View File

@ -1,5 +1,5 @@
<?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#" xml:lang="en">
<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>
@ -9,6 +9,11 @@
<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"/>
@ -87,6 +92,13 @@
<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"/>
@ -209,6 +221,11 @@
<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"/>
@ -238,6 +255,11 @@
<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"/>

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,9 +10,9 @@
<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/website.css"></script>
<script src="dist/converse.js"></script>
</head>
@ -28,19 +28,22 @@
});
converse.initialize({
i18n: 'af',
theme: 'dracula',
auto_away: 300,
enable_smacks: true,
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'],
theme: 'concord',
view_mode: 'fullscreen',
websocket_url: 'wss://conversejs.org/xmpp-websocket',
// websocket_url: 'ws://chat.example.org:5380/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

@ -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,24 +2,20 @@
<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: 2.5em" 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://www.pluckeye.net/?utm_source=conversejs" target="_blank" rel="noopener">
<img style="width: 8em" src="/logo/pluckeye.svg" alt="Pluckeye">
<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://originalenergie.de/?utm_source=conversejs" target="_blank" rel="noopener">
<img style="width: 9em" src="/logo/originalenergie-black.png" alt="Original Energie">
<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>

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 = '8.0.0'
version = '10.1.6'
# The full version, including alpha/beta/rc tags.
release = '8.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
@ -192,13 +217,6 @@ allow_message_styling
Determines wehether support for XEP-0393 Message Styling hints are enabled or not.
allow_muc
---------
* Default: ``true``
Allow multi-user chat (muc) in chatrooms. Setting this to ``false`` will remove
the ``Chatrooms`` tab from the control box.
allow_muc_invitations
---------------------
@ -389,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
---------
@ -676,7 +693,7 @@ appear in another.
.. code-block:: javascript
converse.initialize({
connection_options: { 'worker': true }
connection_options: { worker: '/dist/shared-connection-worker.js' }
});
@ -735,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
--------------
@ -751,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
-------------
@ -793,28 +810,6 @@ domain_placeholder
The placeholder text shown in the domain input on the registration form.
embed_audio
-----------
* Default: ``true``
If set to ``false``, audio files won't be embedded in chats, instead only their links will be shown.
It also accepts an array strings of whitelisted domain names to only render audio files that belong to those domains.
E.g. ``['conversejs.org']``
embed_videos
------------
* Default: ``true``
If set to ``false``, videos 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 videos that belong to those domains.
E.g. ``['imgur.com', 'imgbb.com']``
emoji_categories
----------------
@ -906,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.
@ -930,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
------------
@ -966,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
@ -1206,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
-------------
@ -1449,11 +1406,10 @@ Example:
muc_show_info_messages
----------------------
* 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:
* 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:
.. 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'];
@ -1475,6 +1431,7 @@ It is recommended to use the aforementioned Converse object in the following fas
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,
@ -1504,19 +1461,6 @@ 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>`_)
and the nickname form at the bottom.
muc_show_ogp_unfurls
--------------------
* Default: ``true``
Supports showing extra metadata (picture and description) for URLs contained in
groupchat messages.
The metadata must come from the MUC itself, metadata sent from participants
themselves will not be shown.
For Prosody XMPP server, `mod_ogp <https://modules.prosody.im/mod_ogp.html>`_ can be used.
muc_subscribe_to_rai
--------------------
@ -1723,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.
@ -1813,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
@ -1919,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
--------------------------
@ -1973,8 +2004,8 @@ 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.
E.g. ``['imgur.com', 'imgbb.com']``
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 ``[]``.
show_retraction_warning
@ -2052,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
-----------------
@ -2109,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.
@ -2214,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>
=============================
Starting up a dev environment
=============================
.. _`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
@ -80,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

@ -23,11 +23,10 @@ to fix a bug or to add new functionality.
.. toctree::
:maxdepth: 2
dependencies
style_guide
webserver
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

@ -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.
@ -180,11 +180,59 @@ The code for it could look something like this:
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,40 +308,6 @@ For example:
Object.assign(_converse.ChatBoxView.prototype, { doSomething });
Overriding a template
~~~~~~~~~~~~~~~~~~~~~
Converse uses `lit-html <https://lit-html.polymer-project.org/guide>`_
templates.
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
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).
.. _`dependencies`:
@ -436,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>`_.
@ -511,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');
@ -526,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/8.0.0/dist/converse.min.js
* https://cdn.conversejs.org/8.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/8.0.0/dist/converse.min.css">
<script src="https://cdn.conversejs.org/8.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

@ -11,19 +11,109 @@ Theming
Setting up your environment
===========================
In order to theme Converse, you first need to set up a :ref:`development` environment
and then you'll also want to follow the guide to :ref:`webserver`.
In order to theme Converse, you first need to follow the steps for :ref:`setup_dev_environment`, including :ref:`webserver`.
Creating a custom theme
=======================
Converse can be themed via CSS custom properties (aka CSS variables) and it has
some themes available in its source repository.
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.
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>`_.
The native theme files can be found in `shared/styles/themes <https://github.com/conversejs/converse.js/tree/master/src/shared/styles/themes>`_.
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" });
.. code-block:: html
<converse-root class="conversejs theme-dracula"></converse-root>
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
=================
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).
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
Modifying the HTML templates of Converse
========================================
Converse uses `lit-html <https://lit-html.polymer-project.org/guide>`_ as HTML
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.
Some top-level templates are found in the ``./src/templates`` directory, but
usually the templates that are relevant to a specific plugin will be find
inside that plugin's subdirectory.
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>`_.
@ -53,19 +143,3 @@ two of my own custom templates.
'./templates/message.js': path.resolve(__dirname, 'path/to/my/custom/chat_message.js'),
}
}
Modifying the CSS
=================
The CSS files are generated from `Sass <http://sass-lang.com>`_ files that end in ``.scss`` and
which are distributed throughout the source code.
Similarly to the template files, 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>`_.
To generate the CSS you can run::
make css

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

@ -1,51 +0,0 @@
.. raw:: html
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/webserver.rst">Edit me on GitHub</a></div>
.. _`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.
If you're running ``make devserver``, you need to open http://localhost:8080
instead.
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``.

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

@ -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" />
@ -143,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>
@ -238,12 +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>
<li><a href="https://www.pluckeye.net/?utm_source=conversejs" target="_blank" rel="noopener"><img style="width: 10em" src="/logo/pluckeye.svg" alt="Pluckeye"></a></li>
<li><a href="https://originalenergie.de/?utm_source=conversejs" target="_blank" rel="noopener"><img style="width: 10em" src="/logo/originalenergie.png" alt="Original Energie"></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/8.0.0/css/font-awesome.min.css" />
<link type="text/css" rel="stylesheet" media="screen" href="https://cdn.conversejs.org/8.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/8.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/8.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/8.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,15 @@ 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",
@ -28,16 +29,21 @@ module.exports = function(config) {
{ 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' },
@ -63,22 +69,29 @@ module.exports = function(config) {
{ 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/mep.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/muclist.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' },
@ -86,11 +99,18 @@ module.exports = function(config) {
{ 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' },

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

View File

@ -1,85 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 14.0.0, SVG Export Plug-In -->
<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"
version="1.1"
x="0px"
y="0px"
width="686.18805"
height="191.18677"
viewBox="0 0 686.19 191.18677"
enable-background="new -42.099 -9.411 750 200"
xml:space="preserve"
id="svg2"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="pluckeye.svg"><metadata
id="metadata30"><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></dc:title></cc:Work></rdf:RDF></metadata><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1031"
id="namedview28"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:zoom="0.44533333"
inkscape:cx="-88.043686"
inkscape:cy="95.59337"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" /><defs
id="defs4" /><path
d="m 145.61875,146.43082 c 0,6.15645 -5.32372,11.48006 -11.48017,11.48006 -6.48901,0 -11.14739,-5.32361 -11.14739,-11.48006 V 38.952995 c 0,-6.322719 4.65838,-11.147401 11.14739,-11.147401 6.15545,0 11.48017,4.824682 11.48017,11.147401 z"
id="path6"
inkscape:connector-curvature="0" /><path
d="m 216.32874,77.884176 c 0,-6.155351 5.32372,-10.981066 11.48006,-10.981066 6.48901,0 10.98111,4.825715 10.98111,10.981066 v 68.546644 c 0,6.15645 -4.4921,11.48006 -10.98111,11.48006 -3.82665,0 -7.48702,-2.1633 -9.48304,-5.15733 -5.82367,3.3277 -12.64435,5.15733 -19.79881,5.15733 -22.79373,0 -41.26086,-18.46802 -41.26086,-41.09447 V 78.384203 c 0,-6.489043 4.99205,-11.48006 11.31378,-11.48006 6.32162,0 11.48006,4.991017 11.48006,11.48006 v 38.432207 c 0,10.14838 8.48503,17.96907 18.46702,17.96907 9.9821,0 17.80179,-7.81969 17.80179,-17.96907 z"
id="path8"
inkscape:connector-curvature="0" /><path
d="m 291.86761,157.91088 c -25.62148,0 -45.58657,-20.29776 -45.58657,-45.2549 0,-25.621434 19.96509,-45.75287 45.58657,-45.75287 7.32074,0 14.3087,1.663328 20.9631,4.991017 5.65739,3.162387 7.98608,10.482061 4.82466,15.972083 -3.3277,5.657379 -9.64932,7.986036 -15.30671,4.99205 -3.16142,-1.663328 -7.32074,-2.496025 -10.48205,-2.496025 -12.81074,0 -22.62745,9.650405 -22.62745,22.293745 0,12.1464 9.81571,21.79583 22.62745,21.79583 3.16131,0 7.32063,-0.83173 10.48205,-2.32869 5.65739,-2.66236 11.97901,-0.66634 15.30671,4.65838 3.16142,5.65739 0.83173,12.97813 -4.82466,16.30472 -6.6554,2.99503 -13.64236,4.82466 -20.9631,4.82466 z"
id="path10"
inkscape:connector-curvature="0" /><path
d="m 403.67318,141.27349 c 3.3277,5.65739 0.49906,12.1464 -4.65827,15.14043 -5.82378,3.3277 -12.97813,0.83162 -16.13844,-4.82466 l -25.95415,-34.93924 -7.65341,5.32372 v 24.45708 c 0,6.15645 -5.32361,11.48006 -11.48006,11.48006 -6.48801,0 -11.14628,-5.32361 -11.14628,-11.48006 V 38.952995 c 0,-6.322719 4.65827,-11.147401 11.14628,-11.147401 6.15645,0 11.48006,4.824682 11.48006,11.147401 v 54.570594 l 35.93725,-24.124454 c 4.99105,-3.993018 12.97702,-2.32969 16.13844,2.32969 3.82565,5.656346 2.32858,12.977064 -3.16242,16.803747 l -21.96111,14.974088 z"
id="path12"
inkscape:connector-curvature="0" /><path
d="m 472.39037,100.84431 c -2.66136,-4.824696 -6.82168,-8.152385 -12.31168,-10.148372 -1.99702,-0.832697 -3.99304,-0.832697 -5.99006,-0.832697 -12.1454,0 -22.46017,10.315729 -22.46017,22.461069 0,12.31179 10.31477,22.29378 22.46017,22.29378 3.16242,0 6.6554,-1.16429 9.98299,-2.66125 5.65739,-2.66236 13.14341,-0.66645 15.80577,4.82466 2.66136,5.32372 0.66534,12.81074 -4.82466,15.4731 -6.6554,3.49398 -14.3087,5.65739 -20.9641,5.65739 -25.12142,0 -45.58657,-20.63043 -45.58657,-45.58657 0,-25.289841 20.46515,-45.421277 45.58657,-45.421277 42.25987,1.496993 44.92123,39.264827 44.92123,45.421277 0,6.15534 -5.82378,11.64534 -11.81273,11.64534 h -32.60955 c -6.48801,0 -11.31367,-5.49 -11.31367,-11.64534 0,-6.82168 4.82566,-11.48008 11.31367,-11.48008 h 17.80279 z"
id="path14"
inkscape:connector-curvature="0" /><path
d="m 565.56464,78.384203 c 0,-6.322708 4.99205,-11.48006 11.31378,-11.48006 6.32162,0 11.31367,5.157352 11.31367,11.48006 v 79.527787 c 0,18.63341 -14.97404,33.27478 -33.60745,33.27478 h -7.98608 c -6.15534,0 -11.31267,-5.15733 -11.31267,-11.31267 0,-6.32273 5.15733,-11.14739 11.31267,-11.14739 h 7.98608 c 6.15534,0 10.98,-4.65838 10.98,-10.81472 v -4.15943 c -5.32361,2.66236 -11.31267,4.15943 -17.80168,4.15943 -22.79384,0 -41.26097,-18.46813 -41.26097,-41.09458 V 78.385236 c 0,-6.489043 4.99105,-11.48006 11.31278,-11.48006 6.32273,0 11.48006,4.991017 11.48006,11.48006 v 38.432174 c 0,10.14838 8.48503,17.96907 18.46702,17.96907 9.9831,0 17.80179,-7.81969 17.80179,-17.96907 V 78.384203 Z"
id="path16"
inkscape:connector-curvature="0" /><path
d="m 659.56953,100.84431 c -2.66125,-4.824696 -6.82168,-8.152385 -12.31168,-10.148372 -1.99702,-0.832697 -3.99304,-0.832697 -5.99006,-0.832697 -12.1454,0 -22.46006,10.315729 -22.46006,22.461069 0,12.31179 10.31466,22.29378 22.46006,22.29378 3.16242,0 6.6554,-1.16429 9.9831,-2.66125 5.65739,-2.66236 13.14341,-0.66645 15.80577,4.82466 2.66125,5.32372 0.66523,12.81074 -4.82477,15.4731 -6.65529,3.49398 -14.3087,5.65739 -20.9641,5.65739 -25.12142,0 -45.58657,-20.63043 -45.58657,-45.58657 0,-25.289841 20.46515,-45.421277 45.58657,-45.421277 42.25987,1.496993 44.92123,39.264827 44.92123,45.421277 0,6.15534 -5.82367,11.64534 -11.81273,11.64534 h -32.60955 c -6.48801,0 -11.31367,-5.49 -11.31367,-11.64534 0,-6.82168 4.82566,-11.48008 11.31367,-11.48008 h 17.80279 z"
id="path18"
inkscape:connector-curvature="0" /><path
d="m 93.208361,28.712678 -8.942715,23.461191 c 6.562397,8.976804 8.571824,20.980672 4.29883,32.190053 C 81.853305,101.97041 62.279755,110.7406 44.673268,104.02839 27.064715,97.318249 18.295567,77.742633 25.008803,60.135113 29.54008,48.246974 39.937435,40.398338 51.631359,38.612061 L 60.408772,15.588917 C 36.22336,14.027866 12.839646,28.187848 3.7502295,52.031304 -7.4219625,81.343067 7.2597485,114.11162 36.568415,125.28589 65.878123,136.45916 98.649821,121.77747 109.82302,92.467742 118.68414,69.22247 111.27043,43.811777 93.208361,28.712678 Z"
id="path20"
inkscape:connector-curvature="0"
style="fill:#09476b" /><path
d="m 84.968174,0.77392782 v 0 C 78.879979,-1.5464678 72.013835,1.5291407 69.691377,7.617335 L 57.064543,40.741327 c -2.322458,6.089228 0.75419,12.955371 6.843418,15.275764 v 0 c 6.087162,2.322459 12.954327,-0.753145 15.275753,-6.843406 L 91.810547,16.04969 C 94.131973,9.9614914 91.056369,3.0963883 84.968174,0.77392782 Z"
id="path22"
inkscape:connector-curvature="0"
style="fill:#09476b" /><path
d="m 22.705971,110.04938 c 0.004,-0.12185 0.01855,-0.2407 0.01855,-0.36466 V 74.236213 c 0,-6.515901 -5.106724,-11.835456 -11.361253,-11.835456 -6.2555605,0 -11.3622875,5.319555 -11.3622875,11.835456 v 35.449507 c 0,0.15195 0.01756,0.30068 0.02169,0.45152 -0.0021,0.12196 -0.01756,0.2407 -0.01756,0.36366 v 35.44952 c 0,6.51489 5.106728,11.8355 11.3612555,11.8355 6.254528,0 11.362285,-5.32061 11.362285,-11.8355 V 110.5009 c 0,-0.15295 -0.01655,-0.30068 -0.02277,-0.45152 z"
id="path24"
inkscape:connector-curvature="0"
style="fill:#09476b" /><path
d="m 52.570466,85.838189 v 0 c -6.11196,-2.32969 -9.17414,-9.165865 -6.843406,-15.27783 v 0 c 2.32969,-6.109888 9.164832,-9.173096 15.275753,-6.843406 v 0 c 6.111954,2.329689 9.175171,9.16381 6.844439,15.276797 v 0 c -2.32969,6.111954 -9.164832,9.174129 -15.276786,6.844439 z"
id="path26"
inkscape:connector-curvature="0" /></svg>

Before

Width:  |  Height:  |  Size: 8.2 KiB

View File

@ -2,7 +2,7 @@
"short_name": "Converse",
"name": "Converse Chat",
"description": "Messaging Freedom",
"version": "8.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/8.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/8.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>

52500
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,42 +1,46 @@
{
"name": "converse.js",
"version": "8.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": [
"*.js",
"*.json",
"CHANGES.md",
"LICENSE.txt",
"README.md",
"COPYRIGHT",
"dist/",
"docs/**/*.rst",
"docs/**/*.md",
"docs/**/*.rst",
"sass/**/*.scss",
"src/*.js",
"src/**/*.pot",
"src/**/*.po",
"src/**/*.js",
"src/**/*.html",
"src/**/*.svg",
"src/**/*.js",
"src/**/*.json",
"src/**/*.md",
"src/**/*.po",
"src/**/*.pot",
"src/**/*.scss",
"src/**/*.svg",
"src/**/*.txt",
"src/**/*.json"
"3rdparty/*.js"
],
"scripts": {
"serve": "webpack serve --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",
@ -63,56 +67,70 @@
"browser": "*"
},
"devDependencies": {
"@babel/cli": "^7.14.5",
"@babel/core": "^7.14.6",
"@babel/preset-env": "^7.14.7",
"@babel/cli": "^7.17.10",
"@babel/core": "^7.18.5",
"@babel/preset-env": "^7.18.2",
"@converse/headless": "file:src/headless",
"autoprefixer": "^9.8.6",
"babel-eslint": "^10.1.0",
"babel-loader": "^8.2.2",
"@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": "^5.3.0",
"copy-webpack-plugin": "^9.0.1",
"css-loader": "^5.2.7",
"eslint": "^7.32.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",
"file-loader": "^6.2.0",
"html-webpack-plugin": "^5.3.2",
"http-server": "^0.12.3",
"imports-loader": "^3.0.0",
"http-server": "^14.1.0",
"imports-loader": "^4.0.0",
"install": "^0.13.0",
"jsdoc": "^3.6.7",
"karma": "^6.3.4",
"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": "^4.0.1",
"karma-jasmine-html-reporter": "^1.7.0",
"karma-jasmine": "^5.0.0",
"karma-jasmine-html-reporter": "^2.0.0",
"karma-webpack": "^5.0.0",
"lerna": "^4.0.0",
"mini-css-extract-plugin": "^1.6.2",
"minimist": "^1.2.3",
"npm": "^7.19.1",
"po-loader": "^0.5.0",
"po2json": "^1.0.0-beta",
"postcss-clean": "^1.2.2",
"postcss-loader": "^6.1.1",
"prettierx": "^0.18.2",
"run-headless-chromium": "^0.1.1",
"sass": "^1.35.2",
"sass-loader": "^11.0.1",
"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",
"webpack": "^5.36.1",
"webpack-cli": "^4.7.2",
"webpack-dev-server": "^4.0.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": {
"@fortawesome/fontawesome-free": "5.14.0",
"@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.0.0-rc.2"
"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

@ -28,7 +28,7 @@ const converse = {
},
initialize (settings={}) {
converse.load(settings).initialize(settings);
return converse.load(settings).initialize(settings);
},
/**
@ -49,7 +49,7 @@ const converse = {
*
* @memberOf converse
* @method load
* @param {object} settings A map of configuration-settings that are needed at load time.
* @param { object } settings A map of configuration-settings that are needed at load time.
* @example
* converse.load({assets_path: '/path/to/assets/'});
*/
@ -57,7 +57,7 @@ const converse = {
if (settings.assets_path) {
__webpack_public_path__ = settings.assets_path; // eslint-disable-line no-undef
}
require('./converse.js');
require('./index.js');
Object.keys(plugins).forEach(name => converse.plugins.add(name, plugins[name]));
return converse;
}

2
src/headless/.npmignore Normal file
View File

@ -0,0 +1,2 @@
node_modules
tests

View File

@ -13,5 +13,5 @@ It's also installable with NPM/Yarn as [@converse/headless](https://www.npmjs.co
The main distribution of Converse relies on the headless build.
The file [src/headless/headless.js](https://github.com/jcbrand/converse.js/blob/master/src/headless/headless.js)
The file [src/headless/index.js](https://github.com/jcbrand/converse.js/blob/master/src/headless/index.js)
is used to determine which plugins are included in the build.

View File

@ -1,76 +0,0 @@
import log from '@converse/headless/log.js';
import { getAppSetting, extendAppSettings, updateAppSettings } from '@converse/headless/shared/settings';
/**
* This grouping allows access to the
* [configuration settings](/docs/html/configuration.html#configuration-settings)
* of Converse.
*
* @namespace _converse.api.settings
* @memberOf _converse.api
*/
export default {
/**
* Allows new configuration settings to be specified, or new default values for
* existing configuration settings to be specified.
*
* Note, calling this method *after* converse.initialize has been
* called will *not* change the initialization settings provided via
* `converse.initialize`.
*
* @method _converse.api.settings.extend
* @param {object} settings The configuration settings
* @example
* _converse.api.settings.extend({
* 'enable_foo': true
* });
*
* // The user can then override the default value of the configuration setting when
* // calling `converse.initialize`.
* converse.initialize({
* 'enable_foo': false
* });
*/
extend (settings) {
return extendAppSettings(settings);
},
update (settings) {
log.warn(
'The api.settings.update method has been deprecated and will be removed. ' +
'Please use api.settings.extend instead.'
);
return this.extend(settings);
},
/**
* @method _converse.api.settings.get
* @returns {*} Value of the particular configuration setting.
* @example _converse.api.settings.get("play_sounds");
*/
get (key) {
return getAppSetting(key);
},
/**
* Set one or many configuration settings.
*
* Note, this is not an alternative to calling {@link converse.initialize}, which still needs
* to be called. Generally, you'd use this method after Converse is already
* running and you want to change the configuration on-the-fly.
*
* @method _converse.api.settings.set
* @param {Object} [settings] An object containing configuration settings.
* @param {string} [key] Alternatively to passing in an object, you can pass in a key and a value.
* @param {string} [value]
* @example _converse.api.settings.set("play_sounds", true);
* @example
* _converse.api.settings.set({
* "play_sounds": true,
* "hide_offline_users": true
* });
*/
set (key, val) {
updateAppSettings(key, val);
},
};

File diff suppressed because it is too large Load Diff

View File

@ -2,15 +2,14 @@
* --------------------
* Any of the following components may be removed if they're not needed.
*/
import "./plugins/adhoc.js"; // XEP-0050 Ad Hoc Commands
import "./plugins/bookmarks/index.js"; // XEP-0199 XMPP Ping
import "./plugins/bosh.js"; // XEP-0206 BOSH
import "./plugins/caps/index.js"; // XEP-0115 Entity Capabilities
import "./plugins/carbons.js"; // XEP-0280 Message Carbons
import "./plugins/chat/index.js"; // RFC-6121 Instant messaging
import "./plugins/chatboxes/index.js";
import "./plugins/disco/index.js"; // XEP-0030 Service discovery
import "./plugins/headlines.js"; // Support for headline messages
import "./plugins/adhoc/index.js"; // XEP-0050 Ad Hoc Commands
import "./plugins/headlines/index.js"; // Support for headline messages
import "./plugins/mam/index.js"; // XEP-0313 Message Archive Management
import "./plugins/muc/index.js"; // XEP-0045 Multi-user chat
import "./plugins/ping/index.js"; // XEP-0199 XMPP Ping
@ -18,7 +17,7 @@ import "./plugins/pubsub.js"; // XEP-0060 Pubsub
import "./plugins/roster/index.js"; // RFC-6121 Contacts Roster
import "./plugins/smacks/index.js"; // XEP-0198 Stream Management
import "./plugins/status/index.js";
import "./plugins/vcard.js"; // XEP-0054 VCard-temp
import "./plugins/vcard/index.js"; // XEP-0054 VCard-temp
/* END: Removable components */
import { converse } from "./core.js";

View File

@ -1,4 +1,4 @@
import isElement from 'lodash-es/isElement';
import { isElement } from './utils/core.js';
const LEVELS = {
'debug': 0,
@ -8,24 +8,26 @@ const LEVELS = {
'fatal': 4
}
/* eslint-disable @typescript-eslint/no-empty-function */
const logger = Object.assign({
'debug': console?.log ? console.log.bind(console) : function noop () {},
'error': console?.log ? console.log.bind(console) : function noop () {},
'info': console?.log ? console.log.bind(console) : function noop () {},
'warn': console?.log ? console.log.bind(console) : function noop () {}
}, console);
/* eslint-enable @typescript-eslint/no-empty-function */
/**
* The log namespace
* @namespace log
*/
const log = {
export default {
/**
* The the log-level, which determines how verbose the logging is.
* @method log#setLogLevel
* @param { integer } level - The loglevel which allows for filtering of log messages
* @param { number } level - The loglevel which allows for filtering of log messages
*/
setLogLevel (level) {
if (!['debug', 'info', 'warn', 'error', 'fatal'].includes(level)) {
@ -41,8 +43,8 @@ const log = {
* When using the 'error' or 'warn' loglevels, a full stacktrace will be
* logged as well.
* @method log#log
* @param { string } message - The message to be logged
* @param { integer } level - The loglevel which allows for filtering of log messages
* @param { string | Error } message - The message to be logged
* @param { number } level - The loglevel which allows for filtering of log messages
*/
log (message, level, style='') {
if (LEVELS[level] < LEVELS[this.loglevel]) {
@ -93,5 +95,3 @@ const log = {
this.log(message, 'fatal', style);
}
}
export default log;

View File

@ -1,185 +1,796 @@
{
"name": "@converse/headless",
"version": "8.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@converse/openpromise": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/@converse/openpromise/-/openpromise-0.0.1.tgz",
"integrity": "sha512-oA1TKrm6H838isYZJxMWXpXyOUezkD49eMJ6bkI+FfL2MsVuOV3ZbhBV+c07mLSknKXO7pUbWTVa5f7bXJXYjQ=="
},
"@converse/skeletor": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/@converse/skeletor/-/skeletor-0.0.5.tgz",
"integrity": "sha512-x9aQTCwQOao8jdgfb/+EzITB5/sj+WhCu2yp+uccURte3zTZbG6TSJEI2dqpLxThpgmSQwrsRQDDQ3jc7FZ/2Q==",
"requires": {
"lit-html": "^2.0.0-rc.2",
"lodash-es": "^4.17.21",
"mergebounce": "0.1.0"
}
},
"@types/trusted-types": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-1.0.6.tgz",
"integrity": "sha512-230RC8sFeHoT6sSUlRO6a8cAnclO06eeiq1QDfiv2FGCLWFvvERWgwIQD4FWqD9A69BN7Lzee4OXwoMVnnsWDw=="
},
"abab": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz",
"integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q=="
},
"babel-runtime": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
"integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
"requires": {
"core-js": "^2.4.0",
"regenerator-runtime": "^0.11.0"
}
},
"core-js": {
"version": "2.6.12",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
"integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ=="
},
"dayjs": {
"version": "1.10.6",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.6.tgz",
"integrity": "sha512-AztC/IOW4L1Q41A86phW5Thhcrco3xuAA+YX/BLpLWWjRcTj5TOt/QImBLmCKlrF7u7k47arTnOyL6GnbG8Hvw=="
},
"filesize": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/filesize/-/filesize-7.0.0.tgz",
"integrity": "sha512-Wsstw+O1lZ9gVmOI1thyeQvODsaoId2qw14lCqIzUhoHKXX7T2hVpB7BR6SvgodMBgWccrx/y2eyV8L7tDmY6A=="
},
"immediate": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
"integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps="
},
"lie": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
"integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=",
"requires": {
"immediate": "~3.0.5"
}
},
"lit-html": {
"version": "2.0.0-rc.3",
"resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.0.0-rc.3.tgz",
"integrity": "sha512-Y6P8LlAyQuqvzq6l/Nc4z5/P5M/rVLYKQIRxcNwSuGajK0g4kbcBFQqZmgvqKG+ak+dHZjfm2HUw9TF5N/pkCw==",
"requires": {
"@types/trusted-types": "^1.0.1"
}
},
"localforage": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz",
"integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==",
"requires": {
"lie": "3.1.1"
}
},
"localforage-driver-commons": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/localforage-driver-commons/-/localforage-driver-commons-1.0.3.tgz",
"integrity": "sha512-K9PiNNXcyX98lQVyCADjv+QKxFD71y0DtVUhqMjwCkFY/d/g7GdJLPN9U92M7RUvfkL8mzPhC+mWEKo9tur5oQ=="
},
"localforage-driver-memory": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/localforage-driver-memory/-/localforage-driver-memory-1.0.5.tgz",
"integrity": "sha512-m4v478ixdT3hA7gKv+pAxDIWgMKiUV2GuYem5jnpOBQFVJbrHU7jmNlrj8a0MfD9qff3i48E3Yfip5Eu1AN6Qg==",
"requires": {
"localforage-driver-commons": "^1.0.1",
"tslib": "^1.6.0"
}
},
"localforage-setitems": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/localforage-setitems/-/localforage-setitems-1.4.0.tgz",
"integrity": "sha1-NrhZDVB9+1yAQDPih+zljYiZbV8=",
"requires": {
"localforage": ">=1.4.0"
}
},
"localforage-webextensionstorage-driver": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/localforage-webextensionstorage-driver/-/localforage-webextensionstorage-driver-2.0.0.tgz",
"integrity": "sha512-gB9q+NOn3D62x8Akn7nykh2H0ArNehYflZ3sgGZNc8eB6Yf0HnK30vwpe0xXTLYMIe15XeRNiiZd8qwTFnGYSw==",
"requires": {
"babel-runtime": "^6.22.0"
}
},
"lodash-es": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
},
"mergebounce": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/mergebounce/-/mergebounce-0.1.0.tgz",
"integrity": "sha512-M78tj1Ca6Q1QNmVexX+ExuX2Ta8OsNFT3h2RmPpYSUeXF+7/NyImQ/03NxpNzycvjWMNzSOX5uq7fzuj4Rgqrw==",
"requires": {
"@converse/openpromise": "0.0.1",
"lodash-es": "^4.17.21"
}
},
"pluggable.js": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/pluggable.js/-/pluggable.js-3.0.1.tgz",
"integrity": "sha512-DQC51A6aKLk6anvyvQfukNcVzGHOI5B04DerHioqLSF7ptI+Nla2hHzG4PGxq8tKqOGwQHnXnj9qxcFM3VViEQ==",
"requires": {
"lodash-es": "^4.17.21"
}
},
"regenerator-runtime": {
"version": "0.11.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
},
"sizzle": {
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/sizzle/-/sizzle-2.3.6.tgz",
"integrity": "sha512-abtd95IkbcMAaYk1Lux4k9Xz6wnQqyLy2aco9HGJ8jVaCDEcc+ug0hW8RdV6aIre3ycWXxPdcX0u7QL/1UaSoA=="
},
"sprintf-js": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz",
"integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug=="
},
"strophe.js": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/strophe.js/-/strophe.js-1.4.2.tgz",
"integrity": "sha512-jkyZQCZLm7Zgmra0zJKxpHPNIUncYj/e/eYfgxFoc5gwrWeHWigNBs0q7wtqhCiqG6Qxcf22PUpcyBq8cK+9ew==",
"requires": {
"abab": "^2.0.3",
"ws": "^7.0.0",
"xmldom": "0.5.0"
}
},
"tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
},
"urijs": {
"version": "1.19.7",
"resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.7.tgz",
"integrity": "sha512-Id+IKjdU0Hx+7Zx717jwLPsPeUqz7rAtuVBRLLs+qn+J2nf9NGITWVCxcijgYxBqe83C7sqsQPs6H1pyz3x9gA=="
},
"ws": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz",
"integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==",
"optional": true
},
"xmldom": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.5.0.tgz",
"integrity": "sha512-Foaj5FXVzgn7xFzsKeNIde9g6aFBxTPi37iwsno8QvApmtg7KYrr+OPyRHcJF7dud2a5nGRBXK3n0dL62Gf7PA==",
"optional": true
}
}
"name": "@converse/headless",
"version": "10.1.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@converse/headless",
"version": "10.1.0",
"license": "MPL-2.0",
"dependencies": {
"@converse/openpromise": "^0.0.1",
"@converse/skeletor": "0.0.8",
"dayjs": "1.11.8",
"dompurify": "^2.3.1",
"filesize": "^7.0.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.0",
"urijs": "^1.19.10"
}
},
"node_modules/@converse/localforage-getitems": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/@converse/localforage-getitems/-/localforage-getitems-1.4.3.tgz",
"integrity": "sha512-ofch1Zv9+CxU4xYxBq+QmsJFKLi6FZ69REPoTc56eeWN6ps0/+g5gD4/gwukEFhAuE8jsBpjcrnizXsa4WsMxQ==",
"dependencies": {
"localforage": ">=1.4.0"
}
},
"node_modules/@converse/openpromise": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/@converse/openpromise/-/openpromise-0.0.1.tgz",
"integrity": "sha512-oA1TKrm6H838isYZJxMWXpXyOUezkD49eMJ6bkI+FfL2MsVuOV3ZbhBV+c07mLSknKXO7pUbWTVa5f7bXJXYjQ=="
},
"node_modules/@converse/skeletor": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/@converse/skeletor/-/skeletor-0.0.8.tgz",
"integrity": "sha512-8/wAenuk7QKOHaOsk89e5zFyQZz5HhsuqWBzrzDxmepiBVlRvnxjVdB6619IFyW0VWf0ezcm5Rl4JndUx2sbqg==",
"dependencies": {
"@converse/localforage-getitems": "1.4.3",
"lit-html": "^2.0.0-rc.2",
"localforage": "^1.10.0",
"localforage-driver-memory": "^1.0.5",
"localforage-setitems": "^1.4.0",
"lodash-es": "^4.17.21",
"mergebounce": "0.1.1"
}
},
"node_modules/@types/trusted-types": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.3.tgz",
"integrity": "sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g=="
},
"node_modules/@xmldom/xmldom": {
"version": "0.8.3",
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.3.tgz",
"integrity": "sha512-Lv2vySXypg4nfa51LY1nU8yDAGo/5YwF+EY/rUZgIbfvwVARcd67ttCM8SMsTeJy51YhHYavEq+FS6R0hW9PFQ==",
"optional": true,
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/abab": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
"integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA=="
},
"node_modules/anymatch": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
"dependencies": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/babel-runtime": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
"integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==",
"dependencies": {
"core-js": "^2.4.0",
"regenerator-runtime": "^0.11.0"
}
},
"node_modules/binary-extensions": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
"engines": {
"node": ">=8"
}
},
"node_modules/braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"dependencies": {
"fill-range": "^7.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/chokidar": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
"funding": [
{
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
],
"dependencies": {
"anymatch": "~3.1.2",
"braces": "~3.0.2",
"glob-parent": "~5.1.2",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.6.0"
},
"engines": {
"node": ">= 8.10.0"
},
"optionalDependencies": {
"fsevents": "~2.3.2"
}
},
"node_modules/core-js": {
"version": "2.6.12",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
"integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==",
"deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.",
"hasInstallScript": true
},
"node_modules/dayjs": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.6.tgz",
"integrity": "sha512-zZbY5giJAinCG+7AGaw0wIhNZ6J8AhWuSXKvuc1KAyMiRsvGQWqh4L+MomvhdAYjN+lqvVCMq1I41e3YHvXkyQ=="
},
"node_modules/debounce": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz",
"integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug=="
},
"node_modules/dompurify": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.4.tgz",
"integrity": "sha512-1e2SpqHiRx4DPvmRuXU5J0di3iQACwJM+mFGE2HAkkK7Tbnfk9WcghcAmyWc9CRrjyRRUpmuhPUH6LphQQR3EQ=="
},
"node_modules/filesize": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/filesize/-/filesize-7.0.0.tgz",
"integrity": "sha512-Wsstw+O1lZ9gVmOI1thyeQvODsaoId2qw14lCqIzUhoHKXX7T2hVpB7BR6SvgodMBgWccrx/y2eyV8L7tDmY6A==",
"engines": {
"node": ">= 0.4.0"
}
},
"node_modules/fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"dependencies": {
"to-regex-range": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"hasInstallScript": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dependencies": {
"is-glob": "^4.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/immediate": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="
},
"node_modules/is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
"dependencies": {
"binary-extensions": "^2.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
"dependencies": {
"is-extglob": "^2.1.1"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"engines": {
"node": ">=0.12.0"
}
},
"node_modules/karma-rollup-preprocessor": {
"version": "7.0.8",
"resolved": "https://registry.npmjs.org/karma-rollup-preprocessor/-/karma-rollup-preprocessor-7.0.8.tgz",
"integrity": "sha512-WiuBCS9qsatJuR17dghiTARBZ7LF+ml+eb7qJXhw7IbsdY0lTWELDRQC/93J9i6636CsAXVBL3VJF4WtaFLZzA==",
"dependencies": {
"chokidar": "^3.3.1",
"debounce": "^1.2.0"
},
"engines": {
"node": ">= 8.0.0"
},
"peerDependencies": {
"rollup": ">= 1.0.0"
}
},
"node_modules/lie": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
"integrity": "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==",
"dependencies": {
"immediate": "~3.0.5"
}
},
"node_modules/lit-html": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.6.1.tgz",
"integrity": "sha512-Z3iw+E+3KKFn9t2YKNjsXNEu/LRLI98mtH/C6lnFg7kvaqPIzPn124Yd4eT/43lyqrejpc5Wb6BHq3fdv4S8Rw==",
"dependencies": {
"@types/trusted-types": "^2.0.2"
}
},
"node_modules/localforage": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz",
"integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==",
"dependencies": {
"lie": "3.1.1"
}
},
"node_modules/localforage-driver-commons": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/localforage-driver-commons/-/localforage-driver-commons-1.0.3.tgz",
"integrity": "sha512-K9PiNNXcyX98lQVyCADjv+QKxFD71y0DtVUhqMjwCkFY/d/g7GdJLPN9U92M7RUvfkL8mzPhC+mWEKo9tur5oQ==",
"peerDependencies": {
"tslib": "^1.6.0"
}
},
"node_modules/localforage-driver-memory": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/localforage-driver-memory/-/localforage-driver-memory-1.0.5.tgz",
"integrity": "sha512-m4v478ixdT3hA7gKv+pAxDIWgMKiUV2GuYem5jnpOBQFVJbrHU7jmNlrj8a0MfD9qff3i48E3Yfip5Eu1AN6Qg==",
"dependencies": {
"localforage-driver-commons": "^1.0.1",
"tslib": "^1.6.0"
},
"peerDependencies": {
"localforage": "^1.5.0"
}
},
"node_modules/localforage-setitems": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/localforage-setitems/-/localforage-setitems-1.4.0.tgz",
"integrity": "sha512-uU2ZydBZZkwaP0s1m5NMJXKOQJ0pfqFjDfHdv/SU9E1SWZpr4U3qpyJLZSZJvCvaAeBEL9Bvzd0/CWC9Jtk3wg==",
"dependencies": {
"localforage": ">=1.4.0"
}
},
"node_modules/localforage-webextensionstorage-driver": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/localforage-webextensionstorage-driver/-/localforage-webextensionstorage-driver-3.0.0.tgz",
"integrity": "sha512-8DUdLnTiX0aBlKqEMPSKiwesx+nHjdH7Bi8+8Hlq0dKXurW9zJvhVfEDU9Pv/LOskNWGo/PuSzLnAcmFqKCvpg==",
"dependencies": {
"babel-runtime": "^6.22.0"
},
"peerDependencies": {
"localforage": "^1.7.4"
}
},
"node_modules/lodash-es": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
},
"node_modules/mergebounce": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/mergebounce/-/mergebounce-0.1.1.tgz",
"integrity": "sha512-UvBRi+87aFdjLXAQhX3aTja4l5Uc4ZTrSL3V939lR7n7PWrBN8CiQLTprmtVca65Vwu2JuXPbMIvNM4JElMxdQ==",
"dependencies": {
"@converse/openpromise": "0.0.1",
"lodash-es": "^4.17.21"
}
},
"node_modules/normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"engines": {
"node": ">=8.6"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/pluggable.js": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/pluggable.js/-/pluggable.js-3.0.1.tgz",
"integrity": "sha512-DQC51A6aKLk6anvyvQfukNcVzGHOI5B04DerHioqLSF7ptI+Nla2hHzG4PGxq8tKqOGwQHnXnj9qxcFM3VViEQ==",
"dependencies": {
"lodash-es": "^4.17.21"
}
},
"node_modules/readdirp": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
"dependencies": {
"picomatch": "^2.2.1"
},
"engines": {
"node": ">=8.10.0"
}
},
"node_modules/regenerator-runtime": {
"version": "0.11.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
},
"node_modules/rollup": {
"version": "3.15.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-3.15.0.tgz",
"integrity": "sha512-F9hrCAhnp5/zx/7HYmftvsNBkMfLfk/dXUh73hPSM2E3CRgap65orDNJbLetoiUFwSAk6iHPLvBrZ5iHYvzqsg==",
"peer": true,
"bin": {
"rollup": "dist/bin/rollup"
},
"engines": {
"node": ">=14.18.0",
"npm": ">=8.0.0"
},
"optionalDependencies": {
"fsevents": "~2.3.2"
}
},
"node_modules/sizzle": {
"version": "2.3.10",
"resolved": "https://registry.npmjs.org/sizzle/-/sizzle-2.3.10.tgz",
"integrity": "sha512-kPGev+SiByuzi/YPDTqCwdKLWCaN9+14ve86yH0gP6Efue04xjLYWJrcLC6y1buFyIVXkwHNXPsOTEd1MYVPbQ=="
},
"node_modules/sprintf-js": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz",
"integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug=="
},
"node_modules/strophe.js": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/strophe.js/-/strophe.js-1.6.0.tgz",
"integrity": "sha512-LE2B6nEJNUbF2Cl/p1tLIsXVJ9l86B/Z12HYYiO3n92VwYkhJ/5vJ+1ZMdwP9eN9GP8a3nbqfS5zE9umcK0FdA==",
"dependencies": {
"abab": "^2.0.3",
"karma-rollup-preprocessor": "^7.0.8"
},
"optionalDependencies": {
"@xmldom/xmldom": "0.8.3",
"ws": "^8.5.0"
}
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dependencies": {
"is-number": "^7.0.0"
},
"engines": {
"node": ">=8.0"
}
},
"node_modules/tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
},
"node_modules/urijs": {
"version": "1.19.11",
"resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.11.tgz",
"integrity": "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ=="
},
"node_modules/ws": {
"version": "8.12.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.12.1.tgz",
"integrity": "sha512-1qo+M9Ba+xNhPB+YTWUlK6M17brTut5EXbcBaMRN5pH5dFrXz7lzz1ChFSUq3bOUl8yEvSenhHmYUNJxFzdJew==",
"optional": true,
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
}
},
"dependencies": {
"@converse/localforage-getitems": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/@converse/localforage-getitems/-/localforage-getitems-1.4.3.tgz",
"integrity": "sha512-ofch1Zv9+CxU4xYxBq+QmsJFKLi6FZ69REPoTc56eeWN6ps0/+g5gD4/gwukEFhAuE8jsBpjcrnizXsa4WsMxQ==",
"requires": {
"localforage": ">=1.4.0"
}
},
"@converse/openpromise": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/@converse/openpromise/-/openpromise-0.0.1.tgz",
"integrity": "sha512-oA1TKrm6H838isYZJxMWXpXyOUezkD49eMJ6bkI+FfL2MsVuOV3ZbhBV+c07mLSknKXO7pUbWTVa5f7bXJXYjQ=="
},
"@converse/skeletor": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/@converse/skeletor/-/skeletor-0.0.8.tgz",
"integrity": "sha512-8/wAenuk7QKOHaOsk89e5zFyQZz5HhsuqWBzrzDxmepiBVlRvnxjVdB6619IFyW0VWf0ezcm5Rl4JndUx2sbqg==",
"requires": {
"@converse/localforage-getitems": "1.4.3",
"lit-html": "^2.0.0-rc.2",
"localforage": "^1.10.0",
"localforage-driver-memory": "^1.0.5",
"localforage-setitems": "^1.4.0",
"lodash-es": "^4.17.21",
"mergebounce": "0.1.1"
}
},
"@types/trusted-types": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.3.tgz",
"integrity": "sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g=="
},
"@xmldom/xmldom": {
"version": "0.8.3",
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.3.tgz",
"integrity": "sha512-Lv2vySXypg4nfa51LY1nU8yDAGo/5YwF+EY/rUZgIbfvwVARcd67ttCM8SMsTeJy51YhHYavEq+FS6R0hW9PFQ==",
"optional": true
},
"abab": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
"integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA=="
},
"anymatch": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
"requires": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
}
},
"babel-runtime": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
"integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==",
"requires": {
"core-js": "^2.4.0",
"regenerator-runtime": "^0.11.0"
}
},
"binary-extensions": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA=="
},
"braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"requires": {
"fill-range": "^7.0.1"
}
},
"chokidar": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
"requires": {
"anymatch": "~3.1.2",
"braces": "~3.0.2",
"fsevents": "~2.3.2",
"glob-parent": "~5.1.2",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.6.0"
}
},
"core-js": {
"version": "2.6.12",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
"integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ=="
},
"dayjs": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.6.tgz",
"integrity": "sha512-zZbY5giJAinCG+7AGaw0wIhNZ6J8AhWuSXKvuc1KAyMiRsvGQWqh4L+MomvhdAYjN+lqvVCMq1I41e3YHvXkyQ=="
},
"debounce": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz",
"integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug=="
},
"dompurify": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.4.tgz",
"integrity": "sha512-1e2SpqHiRx4DPvmRuXU5J0di3iQACwJM+mFGE2HAkkK7Tbnfk9WcghcAmyWc9CRrjyRRUpmuhPUH6LphQQR3EQ=="
},
"filesize": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/filesize/-/filesize-7.0.0.tgz",
"integrity": "sha512-Wsstw+O1lZ9gVmOI1thyeQvODsaoId2qw14lCqIzUhoHKXX7T2hVpB7BR6SvgodMBgWccrx/y2eyV8L7tDmY6A=="
},
"fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"requires": {
"to-regex-range": "^5.0.1"
}
},
"fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"optional": true
},
"glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"requires": {
"is-glob": "^4.0.1"
}
},
"immediate": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="
},
"is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
"requires": {
"binary-extensions": "^2.0.0"
}
},
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="
},
"is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
"requires": {
"is-extglob": "^2.1.1"
}
},
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
},
"karma-rollup-preprocessor": {
"version": "7.0.8",
"resolved": "https://registry.npmjs.org/karma-rollup-preprocessor/-/karma-rollup-preprocessor-7.0.8.tgz",
"integrity": "sha512-WiuBCS9qsatJuR17dghiTARBZ7LF+ml+eb7qJXhw7IbsdY0lTWELDRQC/93J9i6636CsAXVBL3VJF4WtaFLZzA==",
"requires": {
"chokidar": "^3.3.1",
"debounce": "^1.2.0"
}
},
"lie": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
"integrity": "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==",
"requires": {
"immediate": "~3.0.5"
}
},
"lit-html": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.6.1.tgz",
"integrity": "sha512-Z3iw+E+3KKFn9t2YKNjsXNEu/LRLI98mtH/C6lnFg7kvaqPIzPn124Yd4eT/43lyqrejpc5Wb6BHq3fdv4S8Rw==",
"requires": {
"@types/trusted-types": "^2.0.2"
}
},
"localforage": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz",
"integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==",
"requires": {
"lie": "3.1.1"
}
},
"localforage-driver-commons": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/localforage-driver-commons/-/localforage-driver-commons-1.0.3.tgz",
"integrity": "sha512-K9PiNNXcyX98lQVyCADjv+QKxFD71y0DtVUhqMjwCkFY/d/g7GdJLPN9U92M7RUvfkL8mzPhC+mWEKo9tur5oQ==",
"requires": {}
},
"localforage-driver-memory": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/localforage-driver-memory/-/localforage-driver-memory-1.0.5.tgz",
"integrity": "sha512-m4v478ixdT3hA7gKv+pAxDIWgMKiUV2GuYem5jnpOBQFVJbrHU7jmNlrj8a0MfD9qff3i48E3Yfip5Eu1AN6Qg==",
"requires": {
"localforage-driver-commons": "^1.0.1",
"tslib": "^1.6.0"
}
},
"localforage-setitems": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/localforage-setitems/-/localforage-setitems-1.4.0.tgz",
"integrity": "sha512-uU2ZydBZZkwaP0s1m5NMJXKOQJ0pfqFjDfHdv/SU9E1SWZpr4U3qpyJLZSZJvCvaAeBEL9Bvzd0/CWC9Jtk3wg==",
"requires": {
"localforage": ">=1.4.0"
}
},
"localforage-webextensionstorage-driver": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/localforage-webextensionstorage-driver/-/localforage-webextensionstorage-driver-3.0.0.tgz",
"integrity": "sha512-8DUdLnTiX0aBlKqEMPSKiwesx+nHjdH7Bi8+8Hlq0dKXurW9zJvhVfEDU9Pv/LOskNWGo/PuSzLnAcmFqKCvpg==",
"requires": {
"babel-runtime": "^6.22.0"
}
},
"lodash-es": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
},
"mergebounce": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/mergebounce/-/mergebounce-0.1.1.tgz",
"integrity": "sha512-UvBRi+87aFdjLXAQhX3aTja4l5Uc4ZTrSL3V939lR7n7PWrBN8CiQLTprmtVca65Vwu2JuXPbMIvNM4JElMxdQ==",
"requires": {
"@converse/openpromise": "0.0.1",
"lodash-es": "^4.17.21"
}
},
"normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
},
"picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="
},
"pluggable.js": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/pluggable.js/-/pluggable.js-3.0.1.tgz",
"integrity": "sha512-DQC51A6aKLk6anvyvQfukNcVzGHOI5B04DerHioqLSF7ptI+Nla2hHzG4PGxq8tKqOGwQHnXnj9qxcFM3VViEQ==",
"requires": {
"lodash-es": "^4.17.21"
}
},
"readdirp": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
"requires": {
"picomatch": "^2.2.1"
}
},
"regenerator-runtime": {
"version": "0.11.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
},
"rollup": {
"version": "3.15.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-3.15.0.tgz",
"integrity": "sha512-F9hrCAhnp5/zx/7HYmftvsNBkMfLfk/dXUh73hPSM2E3CRgap65orDNJbLetoiUFwSAk6iHPLvBrZ5iHYvzqsg==",
"peer": true,
"requires": {
"fsevents": "~2.3.2"
}
},
"sizzle": {
"version": "2.3.10",
"resolved": "https://registry.npmjs.org/sizzle/-/sizzle-2.3.10.tgz",
"integrity": "sha512-kPGev+SiByuzi/YPDTqCwdKLWCaN9+14ve86yH0gP6Efue04xjLYWJrcLC6y1buFyIVXkwHNXPsOTEd1MYVPbQ=="
},
"sprintf-js": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz",
"integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug=="
},
"strophe.js": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/strophe.js/-/strophe.js-1.6.0.tgz",
"integrity": "sha512-LE2B6nEJNUbF2Cl/p1tLIsXVJ9l86B/Z12HYYiO3n92VwYkhJ/5vJ+1ZMdwP9eN9GP8a3nbqfS5zE9umcK0FdA==",
"requires": {
"@xmldom/xmldom": "0.8.3",
"abab": "^2.0.3",
"karma-rollup-preprocessor": "^7.0.8",
"ws": "^8.5.0"
}
},
"to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"requires": {
"is-number": "^7.0.0"
}
},
"tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
},
"urijs": {
"version": "1.19.11",
"resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.11.tgz",
"integrity": "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ=="
},
"ws": {
"version": "8.12.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.12.1.tgz",
"integrity": "sha512-1qo+M9Ba+xNhPB+YTWUlK6M17brTut5EXbcBaMRN5pH5dFrXz7lzz1ChFSUq3bOUl8yEvSenhHmYUNJxFzdJew==",
"optional": true,
"requires": {}
}
}
}

View File

@ -1,20 +1,15 @@
{
"name": "@converse/headless",
"version": "8.0.0",
"version": "10.1.6",
"description": "Converse.js Headless build",
"author": "cmrd Senya <senya@riseup.net>",
"author": "JC Brand <jc@opkode.com>",
"contributors": [
"cmrd Senya <senya@riseup.net>"
],
"homepage": "https://conversejs.org",
"license": "MPL-2.0",
"main": "dist/converse-headless.min.js",
"files": [
"*.js",
"*.json",
"dist/",
"README.md",
"utils/*.js",
"templates/*.html",
"templates/*.svg"
],
"main": "dist/converse-headless.js",
"module": "index.js",
"keywords": [
"converse.js",
"XMPP",
@ -26,7 +21,8 @@
],
"repository": {
"type": "git",
"url": "git+https://github.com/conversejs/converse.js.git"
"url": "git+https://github.com/conversejs/converse.js.git",
"directory": "src/headless"
},
"scripts": {
"test": "echo \"Error: run tests from root\" && exit 1"
@ -34,21 +30,19 @@
"bugs": {
"url": "https://github.com/conversejs/converse.js/issues"
},
"gitHead": "9641dcdc820e029b05930479c242d2b707bbe8e2",
"devDependencies": {},
"dependencies": {
"@converse/skeletor": "0.0.5",
"dayjs": "1.10.6",
"filesize": "^7.0.0",
"localforage": "^1.10.0",
"localforage-driver-memory": "^1.0.5",
"localforage-setitems": "^1.4.0",
"localforage-webextensionstorage-driver": "^2.0.0",
"@converse/openpromise": "^0.0.1",
"@converse/skeletor": "^0.0.8",
"dayjs": "^1.11.8",
"dompurify": "^2.3.1",
"filesize": "^10.0.7",
"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.4.2",
"urijs": "^1.19.7"
}
"strophe.js": "^1.6.2",
"urijs": "^1.19.10"
},
"devDependencies": {}
}

View File

@ -1,61 +0,0 @@
import { converse } from "../core.js";
import log from "@converse/headless/log";
import sizzle from 'sizzle';
import { getAttributes } from '@converse/headless/shared/parsers';
const { Strophe } = converse.env;
let _converse, api;
Strophe.addNamespace('ADHOC', 'http://jabber.org/protocol/commands');
function parseForCommands (stanza) {
const items = sizzle(`query[xmlns="${Strophe.NS.DISCO_ITEMS}"][node="${Strophe.NS.ADHOC}"] item`, stanza);
return items.map(getAttributes)
}
const adhoc_api = {
/**
* The XEP-0050 Ad-Hoc Commands API
*
* This API lets you discover ad-hoc commands available for an entity in the XMPP network.
*
* @namespace api.adhoc
* @memberOf api
*/
adhoc: {
/**
* @method api.adhoc.getCommands
* @param { String } to_jid
*/
async getCommands (to_jid) {
let commands = [];
try {
commands = parseForCommands(await api.disco.items(to_jid, Strophe.NS.ADHOC));
} catch (e) {
if (e === null) {
log.error(`Error: timeout while fetching ad-hoc commands for ${to_jid}`);
} else {
log.error(`Error while fetching ad-hoc commands for ${to_jid}`);
log.error(e);
}
}
return commands;
}
}
}
converse.plugins.add('converse-adhoc', {
dependencies: ["converse-disco"],
initialize () {
_converse = this._converse;
api = _converse.api;
Object.assign(api, adhoc_api);
}
});
export default adhoc_api;

View File

@ -0,0 +1,109 @@
import log from '@converse/headless/log';
import { _converse, api, converse } from "@converse/headless/core";
import { getCommandFields, parseForCommands } from './utils.js';
const { Strophe, $iq, u, stx } = converse.env;
export default {
/**
* The XEP-0050 Ad-Hoc Commands API
*
* This API lets you discover ad-hoc commands available for an entity in the XMPP network.
*
* @namespace api.adhoc
* @memberOf api
*/
adhoc: {
/**
* @method api.adhoc.getCommands
* @param { String } to_jid
*/
async getCommands (to_jid) {
try {
return parseForCommands(await api.disco.items(to_jid, Strophe.NS.ADHOC));
} catch (e) {
if (e === null) {
log.error(`Error: timeout while fetching ad-hoc commands for ${to_jid}`);
} else {
log.error(`Error while fetching ad-hoc commands for ${to_jid}`);
log.error(e);
}
return [];
}
},
/**
* @method api.adhoc.fetchCommandForm
*/
async 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 {
return getCommandFields(await api.sendIQ(stanza), jid);
} 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);
}
const { __ } = _converse;
return {
instructions: __('An error occurred while trying to fetch the command form'),
fields: []
}
}
},
/**
* @method api.adhoc.runCommand
* @param { String } jid
* @param { String } sessionid
* @param { 'execute' | 'cancel' | 'prev' | 'next' | 'complete' } action
* @param { String } node
* @param { Array<{ string: string }> } inputs
*/
async runCommand (jid, sessionid, node, action, inputs) {
const iq =
stx`<iq type="set" to="${jid}" xmlns="jabber:client">
<command sessionid="${sessionid}" node="${node}" action="${action}" xmlns="${Strophe.NS.ADHOC}">
${ !['cancel', 'prev'].includes(action) ? stx`
<x xmlns="${Strophe.NS.XFORM}" type="submit">
${ inputs.reduce((out, { name, value }) => out + `<field var="${name}"><value>${value}</value></field>`, '') }
</x>` : '' }
</command>
</iq>`;
const result = await api.sendIQ(iq, null, false);
if (result === null) {
log.warn(`A timeout occurred while trying to run an ad-hoc command`);
const { __ } = _converse;
return {
status: 'error',
note: __('A timeout occurred'),
}
} else if (u.isErrorStanza(result)) {
log.error('Error while trying to execute an ad-hoc command');
log.error(result);
}
const command = result.querySelector('command');
const status = command?.getAttribute('status');
return {
status,
...(status === 'executing' ? getCommandFields(result) : {}),
note: result.querySelector('note')?.textContent
}
}
}
}

View File

@ -0,0 +1,16 @@
import adhoc_api from './api.js';
import { converse } from "@converse/headless/core";
const { Strophe } = converse.env;
Strophe.addNamespace('ADHOC', 'http://jabber.org/protocol/commands');
converse.plugins.add('converse-adhoc', {
dependencies: ["converse-disco"],
initialize () {
Object.assign(this._converse.api, adhoc_api);
}
});

View File

@ -0,0 +1,22 @@
import sizzle from 'sizzle';
import { converse } from "@converse/headless/core";
import { getAttributes } from '@converse/headless/shared/parsers';
const { Strophe, u } = converse.env;
export function parseForCommands (stanza) {
const items = sizzle(`query[xmlns="${Strophe.NS.DISCO_ITEMS}"][node="${Strophe.NS.ADHOC}"] item`, stanza);
return items.map(getAttributes)
}
export function getCommandFields (iq, jid) {
const cmd_el = sizzle(`command[xmlns="${Strophe.NS.ADHOC}"]`, iq).pop();
const data = {
sessionid: cmd_el.getAttribute('sessionid'),
instructions: sizzle('x[type="form"][xmlns="jabber:x:data"] instructions', cmd_el).pop()?.textContent,
fields: sizzle('x[type="form"][xmlns="jabber:x:data"] field', cmd_el)
.map(f => u.xForm2TemplateResult(f, cmd_el, { domain: jid })),
actions: Array.from(cmd_el.querySelector('actions')?.children).map((a) => a.nodeName.toLowerCase()) ?? []
}
return data;
}

View File

@ -1,7 +1,6 @@
import "@converse/headless/plugins/muc/index.js";
import Bookmark from './model.js';
import log from "@converse/headless/log.js";
import { __ } from 'i18n';
import { _converse, api, converse } from "@converse/headless/core";
import { getOpenPromise } from '@converse/openpromise';
import { initStorage } from '@converse/headless/utils/storage.js';
@ -14,7 +13,7 @@ const Bookmarks = {
model: Bookmark,
comparator: (item) => item.get('name').toLowerCase(),
initialize () {
async initialize () {
this.on('add', bm => this.openBookmarkedRoom(bm)
.then(bm => this.markRoomAsBookmarked(bm))
.catch(e => log.fatal(e))
@ -26,6 +25,17 @@ const Bookmarks = {
const cache_key = `converse.room-bookmarks${_converse.bare_jid}`;
this.fetched_flag = cache_key+'fetched';
initStorage(this, cache_key);
await this.fetchBookmarks();
/**
* Triggered once the _converse.Bookmarks collection
* has been created and cached bookmarks have been fetched.
* @event _converse#bookmarksInitialized
* @type { _converse.Bookmarks }
* @example _converse.api.listen.on('bookmarksInitialized', (bookmarks) => { ... });
*/
api.trigger('bookmarksInitialized', this);
},
async openBookmarkedRoom (bookmark) {
@ -86,12 +96,13 @@ const Bookmarks = {
},
onBookmarkError (iq, options) {
const { __ } = _converse;
log.error("Error while trying to add bookmark");
log.error(iq);
api.alert(
'error', __('Error'), [__("Sorry, something went wrong while trying to save your bookmark.")]
);
this.findWhere({'jid': options.jid}).destroy();
this.get(options.jid)?.destroy();
},
fetchBookmarksFromServer (deferred) {
@ -108,16 +119,12 @@ const Bookmarks = {
markRoomAsBookmarked (bookmark) {
const groupchat = _converse.chatboxes.get(bookmark.get('jid'));
if (groupchat !== undefined) {
groupchat.save('bookmarked', true);
}
groupchat?.save('bookmarked', true);
},
markRoomAsUnbookmarked (bookmark) {
const groupchat = _converse.chatboxes.get(bookmark.get('jid'));
if (groupchat !== undefined) {
groupchat.save('bookmarked', false);
}
groupchat?.save('bookmarked', false);
},
createBookmarksFromStanza (stanza) {
@ -145,6 +152,7 @@ const Bookmarks = {
},
onBookmarksReceivedError (deferred, iq) {
const { __ } = _converse;
if (iq === null) {
log.error('Error: timeout while fetching bookmarks');
api.alert('error', __('Timeout Error'),
@ -167,7 +175,9 @@ const Bookmarks = {
}
},
getUnopenedBookmarks () {
async getUnopenedBookmarks () {
await api.waitUntil('bookmarksInitialized')
await api.waitUntil('chatBoxesFetched')
return this.filter(b => !_converse.chatboxes.get(b.get('jid')));
}
}

View File

@ -1,64 +1,36 @@
/**
* @description
* Converse.js plugin which adds views for bookmarks specified in XEP-0048.
* @copyright 2020, the Converse.js contributors
* @copyright 2022, the Converse.js contributors
* @license Mozilla Public License (MPLv2)
*/
import "@converse/headless/plugins/muc/index.js";
import Bookmark from './model.js';
import Bookmarks from './collection.js';
import log from "@converse/headless/log.js";
import { Collection } from "@converse/skeletor/src/collection";
import { Model } from '@converse/skeletor/src/model.js';
import { _converse, api, converse } from "@converse/headless/core";
import { initBookmarks, getNicknameFromBookmark } from './utils.js';
import { Collection } from "@converse/skeletor/src/collection.js";
import { _converse, api, converse } from "@converse/headless/core.js";
import { initBookmarks, getNicknameFromBookmark, handleBookmarksPush } from './utils.js';
const { Strophe, sizzle } = converse.env;
const { Strophe } = converse.env;
Strophe.addNamespace('BOOKMARKS', 'storage:bookmarks');
function handleBookmarksPush (message) {
if (sizzle(`event[xmlns="${Strophe.NS.PUBSUB}#event"] items[node="${Strophe.NS.BOOKMARKS}"]`, message).length) {
api.waitUntil('bookmarksInitialized')
.then(() => _converse.bookmarks.createBookmarksFromStanza(message))
.catch(e => log.fatal(e));
}
return true;
}
converse.plugins.add('converse-bookmarks', {
/* Plugin dependencies are other plugins which might be
* overridden or relied upon, and therefore need to be loaded before
* this plugin.
*
* If the setting "strict_plugin_dependencies" is set to true,
* an error will be raised if the plugin is not found. By default it's
* false, which means these plugins are only loaded opportunistically.
*
* NB: These plugins need to have already been loaded via require.js.
*/
dependencies: ["converse-chatboxes", "converse-muc"],
overrides: {
// Overrides mentioned here will be picked up by converse.js's
// plugin architecture they will replace existing methods on the
// relevant objects or classes.
//
// New functions which don't exist yet can also be added.
ChatRoom: {
getDisplayName () {
const { _converse } = this.__super__;
if (this.get('bookmarked') && _converse.bookmarks) {
const bookmark = _converse.bookmarks.findWhere({'jid': this.get('jid')});
if (bookmark) {
return bookmark.get('name');
}
}
return this.__super__.getDisplayName.apply(this, arguments);
const { _converse, getDisplayName } = this.__super__;
const bookmark = this.get('bookmarked') ? _converse.bookmarks?.get(this.get('jid')) : null;
return bookmark?.get('name') || getDisplayName.apply(this, arguments);
},
getAndPersistNickname (nick) {
@ -69,10 +41,6 @@ converse.plugins.add('converse-bookmarks', {
},
initialize () {
/* The initialize function gets called as soon as the plugin is
* loaded by converse.js's plugin machinery.
*/
// Configuration values for this plugin
// ====================================
// Refer to docs/source/configuration.rst for explanations of these
@ -88,12 +56,6 @@ converse.plugins.add('converse-bookmarks', {
_converse.Bookmark = Bookmark;
_converse.Bookmarks = Collection.extend(Bookmarks);
_converse.BookmarksList = Model.extend({
defaults: {
"toggle-state": _converse.OPENED
}
});
api.listen.on('addClientFeatures', () => {
if (api.settings.get('allow_bookmarks')) {
api.disco.own.features.add(Strophe.NS.BOOKMARKS + '+notify')
@ -101,7 +63,7 @@ converse.plugins.add('converse-bookmarks', {
})
api.listen.on('clearSession', () => {
if (_converse.bookmarks !== undefined) {
if (_converse.bookmarks) {
_converse.bookmarks.clearStore({'silent': true});
window.sessionStorage.removeItem(_converse.bookmarks.fetched_flag);
delete _converse.bookmarks;

View File

@ -1,9 +1,11 @@
import { _converse, api, converse } from '@converse/headless/core';
const { Strophe } = converse.env;
import log from "@converse/headless/log.js";
import { _converse, api, converse } from '@converse/headless/core.js';
const { Strophe, sizzle } = converse.env;
export async function checkBookmarksSupport () {
const identity = await api.disco.getIdentity('pubsub', 'pep', _converse.bare_jid);
if (_converse.allow_public_bookmarks) {
if (api.settings.get('allow_public_bookmarks')) {
return !!identity;
} else {
return api.disco.supports(Strophe.NS.PUBSUB + '#publish-options', _converse.bare_jid);
@ -16,27 +18,21 @@ export async function initBookmarks () {
}
if (await checkBookmarksSupport()) {
_converse.bookmarks = new _converse.Bookmarks();
await _converse.bookmarks.fetchBookmarks();
/**
* Triggered once the _converse.Bookmarks collection
* has been created and cached bookmarks have been fetched.
* @event _converse#bookmarksInitialized
* @example _converse.api.listen.on('bookmarksInitialized', () => { ... });
*/
api.trigger('bookmarksInitialized');
}
}
/**
* Check if the user has a bookmark with a saved nickanme
* for this groupchat and return it.
*/
export function getNicknameFromBookmark (jid) {
if (!_converse.bookmarks || !api.settings.get('allow_bookmarks')) {
if (!api.settings.get('allow_bookmarks')) {
return null;
}
const bookmark = _converse.bookmarks.findWhere({'jid': jid});
if (bookmark) {
return bookmark.get('nick');
}
return _converse.bookmarks?.get(jid)?.get('nick');
}
export function handleBookmarksPush (message) {
if (sizzle(`event[xmlns="${Strophe.NS.PUBSUB}#event"] items[node="${Strophe.NS.BOOKMARKS}"]`, message).length) {
api.waitUntil('bookmarksInitialized')
.then(() => _converse.bookmarks.createBookmarksFromStanza(message))
.catch(e => log.fatal(e));
}
return true;
}

View File

@ -1,13 +1,14 @@
/**
* @module converse-bosh
* @copyright The Converse.js contributors
* @license Mozilla Public License (MPLv2)
* @description Converse.js plugin which add support for XEP-0206: XMPP Over BOSH
*/
import 'strophe.js/src/bosh';
import log from "../log.js";
import { BOSH_WAIT } from '@converse/headless/shared/constants.js';
import { Model } from '@converse/skeletor/src/model.js';
import { _converse, api, converse } from "../core.js";
import log from "../log.js";
import { setUserJID, } from '@converse/headless/utils/init.js';
const { Strophe } = converse.env;
@ -36,13 +37,13 @@ converse.plugins.add('converse-bosh', {
}
if (_converse.jid) {
if (_converse.bosh_session.get('jid') !== _converse.jid) {
const jid = await _converse.setUserJID(_converse.jid);
const jid = await setUserJID(_converse.jid);
_converse.bosh_session.clear({'silent': true });
_converse.bosh_session.save({jid});
}
} else { // Keepalive
const jid = _converse.bosh_session.get('jid');
jid && await _converse.setUserJID(jid);
jid && await setUserJID(jid);
}
return _converse.bosh_session;
}
@ -58,12 +59,13 @@ converse.plugins.add('converse-bosh', {
xhr.onload = async function () {
if (xhr.status >= 200 && xhr.status < 400) {
const data = JSON.parse(xhr.responseText);
const jid = await _converse.setUserJID(data.jid);
const jid = await setUserJID(data.jid);
_converse.connection.attach(
jid,
data.sid,
data.rid,
_converse.connection.onConnectStatusChanged
_converse.connection.onConnectStatusChanged,
BOSH_WAIT
);
} else {
xhr.onerror();
@ -134,7 +136,7 @@ converse.plugins.add('converse-bosh', {
tokens: {
/**
* @method api.tokens.get
* @param {string} [id] The type of token to return ('rid' or 'sid').
* @param { string } [id] The type of token to return ('rid' or 'sid').
* @returns 'string' A token, either the RID or SID token depending on what's asked for.
* @example _converse.api.tokens.get('rid');
*/

View File

@ -1,9 +1,9 @@
/**
* @copyright 2020, the Converse.js contributors
* @copyright 2022, the Converse.js contributors
* @license Mozilla Public License (MPLv2)
*/
import { api, converse } from '@converse/headless/core';
import { createCapsNode } from './utils.js';
import { addCapsNode } from './utils.js';
const { Strophe } = converse.env;
@ -15,7 +15,7 @@ converse.plugins.add('converse-caps', {
dependencies: ['converse-status'],
initialize () {
api.listen.on('constructedPresence', (_, p) => (p.root().cnode(createCapsNode()).up() && p));
api.listen.on('constructedMUCPresence', (_, p) => (p.root().cnode(createCapsNode()).up() && p));
api.listen.on('constructedPresence', (_, p) => addCapsNode(p));
api.listen.on('constructedMUCPresence', (_, p) => addCapsNode(p));
}
});

View File

@ -1,5 +1,5 @@
import SHA1 from 'strophe.js/src/sha1';
import { _converse, converse } from '@converse/headless/core';
import { _converse, converse } from '@converse/headless/core.js';
import { arrayBufferToBase64, stringToArrayBuffer } from '@converse/headless/utils/arraybuffer.js';
const { Strophe, $build } = converse.env;
@ -7,7 +7,7 @@ function propertySort (array, property) {
return array.sort((a, b) => { return a[property] > b[property] ? -1 : 1 });
}
function generateVerificationString () {
async function generateVerificationString () {
const identities = _converse.api.disco.own.identities.get();
const features = _converse.api.disco.own.features.get();
@ -20,14 +20,27 @@ function generateVerificationString () {
let S = identities.reduce((result, id) => `${result}${id.category}/${id.type}/${id?.lang ?? ''}/${id.name}<`, "");
features.sort();
S = features.reduce((result, feature) => `${result}${feature}<`, S);
return SHA1.b64_sha1(S);
const ab = await crypto.subtle.digest('SHA-1', stringToArrayBuffer(S));
return arrayBufferToBase64(ab);
}
export function createCapsNode () {
async function createCapsNode () {
return $build("c", {
'xmlns': Strophe.NS.CAPS,
'hash': "sha-1",
'node': "https://conversejs.org",
'ver': generateVerificationString()
}).nodeTree;
'ver': await generateVerificationString()
}).tree();
}
/**
* Given a stanza, adds a XEP-0115 CAPS element
* @param { Element } stanza
*/
export async function addCapsNode (stanza) {
const caps_el = await createCapsNode();
stanza.root().cnode(caps_el).up();
return stanza;
}

View File

@ -1,52 +0,0 @@
/**
* @module converse-carbons
* @copyright The Converse.js contributors
* @license Mozilla Public License (MPLv2)
* @description Implements support for XEP-0280 Message Carbons
*/
import log from '@converse/headless/log';
import { Strophe } from 'strophe.js/src/strophe';
import { _converse, api, converse } from "../core.js";
/* Ask the XMPP server to enable Message Carbons
* See XEP-0280 https://xmpp.org/extensions/xep-0280.html#enabling
*/
function enableCarbons (reconnecting) {
if (reconnecting) {
_converse.session?.set({'carbons_enabled': false})
}
if (!api.settings.get("message_carbons") || _converse.session?.get('carbons_enabled')) {
return;
}
const carbons_iq = new Strophe.Builder('iq', {
'from': _converse.connection.jid,
'id': 'enablecarbons',
'type': 'set'
})
.c('enable', {xmlns: Strophe.NS.CARBONS});
_converse.connection.addHandler((iq) => {
if (iq.querySelectorAll('error').length > 0) {
log.warn('An error occurred while trying to enable message carbons.');
} else {
_converse.session.set({'carbons_enabled': true});
log.debug('Message carbons have been enabled.');
}
_converse.session.save(); // Gather multiple sets into one save
}, null, "iq", null, "enablecarbons");
_converse.connection.send(carbons_iq);
}
converse.plugins.add('converse-carbons', {
initialize () {
api.settings.extend({
message_carbons: true
});
api.listen.on('afterResourceBinding', enableCarbons);
}
});

View File

@ -13,7 +13,7 @@ export default {
/**
* @method api.chats.create
* @param {string|string[]} jid|jids An jid or array of jids
* @param {object} [attrs] An object containing configuration attributes.
* @param { object } [attrs] An object containing configuration attributes.
*/
async create (jids, attrs) {
if (typeof jids === 'string') {
@ -44,9 +44,9 @@ export default {
*
* @method api.chats.open
* @param {String|string[]} name - e.g. 'buddy@example.com' or ['buddy1@example.com', 'buddy2@example.com']
* @param {Object} [attrs] - Attributes to be set on the _converse.ChatBox model.
* @param {Boolean} [attrs.minimized] - Should the chat be created in minimized state.
* @param {Boolean} [force=false] - By default, a minimized
* @param { Object } [attrs] - Attributes to be set on the _converse.ChatBox model.
* @param { Boolean } [attrs.minimized] - Should the chat be created in minimized state.
* @param { Boolean } [force=false] - By default, a minimized
* chat won't be maximized (in `overlayed` view mode) and in
* `fullscreen` view mode a newly opened chat won't replace
* another chat already in the foreground.
@ -102,8 +102,8 @@ export default {
*
* @method api.chats.get
* @param {String|string[]} jids - e.g. 'buddy@example.com' or ['buddy1@example.com', 'buddy2@example.com']
* @param {Object} [attrs] - Attributes to be set on the _converse.ChatBox model.
* @param {Boolean} [create=false] - Whether the chat should be created if it's not found.
* @param { Object } [attrs] - Attributes to be set on the _converse.ChatBox model.
* @param { Boolean } [create=false] - Whether the chat should be created if it's not found.
* @returns { Promise<_converse.ChatBox> }
*
* @example

View File

@ -1,29 +1,23 @@
/**
* @copyright 2020, the Converse.js contributors
* @copyright 2022, the Converse.js contributors
* @license Mozilla Public License (MPLv2)
*/
import ChatBox from './model.js';
import MessageMixin from './message.js';
import ModelWithContact from './model-with-contact.js';
import chat_api from './api.js';
import { Collection } from "@converse/skeletor/src/collection";
import { Collection } from '@converse/skeletor/src/collection';
import { _converse, api, converse } from '../../core.js';
import { autoJoinChats, handleMessageStanza, onClearSession, openChat, registerMessageHandlers } from './utils.js';
import {
autoJoinChats,
enableCarbons,
handleMessageStanza,
onClearSession,
openChat,
registerMessageHandlers,
} from './utils.js';
converse.plugins.add('converse-chat', {
/* Optional dependencies are other plugins which might be
* overridden or relied upon, and therefore need to be loaded before
* this plugin. They are called "optional" because they might not be
* available, in which case any overrides applicable to them will be
* ignored.
*
* It's possible however to make optional dependencies non-optional.
* If the setting "strict_plugin_dependencies" is set to true,
* an error will be raised if the plugin is not found.
*
* NB: These plugins need to have already been loaded via require.js.
*/
dependencies: ['converse-chatboxes', 'converse-disco'],
initialize () {
@ -40,14 +34,14 @@ converse.plugins.add('converse-chat', {
'filter_by_resource': false,
'prune_messages_above': undefined,
'pruning_behavior': 'unscrolled',
'send_chat_markers': ["received", "displayed", "acknowledged"],
'send_chat_markers': ['received', 'displayed', 'acknowledged'],
'send_chat_state_notifications': true,
});
_converse.Message = ModelWithContact.extend(MessageMixin);
_converse.Messages = Collection.extend({
model: _converse.Message,
comparator: 'time'
comparator: 'time',
});
Object.assign(_converse, { ChatBox, handleMessageStanza });
@ -58,5 +52,8 @@ converse.plugins.add('converse-chat', {
api.listen.on('chatBoxesFetched', autoJoinChats);
api.listen.on('presencesInitialized', registerMessageHandlers);
api.listen.on('clearSession', onClearSession);
}
api.listen.on('connected', () => enableCarbons());
api.listen.on('reconnected', () => enableCarbons());
},
});

View File

@ -4,11 +4,11 @@ import log from '../../log.js';
import { _converse, api, converse } from '../../core.js';
import { getOpenPromise } from '@converse/openpromise';
const u = converse.env.utils;
const { Strophe } = converse.env;
const { Strophe, sizzle, u } = converse.env;
/**
* Mixin which turns a `ModelWithContact` model into a non-MUC message. These can be either `chat` messages or `headline` messages.
* Mixin which turns a `ModelWithContact` model into a non-MUC message.
* These can be either `chat`, `normal` or `headline` messages.
* @mixin
* @namespace _converse.Message
* @memberOf _converse
@ -29,13 +29,14 @@ const MessageMixin = {
return;
}
this.initialized = getOpenPromise();
if (this.get('type') === 'chat') {
ModelWithContact.prototype.initialize.apply(this, arguments);
this.setRosterContact(Strophe.getBareJidFromJid(this.get('from')));
}
if (this.get('file')) {
this.on('change:put', this.uploadFile, this);
this.on('change:put', () => this.uploadFile());
}
// If `type` changes from `error` to `chat`, we want to set the contact. See #2733
this.on('change:type', () => this.setContact());
this.on('change:is_ephemeral', () => this.setTimerForEphemeralMessage());
await this.setContact();
this.setTimerForEphemeralMessage();
/**
* Triggered once a {@link _converse.Message} has been created and initialized.
@ -47,25 +48,26 @@ const MessageMixin = {
this.initialized.resolve();
},
setContact () {
if (['chat', 'normal'].includes(this.get('type'))) {
ModelWithContact.prototype.initialize.apply(this, arguments);
this.setRosterContact(Strophe.getBareJidFromJid(this.get('from')));
}
},
/**
* Sets an auto-destruct timer for this message, if it's is_ephemeral.
* @private
* @method _converse.Message#setTimerForEphemeralMessage
* @returns { Boolean } - Indicates whether the message is
* ephemeral or not, and therefore whether the timer was set or not.
*/
setTimerForEphemeralMessage () {
const setTimer = () => {
this.ephemeral_timer = window.setTimeout(this.safeDestroy.bind(this), 10000);
};
if (this.isEphemeral()) {
setTimer();
return true;
} else {
this.on('change:is_ephemeral', () =>
this.isEphemeral() ? setTimer() : clearTimeout(this.ephemeral_timer)
);
return false;
if (this.ephemeral_timer) {
clearTimeout(this.ephemeral_timer);
}
const is_ephemeral = this.isEphemeral();
if (is_ephemeral) {
const timeout = typeof is_ephemeral === "number" ? is_ephemeral : 10000;
this.ephemeral_timer = window.setTimeout(() => this.safeDestroy(), timeout);
}
},
@ -99,7 +101,7 @@ const MessageMixin = {
try {
this.destroy();
} catch (e) {
log.error(e);
log.warn(`safeDestroy: ${e}`);
}
},
@ -141,18 +143,15 @@ const MessageMixin = {
}
const date = dayjs(this.get('time'));
return this.get('from') === prev_model.get('from') &&
!this.isMeCommand() &&
!prev_model.isMeCommand() &&
this.get('type') !== 'info' &&
prev_model.get('type') !== 'info' &&
!this.isMeCommand() && !prev_model.isMeCommand() &&
!!this.get('is_encrypted') === !!prev_model.get('is_encrypted') &&
this.get('type') === prev_model.get('type') && this.get('type') !== 'info' &&
date.isBefore(dayjs(prev_model.get('time')).add(10, 'minutes')) &&
!!this.get('is_encrypted') === !!prev_model.get('is_encrypted');
(this.get('type') === 'groupchat' ? this.get('occupant_id') === prev_model.get('occupant_id') : true);
},
getDisplayName () {
if (this.get('type') === 'groupchat') {
return this.get('nick');
} else if (this.contact) {
if (this.contact) {
return this.contact.getDisplayName();
} else if (this.vcard) {
return this.vcard.getDisplayName();
@ -162,11 +161,14 @@ const MessageMixin = {
},
getMessageText () {
const { __ } = _converse;
if (this.get('is_encrypted')) {
const { __ } = _converse;
return this.get('plaintext') || this.get('body') || __('Undecryptable OMEMO message');
} else if (['groupchat', 'chat', 'normal'].includes(this.get('type'))) {
return this.get('body');
} else {
return this.get('message');
}
return this.get('message');
},
/**
@ -194,6 +196,18 @@ const MessageMixin = {
return api.sendIQ(iq);
},
getUploadRequestMetadata (stanza) {
const headers = sizzle(`slot[xmlns="${Strophe.NS.HTTPUPLOAD}"] put header`, stanza);
// https://xmpp.org/extensions/xep-0363.html#request
// TODO: Can't set the Cookie header in JavaScipt, instead cookies need
// to be manually set via document.cookie, so we're leaving it out here.
return {
'headers': headers
.map(h => ({ 'name': h.getAttribute('name'), 'value': h.textContent }))
.filter(h => ['Authorization', 'Expires'].includes(h.name))
}
},
async getRequestSlotURL () {
const { __ } = _converse;
let stanza;
@ -207,8 +221,9 @@ const MessageMixin = {
'is_ephemeral': true
});
}
const slot = stanza.querySelector('slot');
const slot = sizzle(`slot[xmlns="${Strophe.NS.HTTPUPLOAD}"]`, stanza).pop();
if (slot) {
this.upload_metadata = this.getUploadRequestMetadata(stanza);
this.save({
'get': slot.querySelector('get').getAttribute('url'),
'put': slot.querySelector('put').getAttribute('url')
@ -224,6 +239,7 @@ const MessageMixin = {
uploadFile () {
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = async () => {
if (xhr.readyState === XMLHttpRequest.DONE) {
log.info('Status: ' + xhr.status);
@ -277,6 +293,7 @@ const MessageMixin = {
};
xhr.open('PUT', this.get('put'), true);
xhr.setRequestHeader('Content-type', this.file.type);
this.upload_metadata.headers?.forEach(h => xhr.setRequestHeader(h.name, h.value));
xhr.send(this.file);
}
};

View File

@ -1,17 +1,19 @@
import ModelWithContact from './model-with-contact.js';
import filesize from "filesize";
import isMatch from "lodash-es/isMatch";
import isObject from "lodash-es/isObject";
import log from '@converse/headless/log';
import pick from "lodash-es/pick";
import { Model } from '@converse/skeletor/src/model.js';
import { TimeoutError } from '../../shared/errors.js';
import { _converse, api, converse } from "../../core.js";
import { debouncedPruneHistory, handleCorrection } from '@converse/headless/shared/chat/utils.js';
import { filesize } from "filesize";
import { getMediaURLsMetadata } from '@converse/headless/shared/parsers.js';
import { getOpenPromise } from '@converse/openpromise';
import { initStorage } from '@converse/headless/utils/storage.js';
import { debouncedPruneHistory, pruneHistory } from '@converse/headless/shared/chat/utils.js';
import { getMediaURLs } from '@converse/headless/shared/parsers';
import { isUniView, isEmptyMessage } from '../../utils/core.js';
import { parseMessage } from './parsers.js';
import { sendMarker } from '@converse/headless/shared/actions';
import { sendMarker } from '@converse/headless/shared/actions.js';
const { Strophe, $msg } = converse.env;
@ -30,7 +32,7 @@ const ChatBox = ModelWithContact.extend({
return {
'bookmarked': false,
'chat_state': undefined,
'hidden': _converse.isUniView() && !api.settings.get('singleton'),
'hidden': isUniView() && !api.settings.get('singleton'),
'message_type': 'chat',
'nickname': undefined,
'num_unread': 0,
@ -61,7 +63,7 @@ const ChatBox = ModelWithContact.extend({
this.initMessages();
if (this.get('type') === _converse.PRIVATE_CHAT_TYPE) {
this.presence = _converse.presences.findWhere({'jid': jid}) || _converse.presences.create({'jid': jid});
this.presence = _converse.presences.get(jid) || _converse.presences.create({ jid });
await this.setRosterContact(jid);
this.presence.on('change:show', item => this.onPresenceChanged(item));
}
@ -90,17 +92,6 @@ const ChatBox = ModelWithContact.extend({
initMessages () {
this.messages = this.getMessagesCollection();
this.messages.fetched = getOpenPromise();
this.messages.fetched.then(() => {
this.pruneHistoryWhenScrolledDown();
/**
* Triggered whenever a `_converse.ChatBox` instance has fetched its messages from
* `sessionStorage` but **NOT** from the server.
* @event _converse#afterMessagesFetched
* @type {_converse.ChatBoxView | _converse.ChatRoomView}
* @example _converse.api.listen.on('afterMessagesFetched', view => { ... });
*/
api.trigger('afterMessagesFetched', this);
});
this.messages.chatbox = this;
initStorage(this.messages, this.getMessagesCacheKey());
@ -129,14 +120,14 @@ const ChatBox = ModelWithContact.extend({
}
},
afterMessagesFetched (messages) {
this.most_recent_cached_message = messages ? this.getMostRecentMessage(messages) : null;
afterMessagesFetched () {
this.pruneHistoryWhenScrolledDown();
/**
* Triggered whenever a `_converse.ChatBox` instance has fetched its messages from
* `sessionStorage` but **NOT** from the server.
* Triggered whenever a { @link _converse.ChatBox } or ${ @link _converse.ChatRoom }
* has fetched its messages from the local cache.
* @event _converse#afterMessagesFetched
* @type {_converse.ChatBox | _converse.ChatRoom}
* @example _converse.api.listen.on('afterMessagesFetched', view => { ... });
* @type { _converse.ChatBox| _converse.ChatRoom }
* @example _converse.api.listen.on('afterMessagesFetched', (chat) => { ... });
*/
api.trigger('afterMessagesFetched', this);
},
@ -146,7 +137,6 @@ const ChatBox = ModelWithContact.extend({
log.info(`Not re-fetching messages for ${this.get('jid')}`);
return;
}
this.most_recent_cached_message = null;
this.messages.fetched_flag = true;
const resolve = this.messages.fetched.resolve;
this.messages.fetch({
@ -235,7 +225,7 @@ const ChatBox = ModelWithContact.extend({
this.notifications.set('chat_state', attrs.chat_state);
}
if (u.shouldCreateMessage(attrs)) {
const msg = this.handleCorrection(attrs) || await this.createMessage(attrs);
const msg = await handleCorrection(this, attrs) || await this.createMessage(attrs);
this.notifications.set({'chat_state': null});
this.handleUnreadMessage(msg);
}
@ -245,7 +235,7 @@ const ChatBox = ModelWithContact.extend({
async onMessageUploadChanged (message) {
if (message.get('upload') === _converse.SUCCESS) {
const attrs = {
'body': message.get('message'),
'body': message.get('body'),
'spoiler_hint': message.get('spoiler_hint'),
'oob_url': message.get('oob_url')
@ -258,7 +248,7 @@ const ChatBox = ModelWithContact.extend({
onMessageAdded (message) {
if (api.settings.get('prune_messages_above') &&
(api.settings.get('pruning_behavior') === 'scrolled' || !this.ui.get('scrolled')) &&
!u.isEmptyMessage(message)
!isEmptyMessage(message)
) {
debouncedPruneHistory(this);
}
@ -271,9 +261,9 @@ const ChatBox = ModelWithContact.extend({
this.messages.trigger('reset');
log.error(e);
} finally {
delete this.msg_chain;
delete this.messages.fetched_flag;
this.messages.fetched = getOpenPromise();
// No point in fetching messages from the cache if it's been cleared.
// Make sure to resolve the fetched promise to avoid freezes.
this.messages.fetched.resolve();
}
},
@ -351,7 +341,7 @@ const ChatBox = ModelWithContact.extend({
api.settings.get('pruning_behavior') === 'unscrolled' &&
!this.ui.get('scrolled')
) {
pruneHistory(this);
debouncedPruneHistory(this);
}
},
@ -379,11 +369,12 @@ const ChatBox = ModelWithContact.extend({
},
async createMessageFromError (error) {
if (error instanceof _converse.TimeoutError) {
if (error instanceof TimeoutError) {
const msg = await this.createMessage({
'type': 'error',
'message': error.message,
'retry_event_id': error.retry_event_id
'retry_event_id': error.retry_event_id,
'is_ephemeral': 30000,
});
msg.error = error;
}
@ -440,10 +431,9 @@ const ChatBox = ModelWithContact.extend({
}
},
getMostRecentMessage (messages) {
messages = messages || this.messages;
for (let i=messages.length-1; i>=0; i--) {
const message = messages.at(i);
getMostRecentMessage () {
for (let i=this.messages.length-1; i>=0; i--) {
const message = this.messages.at(i);
if (message.get('type') === this.get('message_type')) {
return message;
}
@ -451,8 +441,22 @@ const ChatBox = ModelWithContact.extend({
},
getUpdatedMessageAttributes (message, attrs) {
// Filter the attrs object, restricting it to only the `is_archived` key.
return (({ is_archived }) => ({ is_archived }))(attrs)
if (!attrs.error_type && message.get('error_type') === 'Decryption') {
// Looks like we have a failed decrypted message stored, and now
// we have a properly decrypted version of the same message.
// See issue: https://github.com/conversejs/converse.js/issues/2733#issuecomment-1035493594
return Object.assign({}, attrs, {
error_condition: undefined,
error_message: undefined,
error_text: undefined,
error_type: undefined,
is_archived: attrs.is_archived,
is_ephemeral: false,
is_error: false,
});
} else {
return { is_archived: attrs.is_archived };
}
},
updateMessage (message, attrs) {
@ -510,9 +514,9 @@ const ChatBox = ModelWithContact.extend({
*/
shouldShowErrorMessage (attrs) {
const msg = this.getMessageReferencedByError(attrs);
if (!msg && !attrs.body) {
if (!msg && attrs.chat_state) {
// If the error refers to a message not included in our store,
// and it doesn't have a <body> tag, we assume that this was a
// and it has a chat state tag, we assume that this was a
// CSI message (which we don't store).
// See https://github.com/conversejs/converse.js/issues/1317
return;
@ -592,46 +596,6 @@ const ChatBox = ModelWithContact.extend({
return false;
},
/**
* Determines whether the passed in message attributes represent a
* message which corrects a previously received message, or an
* older message which has already been corrected.
* In both cases, update the corrected message accordingly.
* @private
* @method _converse.ChatBox#handleCorrection
* @param { object } attrs - Attributes representing a received
* message, as returned by {@link parseMessage}
* @returns { _converse.Message|undefined } Returns the corrected
* message or `undefined` if not applicable.
*/
handleCorrection (attrs) {
if (!attrs.replace_id || !attrs.from) {
return;
}
const message = this.messages.findWhere({'msgid': attrs.replace_id, 'from': attrs.from});
if (!message) {
return;
}
const older_versions = message.get('older_versions') || {};
if ((attrs.time < message.get('time')) && message.get('edited')) {
// This is an older message which has been corrected afterwards
older_versions[attrs.time] = attrs['message'];
message.save({'older_versions': older_versions});
} else {
// This is a correction of an earlier message we already received
if(Object.keys(older_versions).length) {
older_versions[message.get('edited')] = message.get('message');
}else {
older_versions[message.get('time')] = message.get('message');
}
attrs = Object.assign(attrs, {'older_versions': older_versions});
delete attrs['id']; // Delete id, otherwise a new cache entry gets created
attrs['time'] = message.get('time');
message.save(attrs);
}
return message;
},
/**
* Returns an already cached message (if it exists) based on the
* passed in attributes map.
@ -666,15 +630,16 @@ const ChatBox = ModelWithContact.extend({
},
getMessageBodyQueryAttrs (attrs) {
if (attrs.message && attrs.msgid) {
if (attrs.msgid) {
const query = {
'from': attrs.from,
'msgid': attrs.msgid
}
if (!attrs.is_encrypted) {
// XXX: Need to take XEP-428 <fallback> into consideration
if (!attrs.is_encrypted && attrs.body) {
// We can't match the message if it's a reflected
// encrypted message (e.g. via MAM or in a MUC)
query['message'] = attrs.message;
query['body'] = attrs.body;
}
return query;
}
@ -803,59 +768,80 @@ const ChatBox = ModelWithContact.extend({
* @method _converse.ChatBox#createMessageStanza
* @param { _converse.Message } message - The message object
*/
createMessageStanza (message) {
async createMessageStanza (message) {
const stanza = $msg({
'from': _converse.connection.jid,
'to': this.get('jid'),
'type': this.get('message_type'),
'id': message.get('edited') && u.getUniqueId() || message.get('msgid'),
}).c('body').t(message.get('message')).up()
}).c('body').t(message.get('body')).up()
.c(_converse.ACTIVE, {'xmlns': Strophe.NS.CHATSTATES}).root();
if (message.get('type') === 'chat') {
stanza.c('request', {'xmlns': Strophe.NS.RECEIPTS}).root();
}
if (message.get('is_spoiler')) {
if (message.get('spoiler_hint')) {
stanza.c('spoiler', {'xmlns': Strophe.NS.SPOILER}, message.get('spoiler_hint')).root();
} else {
stanza.c('spoiler', {'xmlns': Strophe.NS.SPOILER}).root();
}
}
(message.get('references') || []).forEach(reference => {
const attrs = {
'xmlns': Strophe.NS.REFERENCE,
'begin': reference.begin,
'end': reference.end,
'type': reference.type,
}
if (reference.uri) {
attrs.uri = reference.uri;
}
stanza.c('reference', attrs).root();
});
if (message.get('oob_url')) {
stanza.c('x', {'xmlns': Strophe.NS.OUTOFBAND}).c('url').t(message.get('oob_url')).root();
if (!message.get('is_encrypted')) {
if (message.get('is_spoiler')) {
if (message.get('spoiler_hint')) {
stanza.c('spoiler', {'xmlns': Strophe.NS.SPOILER}, message.get('spoiler_hint')).root();
} else {
stanza.c('spoiler', {'xmlns': Strophe.NS.SPOILER}).root();
}
}
(message.get('references') || []).forEach(reference => {
const attrs = {
'xmlns': Strophe.NS.REFERENCE,
'begin': reference.begin,
'end': reference.end,
'type': reference.type,
}
if (reference.uri) {
attrs.uri = reference.uri;
}
stanza.c('reference', attrs).root();
});
if (message.get('oob_url')) {
stanza.c('x', {'xmlns': Strophe.NS.OUTOFBAND}).c('url').t(message.get('oob_url')).root();
}
}
if (message.get('edited')) {
stanza.c('replace', {
'xmlns': Strophe.NS.MESSAGE_CORRECT,
'id': message.get('msgid')
}).root();
}
if (message.get('origin_id')) {
stanza.c('origin-id', {'xmlns': Strophe.NS.SID, 'id': message.get('origin_id')}).root();
}
return stanza;
stanza.root();
/**
* *Hook* which allows plugins to update an outgoing message stanza
* @event _converse#createMessageStanza
* @param { _converse.ChatBox | _converse.ChatRoom } - The chat from
* which this message stanza is being sent.
* @param { Object } data - Message data
* @param { _converse.Message | _converse.ChatRoomMessage } data.message
* The message object from which the stanza is created and which gets persisted to storage.
* @param { Strophe.Builder } data.stanza
* The stanza that will be sent out, as a Strophe.Builder object.
* You can use the Strophe.Builder functions to extend the stanza.
* See http://strophe.im/strophejs/doc/1.4.3/files/strophe-umd-js.html#Strophe.Builder.Functions
*/
const data = await api.hook('createMessageStanza', this, { message, stanza });
return data.stanza;
},
getOutgoingMessageAttributes (attrs) {
async getOutgoingMessageAttributes (attrs) {
await api.emojis.initialize();
const is_spoiler = !!this.get('composing_spoiler');
const origin_id = u.getUniqueId();
const text = attrs?.body;
const body = text ? u.httpToGeoUri(u.shortnamesToUnicode(text), _converse) : undefined;
return Object.assign({}, attrs, {
const body = text ? u.shortnamesToUnicode(text) : undefined;
attrs = Object.assign({}, attrs, {
'from': _converse.bare_jid,
'fullname': _converse.xmppstatus.get('fullname'),
'id': origin_id,
@ -870,7 +856,20 @@ const ChatBox = ModelWithContact.extend({
body,
is_spoiler,
origin_id
}, getMediaURLs(text));
}, getMediaURLsMetadata(text));
/**
* *Hook* which allows plugins to update the attributes of an outgoing message.
* These attributes get set on the { @link _converse.Message } or
* { @link _converse.ChatRoomMessage } and persisted to storage.
* @event _converse#getOutgoingMessageAttributes
* @param { _converse.ChatBox | _converse.ChatRoom } chat
* The chat from which this message will be sent.
* @param { MessageAttributes } attrs
* The message attributes, from which the stanza will be created.
*/
attrs = await api.hook('getOutgoingMessageAttributes', this, attrs);
return attrs;
},
/**
@ -884,17 +883,14 @@ const ChatBox = ModelWithContact.extend({
* @param { String } send_time - time when the message was sent
*/
setEditable (attrs, send_time) {
if (attrs.is_headline || u.isEmptyMessage(attrs) || attrs.sender !== 'me') {
if (attrs.is_headline || isEmptyMessage(attrs) || attrs.sender !== 'me') {
return;
}
if (api.settings.get('allow_message_corrections') === 'all') {
attrs.editable = !(attrs.file || attrs.retracted || 'oob_url' in attrs);
} else if ((api.settings.get('allow_message_corrections') === 'last') && (send_time > this.get('time_sent'))) {
this.set({'time_sent': send_time});
const msg = this.messages.findWhere({'editable': true});
if (msg) {
msg.save({'editable': false});
}
this.messages.findWhere({'editable': true})?.save({'editable': false});
attrs.editable = !(attrs.file || attrs.retracted || 'oob_url' in attrs);
}
},
@ -905,7 +901,7 @@ const ChatBox = ModelWithContact.extend({
* before the collection has been fetched.
* @async
* @private
* @method _converse.ChatBox#queueMessageCreation
* @method _converse.ChatBox#createMessage
* @param { Object } attrs
*/
async createMessage (attrs, options) {
@ -926,26 +922,39 @@ const ChatBox = ModelWithContact.extend({
* chat.sendMessage({'body': 'hello world'});
*/
async sendMessage (attrs) {
attrs = this.getOutgoingMessageAttributes(attrs);
attrs = await this.getOutgoingMessageAttributes(attrs);
let message = this.messages.findWhere('correcting')
if (message) {
const older_versions = message.get('older_versions') || {};
older_versions[message.get('time')] = message.get('message');
const edited_time = message.get('edited') || message.get('time');
older_versions[edited_time] = message.getMessageText();
message.save({
'correcting': false,
'edited': (new Date()).toISOString(),
'message': attrs.message,
'older_versions': older_versions,
'references': attrs.references,
'is_only_emojis': attrs.is_only_emojis,
'origin_id': u.getUniqueId(),
'received': undefined
...pick(attrs, ['body', 'is_only_emojis', 'media_urls', 'references', 'is_encrypted']),
...{
'correcting': false,
'edited': (new Date()).toISOString(),
'message': attrs.body,
'ogp_metadata': [],
'origin_id': u.getUniqueId(),
'received': undefined,
older_versions,
plaintext: attrs.is_encrypted ? attrs.message : undefined,
}
});
} else {
this.setEditable(attrs, (new Date()).toISOString());
message = await this.createMessage(attrs);
}
api.send(this.createMessageStanza(message));
try {
const stanza = await this.createMessageStanza(message);
api.send(stanza);
} catch (e) {
message.destroy();
log.error(e);
return;
}
/**
* Triggered when a message is being sent out
@ -1013,6 +1022,10 @@ const ChatBox = ModelWithContact.extend({
* *Hook* which allows plugins to transform files before they'll be
* uploaded. The main use-case is to encrypt the files.
* @event _converse#beforeFileUpload
* @param { _converse.ChatBox | _converse.ChatRoom } chat
* The chat from which this file will be uploaded.
* @param { File } file
* The file that will be uploaded
*/
file = await api.hook('beforeFileUpload', this, file);
@ -1024,8 +1037,8 @@ const ChatBox = ModelWithContact.extend({
'is_ephemeral': true
});
} else {
const attrs = Object.assign(
this.getOutgoingMessageAttributes(), {
const initial_attrs = await this.getOutgoingMessageAttributes();
const attrs = Object.assign(initial_attrs, {
'file': true,
'progress': 0,
'slot_request_url': slot_request_url
@ -1040,7 +1053,7 @@ const ChatBox = ModelWithContact.extend({
},
maybeShow (force) {
if (_converse.isUniView()) {
if (isUniView()) {
const filter = c => !c.get('hidden') &&
c.get('jid') !== this.get('jid') &&
c.get('id') !== 'controlbox';

View File

@ -1,7 +1,7 @@
import dayjs from 'dayjs';
import log from '@converse/headless/log';
import u from '@converse/headless/utils/core';
import { api, converse } from '@converse/headless/core';
import { _converse, api, converse } from '@converse/headless/core';
import { rejectMessage } from '@converse/headless/shared/actions';
import {
@ -11,7 +11,7 @@ import {
getCorrectionAttributes,
getEncryptionAttributes,
getErrorAttributes,
getMediaURLs,
getMediaURLsMetadata,
getOutOfBandAttributes,
getReceiptId,
getReferences,
@ -23,7 +23,7 @@ import {
isHeadline,
isServerMessage,
isValidReceiptRequest,
rejectUnencapsulatedForward,
throwErrorIfInvalidForward,
} from '@converse/headless/shared/parsers';
const { Strophe, sizzle } = converse.env;
@ -32,15 +32,12 @@ const { Strophe, sizzle } = converse.env;
/**
* Parses a passed in message stanza and returns an object of attributes.
* @method st#parseMessage
* @param { XMLElement } stanza - The message stanza
* @param { Element } stanza - The message stanza
* @param { _converse } _converse
* @returns { (MessageAttributes|Error) }
*/
export async function parseMessage (stanza, _converse) {
const err = rejectUnencapsulatedForward(stanza);
if (err) {
return err;
}
export async function parseMessage (stanza) {
throwErrorIfInvalidForward(stanza);
let to_jid = stanza.getAttribute('to');
const to_resource = Strophe.getResourceFromJid(to_jid);
@ -181,7 +178,7 @@ export async function parseMessage (stanza, _converse) {
'thread': stanza.querySelector('thread')?.textContent,
'time': delay ? dayjs(delay.getAttribute('stamp')).toISOString() : now,
'to': stanza.getAttribute('to'),
'type': stanza.getAttribute('type')
'type': stanza.getAttribute('type') || 'normal'
},
getErrorAttributes(stanza),
getOutOfBandAttributes(stanza),
@ -218,8 +215,8 @@ export async function parseMessage (stanza, _converse) {
*/
attrs = await api.hook('parseMessage', stanza, attrs);
// We call this after the hook, to allow plugins to decrypt encrypted
// We call this after the hook, to allow plugins (like omemo) to decrypt encrypted
// messages, since we need to parse the message text to determine whether
// there are media urls.
return Object.assign(attrs, getMediaURLs(attrs.is_encrypted ? attrs.plaintext : attrs.body));
return Object.assign(attrs, getMediaURLsMetadata(attrs.is_encrypted ? attrs.plaintext : attrs.body));
}

View File

@ -1,9 +1,10 @@
import { _converse, api, converse } from '@converse/headless/core.js';
import { isServerMessage, } from '@converse/headless/shared/parsers';
import { parseMessage } from './parsers.js';
import log from '@converse/headless/log.js';
import { _converse, api, converse } from '@converse/headless/core.js';
import { isArchived, isHeadline, isServerMessage, } from '@converse/headless/shared/parsers';
import { parseMessage } from './parsers.js';
import { shouldClearCache } from '@converse/headless/utils/core.js';
const { Strophe, sizzle, u } = converse.env;
const { Strophe, u } = converse.env;
export function openChat (jid) {
if (!u.isValidJID(jid)) {
@ -13,7 +14,7 @@ export function openChat (jid) {
}
export async function onClearSession () {
if (_converse.shouldClearCache()) {
if (shouldClearCache()) {
await Promise.all(
_converse.chatboxes.map(c => c.messages && c.messages.clearStore({ 'silent': true }))
);
@ -28,7 +29,9 @@ async function handleErrorMessage (stanza) {
return;
}
const chatbox = await api.chatboxes.get(from_jid);
chatbox?.handleErrorMessageStanza(stanza);
if (chatbox?.get('type') === _converse.PRIVATE_CHAT_TYPE) {
chatbox?.handleErrorMessageStanza(stanza);
}
}
export function autoJoinChats () {
@ -45,56 +48,35 @@ export function autoJoinChats () {
}
});
/**
* Triggered once any private chats have been automatically joined as
* specified by the `auto_join_private_chats` setting.
* See: https://conversejs.org/docs/html/configuration.html#auto-join-private-chats
* @event _converse#privateChatsAutoJoined
* @example _converse.api.listen.on('privateChatsAutoJoined', () => { ... });
* @example _converse.api.waitUntil('privateChatsAutoJoined').then(() => { ... });
*/
* Triggered once any private chats have been automatically joined as
* specified by the `auto_join_private_chats` setting.
* See: https://conversejs.org/docs/html/configuration.html#auto-join-private-chats
* @event _converse#privateChatsAutoJoined
* @example _converse.api.listen.on('privateChatsAutoJoined', () => { ... });
* @example _converse.api.waitUntil('privateChatsAutoJoined').then(() => { ... });
*/
api.trigger('privateChatsAutoJoined');
}
export function registerMessageHandlers () {
_converse.connection.addHandler(
stanza => {
if (sizzle(`message > result[xmlns="${Strophe.NS.MAM}"]`, stanza).pop()) {
// MAM messages are handled in converse-mam.
// We shouldn't get MAM messages here because
// they shouldn't have a `type` attribute.
log.warn(`Received a MAM message with type "chat".`);
if (
['groupchat', 'error'].includes(stanza.getAttribute('type')) ||
isHeadline(stanza) ||
isServerMessage(stanza) ||
isArchived(stanza)
) {
return true;
}
_converse.handleMessageStanza(stanza);
return true;
return _converse.handleMessageStanza(stanza) || true;
},
null,
'message',
'chat'
);
_converse.connection.addHandler(
stanza => {
// Message receipts are usually without the `type` attribute. See #1353
if (stanza.getAttribute('type') !== null) {
// TODO: currently Strophe has no way to register a handler
// for stanzas without a `type` attribute.
// We could update it to accept null to mean no attribute,
// but that would be a backward-incompatible change
return true; // Gets handled above.
}
_converse.handleMessageStanza(stanza);
return true;
},
Strophe.NS.RECEIPTS,
'message'
);
_converse.connection.addHandler(
stanza => {
handleErrorMessage(stanza);
return true;
},
stanza => handleErrorMessage(stanza) || true,
null,
'message',
'error'
@ -104,28 +86,35 @@ export function registerMessageHandlers () {
/**
* Handler method for all incoming single-user chat "message" stanzas.
* @private
* @param { MessageAttributes } attrs - The message attributes
*/
export async function handleMessageStanza (stanza) {
stanza = stanza.tree?.() ?? stanza;
if (isServerMessage(stanza)) {
// Prosody sends headline messages with type `chat`, so we need to filter them out here.
const from = stanza.getAttribute('from');
return log.info(`handleMessageStanza: Ignoring incoming server message from JID: ${from}`);
}
const attrs = await parseMessage(stanza, _converse);
let attrs;
try {
attrs = await parseMessage(stanza);
} catch (e) {
return log.error(e);
}
if (u.isErrorObject(attrs)) {
attrs.stanza && log.error(attrs.stanza);
return log.error(attrs.message);
}
const has_body = !!sizzle(`body, encrypted[xmlns="${Strophe.NS.OMEMO}"]`, stanza).length;
// XXX: Need to take XEP-428 <fallback> into consideration
const has_body = !!(attrs.body || attrs.plaintext)
const chatbox = await api.chats.get(attrs.contact_jid, { 'nickname': attrs.nick }, has_body);
await chatbox?.queueMessage(attrs);
/**
* @typedef { Object } MessageData
* An object containing the original message stanza, as well as the
* parsed attributes.
* @property { XMLElement } stanza
* @property { Element } stanza
* @property { MessageAttributes } stanza
* @property { ChatBox } chatbox
*/
@ -138,3 +127,33 @@ export async function handleMessageStanza (stanza) {
*/
api.trigger('message', data);
}
/**
* Ask the XMPP server to enable Message Carbons
* See [XEP-0280](https://xmpp.org/extensions/xep-0280.html#enabling)
* @param { Boolean } reconnecting
*/
export async function enableCarbons () {
const domain = Strophe.getDomainFromJid(_converse.bare_jid);
const supported = await api.disco.supports(Strophe.NS.CARBONS, domain);
if (!supported) {
log.warn("Not enabling carbons because it's not supported!");
return;
}
const iq = new Strophe.Builder('iq', {
'from': _converse.connection.jid,
'type': 'set'
}).c('enable', {xmlns: Strophe.NS.CARBONS});
const result = await api.sendIQ(iq, null, false);
if (result === null) {
log.warn(`A timeout occurred while trying to enable carbons`);
} else if (u.isErrorStanza(result)) {
log.warn('An error occurred while trying to enable message carbons.');
log.error(result);
} else {
log.debug('Message carbons have been enabled.');
}
}

View File

@ -16,7 +16,7 @@ const ChatBoxes = Collection.extend({
* @event _converse#chatBoxesFetched
* @type { object }
* @property { _converse.ChatBox | _converse.ChatRoom } chatbox
* @property { XMLElement } stanza
* @property { Element } stanza
* @example _converse.api.listen.on('chatBoxesFetched', obj => { ... });
* @example _converse.api.waitUntil('chatBoxesFetched').then(() => { ... });
*/

View File

@ -1,5 +1,5 @@
/**
* @copyright 2020, the Converse.js contributors
* @copyright 2022, the Converse.js contributors
* @license Mozilla Public License (MPLv2)
*/
import "../emoji/index.js";

View File

@ -24,8 +24,8 @@ export default {
stream: {
/**
* @method api.disco.stream.getFeature
* @param {String} name The feature name
* @param {String} xmlns The XML namespace
* @param { String } name The feature name
* @param { String } xmlns The XML namespace
* @example _converse.api.disco.stream.getFeature('ver', 'urn:xmpp:features:rosterver')
*/
async getFeature (name, xmlns) {
@ -57,10 +57,10 @@ export default {
* Lets you add new identities for this client (i.e. instance of Converse)
* @method api.disco.own.identities.add
*
* @param {String} category - server, client, gateway, directory, etc.
* @param {String} type - phone, pc, web, etc.
* @param {String} name - "Converse"
* @param {String} lang - en, el, de, etc.
* @param { String } category - server, client, gateway, directory, etc.
* @param { String } type - phone, pc, web, etc.
* @param { String } name - "Converse"
* @param { String } lang - en, el, de, etc.
*
* @example _converse.api.disco.own.identities.clear();
*/
@ -102,7 +102,7 @@ export default {
/**
* Lets you register new disco features for this client (i.e. instance of Converse)
* @method api.disco.own.features.add
* @param {String} name - e.g. http://jabber.org/protocol/caps
* @param { String } name - e.g. http://jabber.org/protocol/caps
* @example _converse.api.disco.own.features.add("http://jabber.org/protocol/caps");
*/
add (name) {
@ -134,8 +134,8 @@ export default {
* Query for information about an XMPP entity
*
* @method api.disco.info
* @param {string} jid The Jabber ID of the entity to query
* @param {string} [node] A specific node identifier associated with the JID
* @param { string } jid The Jabber ID of the entity to query
* @param { string } [node] A specific node identifier associated with the JID
* @returns {promise} Promise which resolves once we have a result from the server.
*/
info (jid, node) {
@ -155,8 +155,8 @@ export default {
* Query for items associated with an XMPP entity
*
* @method api.disco.items
* @param {string} jid The Jabber ID of the entity to query for items
* @param {string} [node] A specific node identifier associated with the JID
* @param { string } jid The Jabber ID of the entity to query for items
* @param { string } [node] A specific node identifier associated with the JID
* @returns {promise} Promise which resolves once we have a result from the server.
*/
items (jid, node) {
@ -184,8 +184,8 @@ export default {
* Get the corresponding `DiscoEntity` instance.
*
* @method api.disco.entities.get
* @param {string} jid The Jabber ID of the entity
* @param {boolean} [create] Whether the entity should be created if it doesn't exist.
* @param { string } jid The Jabber ID of the entity
* @param { boolean } [create] Whether the entity should be created if it doesn't exist.
* @example _converse.api.disco.entities.get(jid);
*/
async get (jid, create=false) {
@ -193,21 +193,31 @@ export default {
if (!jid) {
return _converse.disco_entities;
}
if (_converse.disco_entities === undefined && !api.connection.connected()) {
if (_converse.disco_entities === undefined) {
// Happens during tests when disco lookups happen asynchronously after teardown.
const msg = `Tried to look up entity ${jid} but _converse.disco_entities has been torn down`;
log.warn(msg);
log.warn(`Tried to look up entity ${jid} but _converse.disco_entities has been torn down`);
return;
}
const entity = _converse.disco_entities.get(jid);
if (entity || !create) {
return entity;
}
return api.disco.entities.create(jid);
return api.disco.entities.create({ jid });
},
/**
* Create a new disco entity. It's identity and features
* Return any disco items advertised on this entity
*
* @method api.disco.entities.items
* @param { string } jid The Jabber ID of the entity for which we want to fetch items
* @example api.disco.entities.items(jid);
*/
items (jid) {
return _converse.disco_entities.filter(e => e.get('parent_jids')?.includes(jid));
},
/**
* Create a new disco entity. It's identity and features
* will automatically be fetched from cache or from the
* XMPP server.
*
@ -215,14 +225,17 @@ export default {
* `ignore_cache: true` in the options parameter.
*
* @method api.disco.entities.create
* @param {string} jid The Jabber ID of the entity
* @param {object} [options] Additional options
* @param {boolean} [options.ignore_cache]
* @param { object } data
* @param { string } data.jid - The Jabber ID of the entity
* @param { string } data.parent_jid - The Jabber ID of the parent entity
* @param { string } data.name
* @param { object } [options] - Additional options
* @param { boolean } [options.ignore_cache]
* If true, fetch all features from the XMPP server instead of restoring them from cache
* @example _converse.api.disco.entities.create(jid, {'ignore_cache': true});
* @example _converse.api.disco.entities.create({ jid }, {'ignore_cache': true});
*/
create (jid, options) {
return _converse.disco_entities.create({'jid': jid}, options);
create (data, options) {
return _converse.disco_entities.create(data, options);
}
},
@ -235,11 +248,11 @@ export default {
* Return a given feature of a disco entity
*
* @method api.disco.features.get
* @param {string} feature The feature that might be
* @param { string } feature The feature that might be
* supported. In the XML stanza, this is the `var`
* attribute of the `<feature>` element. For
* example: `http://jabber.org/protocol/muc`
* @param {string} jid The JID of the entity
* @param { string } jid The JID of the entity
* (and its associated items) which should be queried
* @returns {promise} A promise which resolves with a list containing
* _converse.Entity instances representing the entity
@ -249,22 +262,56 @@ export default {
* api.disco.features.get(Strophe.NS.MAM, _converse.bare_jid);
*/
async get (feature, jid) {
if (!jid) {
throw new TypeError('You need to provide an entity JID');
}
await api.waitUntil('discoInitialized');
let entity = await api.disco.entities.get(jid, true);
if (!jid) throw new TypeError('You need to provide an entity JID');
const entity = await api.disco.entities.get(jid, true);
if (_converse.disco_entities === undefined && !api.connection.connected()) {
// Happens during tests when disco lookups happen asynchronously after teardown.
const msg = `Tried to get feature ${feature} for ${jid} but _converse.disco_entities has been torn down`;
log.warn(msg);
return;
log.warn(`Tried to get feature ${feature} for ${jid} but _converse.disco_entities has been torn down`);
return [];
}
entity = await entity.waitUntilFeaturesDiscovered;
const promises = [...entity.items.map(i => i.hasFeature(feature)), entity.hasFeature(feature)];
const promises = [
entity.getFeature(feature),
...api.disco.entities.items(jid).map(i => i.getFeature(feature))
];
const result = await Promise.all(promises);
return result.filter(isObject);
},
/**
* Returns true if an entity with the given JID, or if one of its
* associated items, supports a given feature.
*
* @method api.disco.features.has
* @param { string } feature The feature that might be
* supported. In the XML stanza, this is the `var`
* attribute of the `<feature>` element. For
* example: `http://jabber.org/protocol/muc`
* @param { string } jid The JID of the entity
* (and its associated items) which should be queried
* @returns {Promise} A promise which resolves with a boolean
* @example
* api.disco.features.has(Strophe.NS.MAM, _converse.bare_jid);
*/
async has (feature, jid) {
if (!jid) throw new TypeError('You need to provide an entity JID');
const entity = await api.disco.entities.get(jid, true);
if (_converse.disco_entities === undefined && !api.connection.connected()) {
// Happens during tests when disco lookups happen asynchronously after teardown.
log.warn(`Tried to check if ${jid} supports feature ${feature}`);
return false;
}
if (await entity.getFeature(feature)) {
return true;
}
const result = await Promise.all(api.disco.entities.items(jid).map(i => i.getFeature(feature)));
return result.map(isObject).includes(true);
}
},
@ -272,11 +319,11 @@ export default {
* Used to determine whether an entity supports a given feature.
*
* @method api.disco.supports
* @param {string} feature The feature that might be
* @param { string } feature The feature that might be
* supported. In the XML stanza, this is the `var`
* attribute of the `<feature>` element. For
* example: `http://jabber.org/protocol/muc`
* @param {string} jid The JID of the entity
* @param { string } jid The JID of the entity
* (and its associated items) which should be queried
* @returns {promise} A promise which resolves with `true` or `false`.
* @example
@ -286,16 +333,15 @@ export default {
* // The feature is not supported
* }
*/
async supports (feature, jid) {
const features = await api.disco.features.get(feature, jid) || [];
return features.length > 0;
supports (feature, jid) {
return api.disco.features.has(feature, jid);
},
/**
* Refresh the features, fields and identities associated with a
* disco entity by refetching them from the server
* @method api.disco.refresh
* @param {string} jid The JID of the entity whose features are refreshed.
* @param { string } jid The JID of the entity whose features are refreshed.
* @returns {promise} A promise which resolves once the features have been refreshed
* @example
* await api.disco.refresh('room@conference.example.org');
@ -316,7 +362,7 @@ export default {
entity.queryInfo();
} else {
// Create it if it doesn't exist
entity = await api.disco.entities.create(jid, {'ignore_cache': true});
entity = await api.disco.entities.create({ jid }, {'ignore_cache': true});
}
return entity.waitUntilFeaturesDiscovered;
},
@ -333,7 +379,7 @@ export default {
* Return all the features associated with a disco entity
*
* @method api.disco.getFeatures
* @param {string} jid The JID of the entity whose features are returned.
* @param { string } jid The JID of the entity whose features are returned.
* @returns {promise} A promise which resolves with the returned features
* @example
* const features = await api.disco.getFeatures('room@conference.example.org');
@ -355,7 +401,7 @@ export default {
* See [XEP-0129: Service Discovery Extensions](https://xmpp.org/extensions/xep-0128.html)
*
* @method api.disco.getFields
* @param {string} jid The JID of the entity whose fields are returned.
* @param { string } jid The JID of the entity whose fields are returned.
* @example
* const fields = await api.disco.getFields('room@conference.example.org');
*/
@ -378,15 +424,15 @@ export default {
* XEP-0163: https://xmpp.org/extensions/xep-0163.html#support
*
* @method api.disco.getIdentity
* @param {string} The identity category.
* @param { string } The identity category.
* In the XML stanza, this is the `category`
* attribute of the `<identity>` element.
* For example: 'pubsub'
* @param {string} type The identity type.
* @param { string } type The identity type.
* In the XML stanza, this is the `type`
* attribute of the `<identity>` element.
* For example: 'pep'
* @param {string} jid The JID of the entity which might have the identity
* @param { string } jid The JID of the entity which might have the identity
* @returns {promise} A promise which resolves with a map indicating
* whether an identity with a given type is provided by the entity.
* @example

View File

@ -11,7 +11,7 @@ const DiscoEntities = Collection.extend({
this.fetch({
add: true,
success: resolve,
error (m, e) {
error (_m, e) {
log.error(e);
reject (new Error("Could not fetch disco entities"));
}

View File

@ -1,8 +1,8 @@
import log from "@converse/headless/log.js";
import sizzle from "sizzle";
import { Collection } from "@converse/skeletor/src/collection";
import log from '@converse/headless/log.js';
import sizzle from 'sizzle';
import { Collection } from '@converse/skeletor/src/collection';
import { Model } from '@converse/skeletor/src/model.js';
import { _converse, api, converse } from "@converse/headless/core.js";
import { _converse, api, converse } from '@converse/headless/core.js';
import { getOpenPromise } from '@converse/openpromise';
const { Strophe } = converse.env;
@ -19,7 +19,7 @@ const { Strophe } = converse.env;
const DiscoEntity = Model.extend({
idAttribute: 'jid',
initialize (attrs, options) {
initialize (_, options) {
this.waitUntilFeaturesDiscovered = getOpenPromise();
this.dataforms = new Collection();
@ -29,22 +29,17 @@ const DiscoEntity = Model.extend({
this.features = new Collection();
id = `converse.features-${this.get('jid')}`;
this.features.browserStorage = _converse.createStore(id, 'session');
this.listenTo(this.features, 'add', this.onFeatureAdded)
this.listenTo(this.features, 'add', this.onFeatureAdded);
this.fields = new Collection();
id = `converse.fields-${this.get('jid')}`;
this.fields.browserStorage = _converse.createStore(id, 'session');
this.listenTo(this.fields, 'add', this.onFieldAdded)
this.listenTo(this.fields, 'add', this.onFieldAdded);
this.identities = new Collection();
id = `converse.identities-${this.get('jid')}`;
this.identities.browserStorage = _converse.createStore(id, 'session');
this.fetchFeatures(options);
this.items = new _converse.DiscoEntities();
id = `converse.disco-items-${this.get('jid')}`;
this.items.browserStorage = _converse.createStore(id, 'session');
this.items.fetch();
},
/**
@ -59,7 +54,7 @@ const DiscoEntity = Model.extend({
await this.waitUntilFeaturesDiscovered;
return this.identities.findWhere({
'category': category,
'type': type
'type': type,
});
},
@ -67,12 +62,12 @@ const DiscoEntity = Model.extend({
* Returns a Promise which resolves with a map indicating
* whether a given feature is supported.
* @private
* @method _converse.DiscoEntity#hasFeature
* @method _converse.DiscoEntity#getFeature
* @param { String } feature - The feature that might be supported.
*/
async hasFeature (feature) {
await this.waitUntilFeaturesDiscovered
if (this.features.findWhere({'var': feature})) {
async getFeature (feature) {
await this.waitUntilFeaturesDiscovered;
if (this.features.findWhere({ 'var': feature })) {
return this;
}
},
@ -106,7 +101,7 @@ const DiscoEntity = Model.extend({
} else {
const store_id = this.features.browserStorage.name;
const result = await this.features.browserStorage.store.getItem(store_id);
if (result && result.length === 0 || result === null) {
if ((result && result.length === 0) || result === null) {
this.queryInfo();
} else {
this.features.fetch({
@ -114,9 +109,9 @@ const DiscoEntity = Model.extend({
success: () => {
this.waitUntilFeaturesDiscovered.resolve(this);
this.trigger('featuresDiscovered');
}
},
});
this.identities.fetch({add: true});
this.identities.fetch({ add: true });
}
}
},
@ -135,25 +130,27 @@ const DiscoEntity = Model.extend({
onDiscoItems (stanza) {
sizzle(`query[xmlns="${Strophe.NS.DISCO_ITEMS}"] item`, stanza).forEach(item => {
if (item.getAttribute("node")) {
if (item.getAttribute('node')) {
// XXX: Ignore nodes for now.
// See: https://xmpp.org/extensions/xep-0030.html#items-nodes
return;
}
const jid = item.getAttribute('jid');
if (this.items.get(jid) === undefined) {
const entity = _converse.disco_entities.get(jid);
if (entity) {
this.items.add(entity);
} else {
this.items.create({'jid': jid});
}
const entity = _converse.disco_entities.get(jid);
if (entity) {
entity.set({ parent_jids: [this.get('jid')] });
} else {
api.disco.entities.create({
jid,
'parent_jids': [this.get('jid')],
'name': item.getAttribute('name'),
});
}
});
},
async queryForItems () {
if (this.identities.where({'category': 'server'}).length === 0) {
if (this.identities.where({ 'category': 'server' }).length === 0) {
// Don't fetch features and items if this is not a
// server or a conference component.
return;
@ -162,12 +159,12 @@ const DiscoEntity = Model.extend({
this.onDiscoItems(stanza);
},
onInfo (stanza) {
async onInfo (stanza) {
Array.from(stanza.querySelectorAll('identity')).forEach(identity => {
this.identities.create({
'category': identity.getAttribute('category'),
'type': identity.getAttribute('type'),
'name': identity.getAttribute('name')
'name': identity.getAttribute('name'),
});
});
@ -176,19 +173,19 @@ const DiscoEntity = Model.extend({
sizzle('field', form).forEach(field => {
data[field.getAttribute('var')] = {
'value': field.querySelector('value')?.textContent,
'type': field.getAttribute('type')
'type': field.getAttribute('type'),
};
});
this.dataforms.create(data);
});
if (stanza.querySelector(`feature[var="${Strophe.NS.DISCO_ITEMS}"]`)) {
this.queryForItems();
await this.queryForItems();
}
Array.from(stanza.querySelectorAll('feature')).forEach(feature => {
this.features.create({
'var': feature.getAttribute('var'),
'from': stanza.getAttribute('from')
'from': stanza.getAttribute('from'),
});
});
@ -197,13 +194,13 @@ const DiscoEntity = Model.extend({
this.fields.create({
'var': field.getAttribute('var'),
'value': field.querySelector('value')?.textContent,
'from': stanza.getAttribute('from')
'from': stanza.getAttribute('from'),
});
});
this.waitUntilFeaturesDiscovered.resolve(this);
this.trigger('featuresDiscovered');
}
},
});
export default DiscoEntity;

View File

@ -2,7 +2,7 @@
describe("Service Discovery", function () {
describe("Whenever converse.js queries a server for its features", function () {
describe("Whenever a server is queried for its features", function () {
it("stores the features it receives",
mock.initConverse(
@ -76,23 +76,12 @@ describe("Service Discovery", function () {
'var': 'jabber:iq:version'});
_converse.connection._dataRecv(mock.createRequest(stanza));
let entities = await _converse.api.disco.entities.get()
expect(entities.length).toBe(2); // We have an extra entity, which is the user's JID
expect(entities.get(_converse.domain).features.length).toBe(5);
expect(entities.get(_converse.domain).identities.length).toBe(3);
expect(entities.get('montague.lit').features.where({'var': 'jabber:iq:version'}).length).toBe(1);
expect(entities.get('montague.lit').features.where({'var': 'jabber:iq:time'}).length).toBe(1);
expect(entities.get('montague.lit').features.where({'var': 'jabber:iq:register'}).length).toBe(1);
expect(entities.get('montague.lit').features.where(
{'var': 'http://jabber.org/protocol/disco#items'}).length).toBe(1);
expect(entities.get('montague.lit').features.where(
{'var': 'http://jabber.org/protocol/disco#info'}).length).toBe(1);
await u.waitUntil(function () {
// Converse.js sees that the entity has a disco#items feature,
// so it will make a query for it.
return IQ_stanzas.filter(iq => iq.querySelector('query[xmlns="http://jabber.org/protocol/disco#items"]')).length > 0;
});
/* <iq type='result'
* from='catalog.shakespeare.lit'
* to='romeo@montague.net/orchard'
@ -119,9 +108,8 @@ describe("Service Discovery", function () {
* </query>
* </iq>
*/
stanza = IQ_stanzas.find(function (iq) {
return iq.querySelector('iq[to="montague.lit"] query[xmlns="http://jabber.org/protocol/disco#items"]');
});
stanza = IQ_stanzas.find(iq => iq.querySelector('iq[to="montague.lit"] query[xmlns="http://jabber.org/protocol/disco#items"]'));
const items_IQ_id = IQ_ids[IQ_stanzas.indexOf(stanza)];
stanza = $iq({
'type': 'result',
@ -138,7 +126,6 @@ describe("Service Discovery", function () {
.c('item', {
'jid': 'words.shakespeare.lit',
'name': 'Gateway to Marlowe IM'}).up()
.c('item', {
'jid': 'montague.lit',
'node': 'books',
@ -151,16 +138,41 @@ describe("Service Discovery", function () {
'node': 'music',
'name': 'Music from the time of Shakespeare'
});
_converse.connection._dataRecv(mock.createRequest(stanza));
await u.waitUntil(() => _converse.disco_entities);
entities = _converse.disco_entities;
expect(entities.length).toBe(2); // We have an extra entity, which is the user's JID
expect(entities.get(_converse.domain).items.length).toBe(3);
expect(entities.get(_converse.domain).items.pluck('jid').includes('people.shakespeare.lit')).toBeTruthy();
expect(entities.get(_converse.domain).items.pluck('jid').includes('plays.shakespeare.lit')).toBeTruthy();
expect(entities.get(_converse.domain).items.pluck('jid').includes('words.shakespeare.lit')).toBeTruthy();
expect(entities.get(_converse.domain).identities.where({'category': 'conference'}).length).toBe(1);
expect(entities.get(_converse.domain).identities.where({'category': 'directory'}).length).toBe(1);
const entities = await _converse.api.disco.entities.get()
expect(entities.length).toBe(5); // We have an extra entity, which is the user's JID
expect(entities.get(_converse.domain).features.length).toBe(5);
expect(entities.get(_converse.domain).identities.length).toBe(3);
expect(entities.get('montague.lit').features.where({'var': 'jabber:iq:version'}).length).toBe(1);
expect(entities.get('montague.lit').features.where({'var': 'jabber:iq:time'}).length).toBe(1);
expect(entities.get('montague.lit').features.where({'var': 'jabber:iq:register'}).length).toBe(1);
expect(entities.get('montague.lit').features.where(
{'var': 'http://jabber.org/protocol/disco#items'}).length).toBe(1);
expect(entities.get('montague.lit').features.where(
{'var': 'http://jabber.org/protocol/disco#info'}).length).toBe(1);
expect(entities.map(e => e.get('jid'))).toEqual([
'montague.lit',
'romeo@montague.lit',
'people.shakespeare.lit',
'plays.shakespeare.lit',
'words.shakespeare.lit'
]);
const { api, domain } = _converse;
let entity = entities.get(_converse.domain);
expect(api.disco.entities.items(domain).length).toBe(3);
expect(api.disco.entities.items(domain).map(e => e.get('jid'))).toEqual(
['people.shakespeare.lit', 'plays.shakespeare.lit', 'words.shakespeare.lit']
)
expect(entity.identities.where({'category': 'conference'}).length).toBe(1);
expect(entity.identities.where({'category': 'directory'}).length).toBe(1);
entity = entities.get('people.shakespeare.lit');
expect(entity.get('name')).toBe('Directory of Characters');
}));
});

View File

@ -14,6 +14,7 @@ function onDiscoInfoRequest (stanza) {
if (from !== null) {
iqresult.attrs({'to': from});
}
iqresult.c('query', attrs);
_converse.disco._identities.forEach(identity => {
const attrs = {
@ -28,7 +29,7 @@ function onDiscoInfoRequest (stanza) {
}
iqresult.c('identity', attrs).up();
});
_converse.disco._features.forEach(feature => iqresult.c('feature', {'var': feature}).up());
_converse.disco._features.forEach(f => iqresult.c('feature', {'var': f}).up());
api.send(iqresult.tree());
return true;
}
@ -41,9 +42,7 @@ function addClientFeatures () {
api.disco.own.features.add(Strophe.NS.CHATSTATES);
api.disco.own.features.add(Strophe.NS.DISCO_INFO);
api.disco.own.features.add(Strophe.NS.ROSTERX); // Limited support
if (api.settings.get("message_carbons")) {
api.disco.own.features.add(Strophe.NS.CARBONS);
}
api.disco.own.features.add(Strophe.NS.CARBONS);
/**
* Triggered in converse-disco once the core disco features of
* Converse have been added.
@ -66,11 +65,11 @@ export async function initializeDisco () {
_converse.disco_entities = new _converse.DiscoEntities();
const id = `converse.disco-entities-${_converse.bare_jid}`;
_converse.disco_entities.browserStorage = _converse.createStore(id, 'session');
const collection = await _converse.disco_entities.fetchEntities();
if (collection.length === 0 || !collection.get(_converse.domain)) {
// If we don't have an entity for our own XMPP server,
// create one.
_converse.disco_entities.create({'jid': _converse.domain});
// If we don't have an entity for our own XMPP server, create one.
api.disco.entities.create({'jid': _converse.domain}, {'ignore_cache': true});
}
/**
* Triggered once the `converse-disco` plugin has been initialized and the

View File

@ -1,15 +1,13 @@
/**
* @module converse-emoji
* @copyright 2020, the Converse.js contributors
* @copyright 2022, the Converse.js contributors
* @license Mozilla Public License (MPLv2)
*/
import { ASCII_REPLACE_REGEX, CODEPOINTS_REGEX } from './regexes.js';
import './utils.js';
import { Model } from '@converse/skeletor/src/model.js';
import { _converse, api, converse } from "../../core.js";
import { getOpenPromise } from '@converse/openpromise';
import { html } from 'lit';
const u = converse.env.utils;
converse.emojis = {
'initialized': false,
@ -17,200 +15,6 @@ converse.emojis = {
};
const ASCII_LIST = {
'*\\0/*':'1f646', '*\\O/*':'1f646', '-___-':'1f611', ':\'-)':'1f602', '\':-)':'1f605', '\':-D':'1f605', '>:-)':'1f606', '\':-(':'1f613',
'>:-(':'1f620', ':\'-(':'1f622', 'O:-)':'1f607', '0:-3':'1f607', '0:-)':'1f607', '0;^)':'1f607', 'O;-)':'1f607', '0;-)':'1f607', 'O:-3':'1f607',
'-__-':'1f611', ':-Þ':'1f61b', '</3':'1f494', ':\')':'1f602', ':-D':'1f603', '\':)':'1f605', '\'=)':'1f605', '\':D':'1f605', '\'=D':'1f605',
'>:)':'1f606', '>;)':'1f606', '>=)':'1f606', ';-)':'1f609', '*-)':'1f609', ';-]':'1f609', ';^)':'1f609', '\':(':'1f613', '\'=(':'1f613',
':-*':'1f618', ':^*':'1f618', '>:P':'1f61c', 'X-P':'1f61c', '>:[':'1f61e', ':-(':'1f61e', ':-[':'1f61e', '>:(':'1f620', ':\'(':'1f622',
';-(':'1f622', '>.<':'1f623', '#-)':'1f635', '%-)':'1f635', 'X-)':'1f635', '\\0/':'1f646', '\\O/':'1f646', '0:3':'1f607', '0:)':'1f607',
'O:)':'1f607', 'O=)':'1f607', 'O:3':'1f607', 'B-)':'1f60e', '8-)':'1f60e', 'B-D':'1f60e', '8-D':'1f60e', '-_-':'1f611', '>:\\':'1f615',
'>:/':'1f615', ':-/':'1f615', ':-.':'1f615', ':-P':'1f61b', ':Þ':'1f61b', ':-b':'1f61b', ':-O':'1f62e', 'O_O':'1f62e', '>:O':'1f62e',
':-X':'1f636', ':-#':'1f636', ':-)':'1f642', '(y)':'1f44d', '<3':'2764', ':D':'1f603', '=D':'1f603', ';)':'1f609', '*)':'1f609',
';]':'1f609', ';D':'1f609', ':*':'1f618', '=*':'1f618', ':(':'1f61e', ':[':'1f61e', '=(':'1f61e', ':@':'1f620', ';(':'1f622', 'D:':'1f628',
':$':'1f633', '=$':'1f633', '#)':'1f635', '%)':'1f635', 'X)':'1f635', 'B)':'1f60e', '8)':'1f60e', ':/':'1f615', ':\\':'1f615', '=/':'1f615',
'=\\':'1f615', ':L':'1f615', '=L':'1f615', ':P':'1f61b', '=P':'1f61b', ':b':'1f61b', ':O':'1f62e', ':X':'1f636', ':#':'1f636', '=X':'1f636',
'=#':'1f636', ':)':'1f642', '=]':'1f642', '=)':'1f642', ':]':'1f642'
};
function toCodePoint(unicode_surrogates) {
const r = [];
let p = 0;
let i = 0;
while (i < unicode_surrogates.length) {
const c = unicode_surrogates.charCodeAt(i++);
if (p) {
r.push((0x10000 + ((p - 0xD800) << 10) + (c - 0xDC00)).toString(16));
p = 0;
} else if (0xD800 <= c && c <= 0xDBFF) {
p = c;
} else {
r.push(c.toString(16));
}
}
return r.join('-');
}
function fromCodePoint (codepoint) {
let code = typeof codepoint === 'string' ? parseInt(codepoint, 16) : codepoint;
if (code < 0x10000) {
return String.fromCharCode(code);
}
code -= 0x10000;
return String.fromCharCode(
0xD800 + (code >> 10),
0xDC00 + (code & 0x3FF)
);
}
function convert (unicode) {
// Converts unicode code points and code pairs to their respective characters
if (unicode.indexOf("-") > -1) {
const parts = [],
s = unicode.split('-');
for (let i = 0; i < s.length; i++) {
let part = parseInt(s[i], 16);
if (part >= 0x10000 && part <= 0x10FFFF) {
const hi = Math.floor((part - 0x10000) / 0x400) + 0xD800;
const lo = ((part - 0x10000) % 0x400) + 0xDC00;
part = (String.fromCharCode(hi) + String.fromCharCode(lo));
} else {
part = String.fromCharCode(part);
}
parts.push(part);
}
return parts.join('');
}
return fromCodePoint(unicode);
}
function unique (arr) {
return [...new Set(arr)];
}
function getTonedEmojis () {
if (!converse.emojis.toned) {
converse.emojis.toned = unique(
Object.values(converse.emojis.json.people)
.filter(person => person.sn.includes('_tone'))
.map(person => person.sn.replace(/_tone[1-5]/, ''))
);
}
return converse.emojis.toned;
}
export function convertASCII2Emoji (str) {
// Replace ASCII smileys
return str.replace(ASCII_REPLACE_REGEX, (entire, m1, m2, m3) => {
if( (typeof m3 === 'undefined') || (m3 === '') || (!(u.unescapeHTML(m3) in ASCII_LIST)) ) {
// if the ascii doesnt exist just return the entire match
return entire;
}
m3 = u.unescapeHTML(m3);
const unicode = ASCII_LIST[m3].toUpperCase();
return m2+convert(unicode);
});
}
export function getEmojiMarkup (data, options={unicode_only: false, add_title_wrapper: false}) {
const emoji = data.emoji;
const shortname = data.shortname;
if (emoji) {
if (options.unicode_only) {
return emoji;
} else if (api.settings.get('use_system_emojis')) {
if (options.add_title_wrapper) {
return shortname ? html`<span title="${shortname}">${emoji}</span>` : emoji;
} else {
return emoji;
}
} else {
const path = api.settings.get('emoji_image_path');
return html`<img class="emoji"
draggable="false"
title="${shortname}"
alt="${emoji}"
src="${path}/72x72/${data.cp}.png"/>`;
}
} else if (options.unicode_only) {
return shortname;
} else {
return html`<img class="emoji"
draggable="false"
title="${shortname}"
alt="${shortname}"
src="${converse.emojis.by_sn[shortname].url}">`;
}
}
export function getShortnameReferences (text) {
if (!converse.emojis.initialized) {
throw new Error(
'getShortnameReferences called before emojis are initialized. '+
'To avoid this problem, first await the converse.emojis.initilaized_promise.'
);
}
const references = [...text.matchAll(converse.emojis.shortnames_regex)].filter(ref => ref[0].length > 0);
return references.map(ref => {
const cp = converse.emojis.by_sn[ref[0]].cp;
return {
cp,
'begin': ref.index,
'end': ref.index+ref[0].length,
'shortname': ref[0],
'emoji': cp ? convert(cp) : null
}
});
}
function parseStringForEmojis(str, callback) {
const UFE0Fg = /\uFE0F/g;
const U200D = String.fromCharCode(0x200D);
return String(str).replace(CODEPOINTS_REGEX, (emoji, _, offset) => {
const icon_id = toCodePoint(emoji.indexOf(U200D) < 0 ? emoji.replace(UFE0Fg, '') : emoji);
if (icon_id) callback(icon_id, emoji, offset);
});
}
export function getCodePointReferences (text) {
const references = [];
parseStringForEmojis(text, (icon_id, emoji, offset) => {
references.push({
'begin': offset,
'cp': icon_id,
'emoji': emoji,
'end': offset + emoji.length,
'shortname': u.getEmojisByAtrribute('cp')[icon_id]?.sn || ''
});
});
return references;
}
function addEmojisMarkup (text, options) {
let list = [text];
[...getShortnameReferences(text), ...getCodePointReferences(text)]
.sort((a, b) => b.begin - a.begin)
.forEach(ref => {
const text = list.shift();
const emoji = getEmojiMarkup(ref, options);
if (typeof emoji === 'string') {
list = [text.slice(0, ref.begin) + emoji + text.slice(ref.end), ...list];
} else {
list = [text.slice(0, ref.begin), emoji, text.slice(ref.end), ...list];
}
});
return list;
}
converse.plugins.add('converse-emoji', {
initialize () {
@ -253,7 +57,6 @@ converse.plugins.add('converse-emoji', {
}
});
/**
* Model for storing data related to the Emoji picker widget
* @class
@ -268,98 +71,6 @@ converse.plugins.add('converse-emoji', {
}
});
/************************ BEGIN Utils ************************/
// Closured cache
const emojis_by_attribute = {};
Object.assign(u, {
/**
* Returns an emoji represented by the passed in shortname.
* Scans the passed in text for shortnames and replaces them with
* emoji unicode glyphs or alternatively if it's a custom emoji
* without unicode representation then a lit TemplateResult
* which represents image tag markup is returned.
*
* The shortname needs to be defined in `emojis.json`
* and needs to have either a `cp` attribute for the codepoint, or
* an `url` attribute which points to the source for the image.
*
* @method u.shortnamesToEmojis
* @param { String } str - String containg the shortname(s)
* @param { Object } options
* @param { Boolean } options.unicode_only - Whether emojis are rendered as
* unicode codepoints. If so, the returned result will be an array
* with containing one string, because the emojis themselves will
* also be strings. If set to false, emojis will be represented by
* lit TemplateResult objects.
* @param { Boolean } options.add_title_wrapper - Whether unicode
* codepoints should be wrapped with a `<span>` element with a
* title, so that the shortname is shown upon hovering with the
* mouse.
* @returns {Array} An array of at least one string, or otherwise
* strings and lit TemplateResult objects.
*/
shortnamesToEmojis (str, options={unicode_only: false, add_title_wrapper: false}) {
str = convertASCII2Emoji(str);
return addEmojisMarkup(str, options);
},
/**
* Replaces all shortnames in the passed in string with their
* unicode (emoji) representation.
* @method u.shortnamesToUnicode
* @param { String } str - String containing the shortname(s)
* @returns { String }
*/
shortnamesToUnicode (str) {
return u.shortnamesToEmojis(str, {'unicode_only': true})[0];
},
/**
* Determines whether the passed in string is just a single emoji shortname;
* @method u.isOnlyEmojis
* @param { String } shortname - A string which migh be just an emoji shortname
* @returns { Boolean }
*/
isOnlyEmojis (text) {
const words = text.trim().split(/\s+/);
if (words.length === 0 || words.length > 3) {
return false;
}
const emojis = words.filter(text => {
const refs = getCodePointReferences(u.shortnamesToUnicode(text));
return refs.length === 1 && (text === refs[0]['shortname'] || text === refs[0]['emoji']);
});
return emojis.length === words.length;
},
/**
* @method u.getEmojisByAtrribute
* @param { String } attr - The attribute according to which the
* returned map should be keyed.
* @returns { Object } - Map of emojis with the passed in attribute values
* as keys and a list of emojis for a particular category as values.
*/
getEmojisByAtrribute (attr) {
if (emojis_by_attribute[attr]) {
return emojis_by_attribute[attr];
}
if (attr === 'category') {
return converse.emojis.json;
}
const all_variants = converse.emojis.list
.map(e => e[attr])
.filter((c, i, arr) => arr.indexOf(c) == i);
emojis_by_attribute[attr] = {};
all_variants.forEach(v => (emojis_by_attribute[attr][v] = converse.emojis.list.find(i => i[attr] === v)));
return emojis_by_attribute[attr];
}
});
/************************ END Utils ************************/
/************************ BEGIN API ************************/
// We extend the default converse.js API to add methods specific to MUC groupchats.
Object.assign(api, {
/**
@ -375,15 +86,14 @@ converse.plugins.add('converse-emoji', {
async initialize () {
if (!converse.emojis.initialized) {
converse.emojis.initialized = true;
const { default: json } = await import(/*webpackChunkName: "emojis" */ './emoji.json');
converse.emojis.json = json;
const module = await import(/*webpackChunkName: "emojis" */ './emoji.json');
const json = converse.emojis.json = module.default;
converse.emojis.by_sn = Object.keys(json).reduce((result, cat) => Object.assign(result, json[cat]), {});
converse.emojis.list = Object.values(converse.emojis.by_sn);
converse.emojis.list.sort((a, b) => a.sn < b.sn ? -1 : (a.sn > b.sn ? 1 : 0));
converse.emojis.shortnames = converse.emojis.list.map(m => m.sn);
const getShortNames = () => converse.emojis.shortnames.map(s => s.replace(/[+]/g, "\\$&")).join('|');
converse.emojis.shortnames_regex = new RegExp(getShortNames(), "gi");
converse.emojis.toned = getTonedEmojis();
converse.emojis.initialized_promise.resolve();
}
return converse.emojis.initialized_promise;

View File

@ -0,0 +1,209 @@
import { ASCII_REPLACE_REGEX, CODEPOINTS_REGEX } from './regexes.js';
import { converse } from "../../core.js";
const { u } = converse.env;
// Closured cache
const emojis_by_attribute = {};
const ASCII_LIST = {
'*\\0/*':'1f646', '*\\O/*':'1f646', '-___-':'1f611', ':\'-)':'1f602', '\':-)':'1f605', '\':-D':'1f605', '>:-)':'1f606', '\':-(':'1f613',
'>:-(':'1f620', ':\'-(':'1f622', 'O:-)':'1f607', '0:-3':'1f607', '0:-)':'1f607', '0;^)':'1f607', 'O;-)':'1f607', '0;-)':'1f607', 'O:-3':'1f607',
'-__-':'1f611', ':-Þ':'1f61b', '</3':'1f494', ':\')':'1f602', ':-D':'1f603', '\':)':'1f605', '\'=)':'1f605', '\':D':'1f605', '\'=D':'1f605',
'>:)':'1f606', '>;)':'1f606', '>=)':'1f606', ';-)':'1f609', '*-)':'1f609', ';-]':'1f609', ';^)':'1f609', '\':(':'1f613', '\'=(':'1f613',
':-*':'1f618', ':^*':'1f618', '>:P':'1f61c', 'X-P':'1f61c', '>:[':'1f61e', ':-(':'1f61e', ':-[':'1f61e', '>:(':'1f620', ':\'(':'1f622',
';-(':'1f622', '>.<':'1f623', '#-)':'1f635', '%-)':'1f635', 'X-)':'1f635', '\\0/':'1f646', '\\O/':'1f646', '0:3':'1f607', '0:)':'1f607',
'O:)':'1f607', 'O=)':'1f607', 'O:3':'1f607', 'B-)':'1f60e', '8-)':'1f60e', 'B-D':'1f60e', '8-D':'1f60e', '-_-':'1f611', '>:\\':'1f615',
'>:/':'1f615', ':-/':'1f615', ':-.':'1f615', ':-P':'1f61b', ':Þ':'1f61b', ':-b':'1f61b', ':-O':'1f62e', 'O_O':'1f62e', '>:O':'1f62e',
':-X':'1f636', ':-#':'1f636', ':-)':'1f642', '(y)':'1f44d', '<3':'2764', ':D':'1f603', '=D':'1f603', ';)':'1f609', '*)':'1f609',
';]':'1f609', ';D':'1f609', ':*':'1f618', '=*':'1f618', ':(':'1f61e', ':[':'1f61e', '=(':'1f61e', ':@':'1f620', ';(':'1f622', 'D:':'1f628',
':$':'1f633', '=$':'1f633', '#)':'1f635', '%)':'1f635', 'X)':'1f635', 'B)':'1f60e', '8)':'1f60e', ':/':'1f615', ':\\':'1f615', '=/':'1f615',
'=\\':'1f615', ':L':'1f615', '=L':'1f615', ':P':'1f61b', '=P':'1f61b', ':b':'1f61b', ':O':'1f62e', ':X':'1f636', ':#':'1f636', '=X':'1f636',
'=#':'1f636', ':)':'1f642', '=]':'1f642', '=)':'1f642', ':]':'1f642'
};
function toCodePoint(unicode_surrogates) {
const r = [];
let p = 0;
let i = 0;
while (i < unicode_surrogates.length) {
const c = unicode_surrogates.charCodeAt(i++);
if (p) {
r.push((0x10000 + ((p - 0xD800) << 10) + (c - 0xDC00)).toString(16));
p = 0;
} else if (0xD800 <= c && c <= 0xDBFF) {
p = c;
} else {
r.push(c.toString(16));
}
}
return r.join('-');
}
function fromCodePoint (codepoint) {
let code = typeof codepoint === 'string' ? parseInt(codepoint, 16) : codepoint;
if (code < 0x10000) {
return String.fromCharCode(code);
}
code -= 0x10000;
return String.fromCharCode(
0xD800 + (code >> 10),
0xDC00 + (code & 0x3FF)
);
}
function convert (unicode) {
// Converts unicode code points and code pairs to their respective characters
if (unicode.indexOf("-") > -1) {
const parts = [],
s = unicode.split('-');
for (let i = 0; i < s.length; i++) {
let part = parseInt(s[i], 16);
if (part >= 0x10000 && part <= 0x10FFFF) {
const hi = Math.floor((part - 0x10000) / 0x400) + 0xD800;
const lo = ((part - 0x10000) % 0x400) + 0xDC00;
part = (String.fromCharCode(hi) + String.fromCharCode(lo));
} else {
part = String.fromCharCode(part);
}
parts.push(part);
}
return parts.join('');
}
return fromCodePoint(unicode);
}
export function convertASCII2Emoji (str) {
// Replace ASCII smileys
return str.replace(ASCII_REPLACE_REGEX, (entire, _, m2, m3) => {
if( (typeof m3 === 'undefined') || (m3 === '') || (!(u.unescapeHTML(m3) in ASCII_LIST)) ) {
// if the ascii doesnt exist just return the entire match
return entire;
}
m3 = u.unescapeHTML(m3);
const unicode = ASCII_LIST[m3].toUpperCase();
return m2+convert(unicode);
});
}
export function getShortnameReferences (text) {
if (!converse.emojis.initialized) {
throw new Error(
'getShortnameReferences called before emojis are initialized. '+
'To avoid this problem, first await the converse.emojis.initialized_promise'
);
}
const references = [...text.matchAll(converse.emojis.shortnames_regex)].filter(ref => ref[0].length > 0);
return references.map(ref => {
const cp = converse.emojis.by_sn[ref[0]].cp;
return {
cp,
'begin': ref.index,
'end': ref.index+ref[0].length,
'shortname': ref[0],
'emoji': cp ? convert(cp) : null
}
});
}
function parseStringForEmojis(str, callback) {
const UFE0Fg = /\uFE0F/g;
const U200D = String.fromCharCode(0x200D);
return String(str).replace(CODEPOINTS_REGEX, (emoji, _, offset) => {
const icon_id = toCodePoint(emoji.indexOf(U200D) < 0 ? emoji.replace(UFE0Fg, '') : emoji);
if (icon_id) callback(icon_id, emoji, offset);
});
}
export function getCodePointReferences (text) {
const references = [];
parseStringForEmojis(text, (icon_id, emoji, offset) => {
references.push({
'begin': offset,
'cp': icon_id,
'emoji': emoji,
'end': offset + emoji.length,
'shortname': getEmojisByAtrribute('cp')[icon_id]?.sn || ''
});
});
return references;
}
function addEmojisMarkup (text) {
let list = [text];
[...getShortnameReferences(text), ...getCodePointReferences(text)]
.sort((a, b) => b.begin - a.begin)
.forEach(ref => {
const text = list.shift();
const emoji = ref.emoji || ref.shortname;
list = [text.slice(0, ref.begin) + emoji + text.slice(ref.end), ...list];
});
return list;
}
/**
* Replaces all shortnames in the passed in string with their
* unicode (emoji) representation.
* @namespace u
* @method u.shortnamesToUnicode
* @param { String } str - String containing the shortname(s)
* @returns { String }
*/
function shortnamesToUnicode (str) {
return addEmojisMarkup(convertASCII2Emoji(str)).pop();
}
/**
* Determines whether the passed in string is just a single emoji shortname;
* @namespace u
* @method u.isOnlyEmojis
* @param { String } text - A string which migh be just an emoji shortname
* @returns { Boolean }
*/
function isOnlyEmojis (text) {
const words = text.trim().split(/\s+/);
if (words.length === 0 || words.length > 3) {
return false;
}
const emojis = words.filter(text => {
const refs = getCodePointReferences(u.shortnamesToUnicode(text));
return refs.length === 1 && (text === refs[0]['shortname'] || text === refs[0]['emoji']);
});
return emojis.length === words.length;
}
/**
* @namespace u
* @method u.getEmojisByAtrribute
* @param { 'category'|'cp'|'sn' } attr
* The attribute according to which the returned map should be keyed.
* @returns { Object }
* Map of emojis with the passed in `attr` used as key and a list of emojis as values.
*/
function getEmojisByAtrribute (attr) {
if (emojis_by_attribute[attr]) {
return emojis_by_attribute[attr];
}
if (attr === 'category') {
return converse.emojis.json;
}
const all_variants = converse.emojis.list
.map(e => e[attr])
.filter((c, i, arr) => arr.indexOf(c) == i);
emojis_by_attribute[attr] = {};
all_variants.forEach(v => (emojis_by_attribute[attr][v] = converse.emojis.list.find(i => i[attr] === v)));
return emojis_by_attribute[attr];
}
Object.assign(u, {
getEmojisByAtrribute,
isOnlyEmojis,
shortnamesToUnicode,
});

View File

@ -1,164 +0,0 @@
/**
* @module converse-headlines
* @copyright 2020, the Converse.js contributors
* @description XEP-0045 Multi-User Chat Views
*/
import { _converse, api, converse } from "@converse/headless/core";
import { isHeadline, isServerMessage } from '@converse/headless/shared/parsers';
import { parseMessage } from '@converse/headless/plugins/chat/parsers';
converse.plugins.add('converse-headlines', {
/* Plugin dependencies are other plugins which might be
* overridden or relied upon, and therefore need to be loaded before
* this plugin.
*
* If the setting "strict_plugin_dependencies" is set to true,
* an error will be raised if the plugin is not found. By default it's
* false, which means these plugins are only loaded opportunistically.
*
* NB: These plugins need to have already been loaded via require.js.
*/
dependencies: ["converse-chat"],
overrides: {
// Overrides mentioned here will be picked up by converse.js's
// plugin architecture they will replace existing methods on the
// relevant objects or classes.
//
// New functions which don't exist yet can also be added.
ChatBoxes: {
model (attrs, options) {
const { _converse } = this.__super__;
if (attrs.type == _converse.HEADLINES_TYPE) {
return new _converse.HeadlinesBox(attrs, options);
} else {
return this.__super__.model.apply(this, arguments);
}
},
}
},
initialize () {
/* The initialize function gets called as soon as the plugin is
* loaded by converse.js's plugin machinery.
*/
/**
* Shows headline messages
* @class
* @namespace _converse.HeadlinesBox
* @memberOf _converse
*/
_converse.HeadlinesBox = _converse.ChatBox.extend({
defaults () {
return {
'bookmarked': false,
'hidden': ['mobile', 'fullscreen'].includes(api.settings.get("view_mode")),
'message_type': 'headline',
'num_unread': 0,
'time_opened': this.get('time_opened') || (new Date()).getTime(),
'type': _converse.HEADLINES_TYPE
}
},
async initialize () {
this.set({'box_id': `box-${this.get('jid')}`});
this.initUI();
this.initMessages();
await this.fetchMessages();
/**
* Triggered once a {@link _converse.HeadlinesBox} has been created and initialized.
* @event _converse#headlinesBoxInitialized
* @type { _converse.HeadlinesBox }
* @example _converse.api.listen.on('headlinesBoxInitialized', model => { ... });
*/
api.trigger('headlinesBoxInitialized', this);
}
});
async function onHeadlineMessage (stanza) {
// Handler method for all incoming messages of type "headline".
if (isHeadline(stanza) || isServerMessage(stanza)) {
const from_jid = stanza.getAttribute('from');
await api.waitUntil('rosterInitialized')
if (from_jid.includes('@') &&
!_converse.roster.get(from_jid) &&
!api.settings.get("allow_non_roster_messaging")) {
return;
}
if (stanza.querySelector('body') === null) {
// Avoid creating a chat box if we have nothing to show inside it.
return;
}
const chatbox = _converse.chatboxes.create({
'id': from_jid,
'jid': from_jid,
'type': _converse.HEADLINES_TYPE,
'from': from_jid
});
const attrs = await parseMessage(stanza, _converse);
await chatbox.createMessage(attrs);
api.trigger('message', {chatbox, stanza, attrs});
}
}
/************************ BEGIN Event Handlers ************************/
function registerHeadlineHandler () {
_converse.connection.addHandler(message => (onHeadlineMessage(message) || true), null, 'message');
}
api.listen.on('connected', registerHeadlineHandler);
api.listen.on('reconnected', registerHeadlineHandler);
/************************ END Event Handlers ************************/
/************************ BEGIN API ************************/
Object.assign(api, {
/**
* The "headlines" namespace, which is used for headline-channels
* which are read-only channels containing messages of type
* "headline".
*
* @namespace api.headlines
* @memberOf api
*/
headlines: {
/**
* Retrieves a headline-channel or all headline-channels.
*
* @method api.headlines.get
* @param {String|String[]} jids - e.g. 'buddy@example.com' or ['buddy1@example.com', 'buddy2@example.com']
* @param {Object} [attrs] - Attributes to be set on the _converse.ChatBox model.
* @param {Boolean} [create=false] - Whether the chat should be created if it's not found.
* @returns { Promise<_converse.HeadlinesBox> }
*/
async get (jids, attrs={}, create=false) {
async function _get (jid) {
let model = await api.chatboxes.get(jid);
if (!model && create) {
model = await api.chatboxes.create(jid, attrs, _converse.HeadlinesBox);
} else {
model = (model && model.get('type') === _converse.HEADLINES_TYPE) ? model : null;
if (model && Object.keys(attrs).length) {
model.save(attrs);
}
}
return model;
}
if (jids === undefined) {
const chats = await api.chatboxes.get();
return chats.filter(c => (c.get('type') === _converse.HEADLINES_TYPE));
} else if (typeof jids === 'string') {
return _get(jids);
}
return Promise.all(jids.map(jid => _get(jid)));
}
}
});
/************************ END API ************************/
}
});

View File

@ -0,0 +1,44 @@
import { _converse, api } from "@converse/headless/core";
export default {
/**
* The "headlines" namespace, which is used for headline-channels
* which are read-only channels containing messages of type
* "headline".
*
* @namespace api.headlines
* @memberOf api
*/
headlines: {
/**
* Retrieves a headline-channel or all headline-channels.
*
* @method api.headlines.get
* @param {String|String[]} jids - e.g. 'buddy@example.com' or ['buddy1@example.com', 'buddy2@example.com']
* @param { Object } [attrs] - Attributes to be set on the _converse.ChatBox model.
* @param { Boolean } [create=false] - Whether the chat should be created if it's not found.
* @returns { Promise<_converse.HeadlinesFeed> }
*/
async get (jids, attrs={}, create=false) {
async function _get (jid) {
let model = await api.chatboxes.get(jid);
if (!model && create) {
model = await api.chatboxes.create(jid, attrs, _converse.HeadlinesFeed);
} else {
model = (model && model.get('type') === _converse.HEADLINES_TYPE) ? model : null;
if (model && Object.keys(attrs).length) {
model.save(attrs);
}
}
return model;
}
if (jids === undefined) {
const chats = await api.chatboxes.get();
return chats.filter(c => (c.get('type') === _converse.HEADLINES_TYPE));
} else if (typeof jids === 'string') {
return _get(jids);
}
return Promise.all(jids.map(jid => _get(jid)));
}
}
};

View File

@ -0,0 +1,31 @@
import ChatBox from '@converse/headless/plugins/chat/model.js';
import { _converse, api } from '../../core.js';
export default class HeadlinesFeed extends ChatBox {
defaults () {
return {
'bookmarked': false,
'hidden': ['mobile', 'fullscreen'].includes(api.settings.get("view_mode")),
'message_type': 'headline',
'num_unread': 0,
'time_opened': this.get('time_opened') || (new Date()).getTime(),
'type': _converse.HEADLINES_TYPE
}
}
async initialize () {
this.set({'box_id': `box-${this.get('jid')}`});
this.initUI();
this.initMessages();
await this.fetchMessages();
/**
* Triggered once a { @link _converse.HeadlinesFeed } has been created and initialized.
* @event _converse#headlinesFeedInitialized
* @type { _converse.HeadlinesFeed }
* @example _converse.api.listen.on('headlinesFeedInitialized', model => { ... });
*/
api.trigger('headlinesFeedInitialized', this);
}
}

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