Compare commits

...
266 Commits
Author SHA1 Message Date
WhkSoft a41440857d update 2023-03-10 12:49:55 +08:00
WhkSoft 3b7f71b573 Added Self-Translate 2023-02-11 21:56:43 +08:00
WhkSoft 0e79db7a3d Added Translate 2023-02-09 18:05:03 +08:00
Krishan 78951a3bc4 Rename LICENSE to LICENSE.md 2023-02-08 17:13:05 +11:00
Krishan 44318d1ecd Replace deprecated 'set-output' with '$GITHUB_OUTPUT' 2023-01-30 15:46:56 +11:00
Krishan a6fb44e1ab Release v2.2.4 2023-01-30 15:27:17 +11:00
Ajay Bura 374d2d1962 Add node polyfills (#1093)
* Add node polyfills

* remove unused polyfill

* enable fs in node polyfill

* remove polyfill aliases and crypto

* Fix build error

* Fix buffer injection
2023-01-30 15:20:53 +11:00
Ajay Bura 3ad143228d Use relative paths for build (#1094) 2023-01-30 15:20:13 +11:00
Krishan 4ea14c853e Release v2.2.3 2023-01-15 16:16:40 +11:00
Ajay Bura 38bbc1c6f5 Vite plugin to add svg as inline data (#1072)
* add vite plugin to add svg as inline data

* Add node types package
2023-01-15 09:52:58 +05:30
Stefano Pigozzi 9a34daa2bc Set accept attribute to image/* in ImageUpload (#989)
That way, browsers will suggest to the users to upload an image file instead of any kind of file.

The behaviour is in-line with Element's, which specifies the same attribute when selecting an avatar.

Please note that it does not prevent users from uploading non-image files as avatars, as browsers interpret that attribute as a mere suggestion, which can be bypassed in the file select dialog.

Partially fixes #982.
2023-01-15 09:44:16 +05:30
Ajay Bura e5e3f5f0a3 Add jsdelivr cdn for twemoji 2023-01-14 18:51:42 +05:30
Ajay Bura 899a89cb3b Replace Webpack to Vite (#1023)
* Add vite, typescript and prettier

* Configure vite

* Fix tsconfig error

* Fix manifest json

* Move manifest json to root

* Bug fix

* Move back manifest json to public
2022-12-20 20:47:51 +05:30
Krishan 63cb564818 chore: update netlify site id secrets 2022-12-14 10:47:10 +05:30
renovate[bot] e93511fde7 Lock file maintenance (#1020)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-14 08:51:14 +05:30
renovate[bot] eeac5c6c45 Update nginx Docker tag to v1.23.3 (#1019)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-14 08:45:11 +05:30
dependabot[bot] f7b48333df Bump sanitize-html from 2.7.3 to 2.8.0 (#1018)
Bumps [sanitize-html](https://github.com/apostrophecms/sanitize-html) from 2.7.3 to 2.8.0.
- [Release notes](https://github.com/apostrophecms/sanitize-html/releases)
- [Changelog](https://github.com/apostrophecms/sanitize-html/blob/main/CHANGELOG.md)
- [Commits](https://github.com/apostrophecms/sanitize-html/compare/2.7.3...2.8.0)

---
updated-dependencies:
- dependency-name: sanitize-html
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-14 08:40:14 +05:30
dependabot[bot] cb88a6fd9c Bump actions/checkout from 3.1.0 to 3.2.0 (#1017)
Bumps [actions/checkout](https://github.com/actions/checkout) from 3.1.0 to 3.2.0.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3.1.0...v3.2.0)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-13 09:19:20 +05:30
renovate[bot] 7b95546b80 Lock file maintenance (#1014)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-11 17:56:00 +05:30
dependabot[bot] 5f9ea6c06a Bump matrix-js-sdk from 21.2.0 to 22.0.0 (#1009)
Bumps [matrix-js-sdk](https://github.com/matrix-org/matrix-js-sdk) from 21.2.0 to 22.0.0.
- [Release notes](https://github.com/matrix-org/matrix-js-sdk/releases)
- [Changelog](https://github.com/matrix-org/matrix-js-sdk/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/matrix-org/matrix-js-sdk/compare/v21.2.0...v22.0.0)

---
updated-dependencies:
- dependency-name: matrix-js-sdk
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-09 16:55:21 +05:30
dependabot[bot] d54d1d964d Bump mini-css-extract-plugin from 2.7.1 to 2.7.2 (#1008)
Bumps [mini-css-extract-plugin](https://github.com/webpack-contrib/mini-css-extract-plugin) from 2.7.1 to 2.7.2.
- [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.1...v2.7.2)

---
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>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-09 16:52:50 +05:30
dependabot[bot] 868f271588 Bump nwtgck/actions-netlify from 1.2.4 to 2.0.0 (#1006)
Bumps [nwtgck/actions-netlify](https://github.com/nwtgck/actions-netlify) from 1.2.4 to 2.0.0.
- [Release notes](https://github.com/nwtgck/actions-netlify/releases)
- [Changelog](https://github.com/nwtgck/actions-netlify/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/nwtgck/actions-netlify/compare/ac1cb16858bada08a9c71a81240a85cfc3f72913...5da65c9f74c7961c5501a3ba329b8d0912f39c03)

---
updated-dependencies:
- dependency-name: nwtgck/actions-netlify
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-09 16:52:04 +05:30
dependabot[bot] 7606c9d325 Bump katex from 0.16.3 to 0.16.4 (#1007)
Bumps [katex](https://github.com/KaTeX/KaTeX) from 0.16.3 to 0.16.4.
- [Release notes](https://github.com/KaTeX/KaTeX/releases)
- [Changelog](https://github.com/KaTeX/KaTeX/blob/main/CHANGELOG.md)
- [Commits](https://github.com/KaTeX/KaTeX/compare/v0.16.3...v0.16.4)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-09 16:51:39 +05:30
dependabot[bot] 3c66a6a1c1 Bump @matrix-org/olm from 3.2.13 to 3.2.14 (#1010)
Bumps @matrix-org/olm from 3.2.13 to 3.2.14.

---
updated-dependencies:
- dependency-name: "@matrix-org/olm"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-09 16:50:52 +05:30
dependabot[bot] bf900e7468 Bump sass from 1.56.1 to 1.56.2 (#1011)
Bumps [sass](https://github.com/sass/dart-sass) from 1.56.1 to 1.56.2.
- [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.56.1...1.56.2)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-09 16:49:25 +05:30
Krishan 52cbcb9128 Replace pull request action with one actively maintained (#1004)
* Replace pull request action with one actively maintained

* Add comment_tag to stop duplicate comments
2022-12-09 13:05:02 +05:30
dependabot[bot] 97e7ba25a6 Bump webpack-cli from 4.10.0 to 5.0.1 (#1002)
Bumps [webpack-cli](https://github.com/webpack/webpack-cli) from 4.10.0 to 5.0.1.
- [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.0.1)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-06 14:26:33 +05:30
dependabot[bot] bc9ff23372 Bump matrix-js-sdk from 21.1.0 to 21.2.0 (#993)
Bumps [matrix-js-sdk](https://github.com/matrix-org/matrix-js-sdk) from 21.1.0 to 21.2.0.
- [Release notes](https://github.com/matrix-org/matrix-js-sdk/releases)
- [Changelog](https://github.com/matrix-org/matrix-js-sdk/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/matrix-org/matrix-js-sdk/compare/v21.1.0...v21.2.0)

---
updated-dependencies:
- dependency-name: matrix-js-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-06 12:58:14 +05:30
dependabot[bot] c176ed8861 Bump @babel/core from 7.20.2 to 7.20.5 (#997)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.20.2 to 7.20.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.20.5/packages/babel-core)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-06 12:54:02 +05:30
dependabot[bot] 63c0653006 Bump @khanacademy/simple-markdown from 0.8.5 to 0.8.6 (#992)
Bumps [@khanacademy/simple-markdown](https://github.com/Khan/simple-markdown) from 0.8.5 to 0.8.6.
- [Release notes](https://github.com/Khan/simple-markdown/releases)
- [Commits](https://github.com/Khan/simple-markdown/commits)

---
updated-dependencies:
- dependency-name: "@khanacademy/simple-markdown"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-06 12:52:45 +05:30
dependabot[bot] fbf899465d Bump eslint-plugin-react from 7.31.10 to 7.31.11 (#996)
Bumps [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) from 7.31.10 to 7.31.11.
- [Release notes](https://github.com/jsx-eslint/eslint-plugin-react/releases)
- [Changelog](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jsx-eslint/eslint-plugin-react/compare/v7.31.10...v7.31.11)

---
updated-dependencies:
- dependency-name: eslint-plugin-react
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-06 12:50:03 +05:30
dependabot[bot] 603e478794 Bump eslint from 8.27.0 to 8.29.0 (#1001)
Bumps [eslint](https://github.com/eslint/eslint) from 8.27.0 to 8.29.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.27.0...v8.29.0)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-06 12:48:48 +05:30
dependabot[bot] 347d23641b Bump softprops/action-gh-release from 0.1.14 to 0.1.15 (#1000)
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 0.1.14 to 0.1.15.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/softprops/action-gh-release/compare/1e07f4398721186383de40550babbdf2b84acfc5...de2c0eb89ae2a093876385947365aca7b0e5f844)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-06 12:48:17 +05:30
dependabot[bot] c4e973e83b Bump mini-css-extract-plugin from 2.6.1 to 2.7.1 (#1003)
Bumps [mini-css-extract-plugin](https://github.com/webpack-contrib/mini-css-extract-plugin) from 2.6.1 to 2.7.1.
- [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.6.1...v2.7.1)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-06 12:45:27 +05:30
renovate[bot] d22abe300b Lock file maintenance (#981)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-16 22:01:14 +05:30
renovate[bot] 2bab3119b0 Update dependency babel-loader to v8.3.0 (#980)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-16 21:56:19 +05:30
dependabot[bot] ea3d7b8892 Bump sass from 1.56.0 to 1.56.1 (#974)
Bumps [sass](https://github.com/sass/dart-sass) from 1.56.0 to 1.56.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.56.0...1.56.1)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-16 21:50:38 +05:30
dependabot[bot] 7eb2f78174 Bump webpack from 5.74.0 to 5.75.0 (#978)
Bumps [webpack](https://github.com/webpack/webpack) from 5.74.0 to 5.75.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.74.0...v5.75.0)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-16 21:50:15 +05:30
dependabot[bot] 7db04440ff Bump matrix-js-sdk from 21.0.1 to 21.1.0 (#975)
Bumps [matrix-js-sdk](https://github.com/matrix-org/matrix-js-sdk) from 21.0.1 to 21.1.0.
- [Release notes](https://github.com/matrix-org/matrix-js-sdk/releases)
- [Changelog](https://github.com/matrix-org/matrix-js-sdk/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/matrix-org/matrix-js-sdk/compare/v21.0.1...v21.1.0)

---
updated-dependencies:
- dependency-name: matrix-js-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-16 21:48:32 +05:30
dependabot[bot] 062beb718d Bump css-loader from 6.7.1 to 6.7.2 (#973)
Bumps [css-loader](https://github.com/webpack-contrib/css-loader) from 6.7.1 to 6.7.2.
- [Release notes](https://github.com/webpack-contrib/css-loader/releases)
- [Changelog](https://github.com/webpack-contrib/css-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/css-loader/compare/v6.7.1...v6.7.2)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-16 21:47:06 +05:30
dependabot[bot] b8f3cf1b47 Bump dawidd6/action-download-artifact from 2.24.0 to 2.24.2 (#972)
Bumps [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact) from 2.24.0 to 2.24.2.
- [Release notes](https://github.com/dawidd6/action-download-artifact/releases)
- [Commits](https://github.com/dawidd6/action-download-artifact/compare/46b4ae883bf0726f5949d025d31cb62c7a5ac70c...e6e25ac3a2b93187502a8be1ef9e9603afc34925)

---
updated-dependencies:
- dependency-name: dawidd6/action-download-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-16 21:45:26 +05:30
dependabot[bot] c280c1339b Bump sass-loader from 13.1.0 to 13.2.0 (#976)
Bumps [sass-loader](https://github.com/webpack-contrib/sass-loader) from 13.1.0 to 13.2.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/v13.1.0...v13.2.0)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-16 21:44:49 +05:30
Krishan 543acc9fff Revert babel-loader v9 and uninstall ajv (#979) 2022-11-16 21:43:35 +05:30
renovate[bot]andKrishan 55d609c82b Lock file maintenance (#969)
* Lock file maintenance

* Fix ajv module not found

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Krishan <33421343+kfiven@users.noreply.github.com>
2022-11-09 20:28:46 +05:30
Krishan f144c1cdbd Update Dockerfile (#970) 2022-11-09 19:36:27 +05:30
Krishan 1531535151 Replace deprecated 'set-output' with '$GITHUB_OUTPUT' (#968) 2022-11-09 18:16:14 +05:30
Krishan 4fe4c8bb03 Use Node Hydrogen LTS (#960)
* Use node hydrogen lts in dockerfile

* Use node v18.12.0

* Use node v18.12.0

* Use node v18.12.0

* use lts syntax

* Update Nodejs LTS to v18.12.1

* Update Dockerfile

* Update Dockerfile

* Update readme
2022-11-08 20:21:51 +05:30
Krishan 1302682900 Update server list in config.json (#947)
* remove kde.org from config

because they have disabled registrations, which is required to be listed on login.register page.

* remove halogen.city

seems dead hs now

* add converser.eu

seems to be working again

* Update config.json

* halogen.city is back
2022-11-08 20:20:17 +05:30
dependabot[bot]andAjay Bura 62e0821be2 Bump matrix-js-sdk from 20.1.0 to 21.0.1 (#959)
* Bump matrix-js-sdk from 20.1.0 to 21.0.0

Bumps [matrix-js-sdk](https://github.com/matrix-org/matrix-js-sdk) from 20.1.0 to 21.0.0.
- [Release notes](https://github.com/matrix-org/matrix-js-sdk/releases)
- [Changelog](https://github.com/matrix-org/matrix-js-sdk/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/matrix-org/matrix-js-sdk/compare/v20.1.0...v21.0.0)

---
updated-dependencies:
- dependency-name: matrix-js-sdk
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump matrix-js-sdk from 20.1.0 to 21.0.1

Bumps [matrix-js-sdk](https://github.com/matrix-org/matrix-js-sdk) from 20.1.0 to 21.0.1.
- [Release notes](https://github.com/matrix-org/matrix-js-sdk/releases)
- [Changelog](https://github.com/matrix-org/matrix-js-sdk/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/matrix-org/matrix-js-sdk/compare/v20.1.0...v21.0.1)

---
updated-dependencies:
- dependency-name: matrix-js-sdk
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Fix upload content

* Change min supported node

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ajay Bura <32841439+ajbura@users.noreply.github.com>
2022-11-08 20:19:22 +05:30
dependabot[bot] 856e616247 Bump @babel/core from 7.19.6 to 7.20.2 (#965)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.19.6 to 7.20.2.
- [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.20.2/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>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-08 18:45:02 +05:30
dependabot[bot] 71fdba3c4a Bump sass from 1.55.0 to 1.56.0 (#964)
Bumps [sass](https://github.com/sass/dart-sass) from 1.55.0 to 1.56.0.
- [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.55.0...1.56.0)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-08 18:43:50 +05:30
dependabot[bot] 7803bd5c06 Bump eslint from 8.26.0 to 8.27.0 (#963)
Bumps [eslint](https://github.com/eslint/eslint) from 8.26.0 to 8.27.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.26.0...v8.27.0)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-08 18:43:07 +05:30
dependabot[bot] 8dc9e01439 Bump @babel/preset-env from 7.19.4 to 7.20.2 (#966)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.19.4 to 7.20.2.
- [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.20.2/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>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-08 18:41:13 +05:30
dependabot[bot] 1d6ce13a6c Bump babel-loader from 9.0.1 to 9.1.0 (#967)
Bumps [babel-loader](https://github.com/babel/babel-loader) from 9.0.1 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/v9.0.1...v9.1.0)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-08 18:40:29 +05:30
mjarr 6a907b1542 Remove MSC3244 use from restricted room creation (#892)
* Remove MSC3244 use from restricted room creation

* Fix condition
2022-11-01 20:36:38 +05:30
dependabot[bot] bef759e358 Bump css-minimizer-webpack-plugin from 4.1.0 to 4.2.2 (#934)
Bumps [css-minimizer-webpack-plugin](https://github.com/webpack-contrib/css-minimizer-webpack-plugin) from 4.1.0 to 4.2.2.
- [Release notes](https://github.com/webpack-contrib/css-minimizer-webpack-plugin/releases)
- [Changelog](https://github.com/webpack-contrib/css-minimizer-webpack-plugin/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/css-minimizer-webpack-plugin/compare/v4.1.0...v4.2.2)

---
updated-dependencies:
- dependency-name: css-minimizer-webpack-plugin
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-01 20:11:14 +05:30
dependabot[bot] 63023c5266 Bump babel-loader from 8.2.5 to 9.0.1 (#958)
Bumps [babel-loader](https://github.com/babel/babel-loader) from 8.2.5 to 9.0.1.
- [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.0.1)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-01 17:02:31 +05:30
dependabot[bot] b6f2f9998e Bump sanitize-html from 2.7.2 to 2.7.3 (#957)
Bumps [sanitize-html](https://github.com/apostrophecms/sanitize-html) from 2.7.2 to 2.7.3.
- [Release notes](https://github.com/apostrophecms/sanitize-html/releases)
- [Changelog](https://github.com/apostrophecms/sanitize-html/blob/main/CHANGELOG.md)
- [Commits](https://github.com/apostrophecms/sanitize-html/compare/2.7.2...2.7.3)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-01 16:58:59 +05:30
dependabot[bot] 6d9115f593 Bump blurhash from 2.0.3 to 2.0.4 (#956)
Bumps [blurhash](https://github.com/woltapp/blurhash) from 2.0.3 to 2.0.4.
- [Release notes](https://github.com/woltapp/blurhash/releases)
- [Commits](https://github.com/woltapp/blurhash/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-01 16:58:04 +05:30
dependabot[bot] 02f7d7c74d Bump nginx from 1.23.1-alpine to 1.23.2-alpine (#943)
Bumps nginx from 1.23.1-alpine to 1.23.2-alpine.

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-25 10:47:03 +05:30
dependabot[bot] eeb4ec0e73 Bump actions/upload-artifact from 3.1.0 to 3.1.1 (#942)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3.1.0 to 3.1.1.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v3.1.0...v3.1.1)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-25 10:45:59 +05:30
dependabot[bot] 9efa05d4de Bump @babel/core from 7.19.3 to 7.19.6 (#944)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.19.3 to 7.19.6.
- [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.19.6/packages/babel-core)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-25 10:45:00 +05:30
dependabot[bot] 72a8483a23 Bump katex from 0.16.2 to 0.16.3 (#945)
Bumps [katex](https://github.com/KaTeX/KaTeX) from 0.16.2 to 0.16.3.
- [Release notes](https://github.com/KaTeX/KaTeX/releases)
- [Changelog](https://github.com/KaTeX/KaTeX/blob/main/CHANGELOG.md)
- [Commits](https://github.com/KaTeX/KaTeX/compare/v0.16.2...v0.16.3)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-25 10:41:07 +05:30
dependabot[bot] d4da49512c Bump eslint from 8.25.0 to 8.26.0 (#946)
Bumps [eslint](https://github.com/eslint/eslint) from 8.25.0 to 8.26.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.25.0...v8.26.0)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-25 10:39:59 +05:30
renovate[bot] 6437970f7f Lock file maintenance (#927)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-10-20 13:37:09 +05:30
dependabot[bot] bf79618221 Bump docker/setup-buildx-action from 2.2.0 to 2.2.1 (#937)
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 2.2.0 to 2.2.1.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v2.2.0...v2.2.1)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-19 21:05:05 +05:30
dependabot[bot] dbeac1f8eb Bump matrix-js-sdk from 20.0.2 to 20.1.0 (#930)
Bumps [matrix-js-sdk](https://github.com/matrix-org/matrix-js-sdk) from 20.0.2 to 20.1.0.
- [Release notes](https://github.com/matrix-org/matrix-js-sdk/releases)
- [Changelog](https://github.com/matrix-org/matrix-js-sdk/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/matrix-org/matrix-js-sdk/compare/v20.0.2...v20.1.0)

---
updated-dependencies:
- dependency-name: matrix-js-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-18 18:28:33 +05:30
dependabot[bot] 1625b8a665 Bump react-modal from 3.15.1 to 3.16.1 (#936)
Bumps [react-modal](https://github.com/reactjs/react-modal) from 3.15.1 to 3.16.1.
- [Release notes](https://github.com/reactjs/react-modal/releases)
- [Changelog](https://github.com/reactjs/react-modal/blob/master/CHANGELOG.md)
- [Commits](https://github.com/reactjs/react-modal/compare/v3.15.1...v3.16.1)

---
updated-dependencies:
- dependency-name: react-modal
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-18 12:51:42 +05:30
dependabot[bot] 5ab202e5c9 Bump @fontsource/inter from 4.5.13 to 4.5.14 (#931)
Bumps [@fontsource/inter](https://github.com/fontsource/fontsource/tree/HEAD/fonts/google/inter) from 4.5.13 to 4.5.14.
- [Release notes](https://github.com/fontsource/fontsource/releases)
- [Changelog](https://github.com/fontsource/fontsource/blob/main/CHANGELOG.md)
- [Commits](https://github.com/fontsource/fontsource/commits/HEAD/fonts/google/inter)

---
updated-dependencies:
- dependency-name: "@fontsource/inter"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-18 12:34:05 +05:30
dependabot[bot] 2f4fbc9d49 Bump react-blurhash from 0.1.3 to 0.2.0 (#932)
Bumps [react-blurhash](https://github.com/woltapp/react-blurhash) from 0.1.3 to 0.2.0.
- [Release notes](https://github.com/woltapp/react-blurhash/releases)
- [Changelog](https://github.com/woltapp/react-blurhash/blob/master/CHANGELOG.md)
- [Commits](https://github.com/woltapp/react-blurhash/commits)

---
updated-dependencies:
- dependency-name: react-blurhash
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-18 12:33:29 +05:30
dependabot[bot] 613ffefeb3 Bump util from 0.12.4 to 0.12.5 (#933)
Bumps [util](https://github.com/browserify/node-util) from 0.12.4 to 0.12.5.
- [Release notes](https://github.com/browserify/node-util/releases)
- [Changelog](https://github.com/browserify/node-util/blob/master/CHANGELOG.md)
- [Commits](https://github.com/browserify/node-util/compare/v0.12.4...v0.12.5)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-18 12:32:09 +05:30
dependabot[bot] 89e93be091 Bump docker/setup-buildx-action from 2.1.0 to 2.2.0 (#929)
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 2.1.0 to 2.2.0.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v2.1.0...v2.2.0)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-18 11:48:41 +05:30
dependabot[bot] 9b42077f7a Bump docker/metadata-action from 4.1.0 to 4.1.1 (#928)
Bumps [docker/metadata-action](https://github.com/docker/metadata-action) from 4.1.0 to 4.1.1.
- [Release notes](https://github.com/docker/metadata-action/releases)
- [Commits](https://github.com/docker/metadata-action/compare/v4.1.0...v4.1.1)

---
updated-dependencies:
- dependency-name: docker/metadata-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-18 11:47:57 +05:30
dependabot[bot] 81b88477bd Bump docker/metadata-action from 4.0.1 to 4.1.0 (#925)
Bumps [docker/metadata-action](https://github.com/docker/metadata-action) from 4.0.1 to 4.1.0.
- [Release notes](https://github.com/docker/metadata-action/releases)
- [Commits](https://github.com/docker/metadata-action/compare/v4.0.1...v4.1.0)

---
updated-dependencies:
- dependency-name: docker/metadata-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-15 15:19:18 +05:30
dependabot[bot] 52376e10a5 Bump docker/setup-buildx-action from 2.0.0 to 2.1.0 (#924)
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 2.0.0 to 2.1.0.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v2.0.0...v2.1.0)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-15 15:18:02 +05:30
dependabot[bot] b8b3f9e7ec Bump docker/login-action from 2.0.0 to 2.1.0 (#923)
Bumps [docker/login-action](https://github.com/docker/login-action) from 2.0.0 to 2.1.0.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v2.0.0...v2.1.0)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-15 15:17:21 +05:30
dependabot[bot] 194eb30042 Bump dawidd6/action-download-artifact from 2.23.0 to 2.24.0 (#922)
Bumps [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact) from 2.23.0 to 2.24.0.
- [Release notes](https://github.com/dawidd6/action-download-artifact/releases)
- [Commits](https://github.com/dawidd6/action-download-artifact/compare/7847792dd435a50521b8e3bd3576dae7459d1fa8...46b4ae883bf0726f5949d025d31cb62c7a5ac70c)

---
updated-dependencies:
- dependency-name: dawidd6/action-download-artifact
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-15 15:16:49 +05:30
dependabot[bot] b52aa9ac76 Bump nwtgck/actions-netlify from 1.2.3 to 1.2.4 (#920)
Bumps [nwtgck/actions-netlify](https://github.com/nwtgck/actions-netlify) from 1.2.3 to 1.2.4.
- [Release notes](https://github.com/nwtgck/actions-netlify/releases)
- [Changelog](https://github.com/nwtgck/actions-netlify/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/nwtgck/actions-netlify/compare/b7c1504e00c6b8a249d1848cc1b522a4865eed99...ac1cb16858bada08a9c71a81240a85cfc3f72913)

---
updated-dependencies:
- dependency-name: nwtgck/actions-netlify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-15 15:16:01 +05:30
dependabot[bot] c825c41aed Bump docker/setup-qemu-action from 2.0.0 to 2.1.0 (#921)
Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 2.0.0 to 2.1.0.
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](https://github.com/docker/setup-qemu-action/compare/v2.0.0...v2.1.0)

---
updated-dependencies:
- dependency-name: docker/setup-qemu-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-15 15:15:17 +05:30
dependabot[bot] 6d8f704542 Bump docker/build-push-action from 3.1.1 to 3.2.0 (#919)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 3.1.1 to 3.2.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v3.1.1...v3.2.0)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-15 15:14:48 +05:30
dependabot[bot] 10a399f7e6 Bump actions/setup-node from 3.5.0 to 3.5.1 (#918)
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 3.5.0 to 3.5.1.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v3.5.0...v3.5.1)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-15 15:13:55 +05:30
renovate[bot] d59a118e83 Lock file maintenance (#902)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-10-11 09:30:59 +05:30
dependabot[bot] 07570f9e8a Bump eslint-plugin-react from 7.31.8 to 7.31.10 (#912)
Bumps [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) from 7.31.8 to 7.31.10.
- [Release notes](https://github.com/jsx-eslint/eslint-plugin-react/releases)
- [Changelog](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jsx-eslint/eslint-plugin-react/compare/v7.31.8...v7.31.10)

---
updated-dependencies:
- dependency-name: eslint-plugin-react
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-11 09:26:09 +05:30
dependabot[bot] 90972e938e Bump sass-loader from 13.0.2 to 13.1.0 (#907)
Bumps [sass-loader](https://github.com/webpack-contrib/sass-loader) from 13.0.2 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/v13.0.2...v13.1.0)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-11 09:20:21 +05:30
dependabot[bot] 4297eb34c9 Bump eslint from 8.24.0 to 8.25.0 (#908)
Bumps [eslint](https://github.com/eslint/eslint) from 8.24.0 to 8.25.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.24.0...v8.25.0)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-11 09:11:49 +05:30
dependabot[bot] 507f9c3c22 Bump @babel/preset-env from 7.19.3 to 7.19.4 (#911)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.19.3 to 7.19.4.
- [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.19.4/packages/babel-preset-env)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-11 09:07:24 +05:30
dependabot[bot] 33551089ad Bump @khanacademy/simple-markdown from 0.8.4 to 0.8.5 (#910)
Bumps [@khanacademy/simple-markdown](https://github.com/Khan/simple-markdown) from 0.8.4 to 0.8.5.
- [Release notes](https://github.com/Khan/simple-markdown/releases)
- [Commits](https://github.com/Khan/simple-markdown/commits)

---
updated-dependencies:
- dependency-name: "@khanacademy/simple-markdown"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-11 09:03:45 +05:30
dependabot[bot] c8301c6ad6 Bump @matrix-org/olm from 3.2.12 to 3.2.13 (#906)
Bumps @matrix-org/olm from 3.2.12 to 3.2.13.

---
updated-dependencies:
- dependency-name: "@matrix-org/olm"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-11 09:00:52 +05:30
dependabot[bot] c3396780d7 Bump actions/checkout from 3.0.2 to 3.1.0 (#904)
Bumps [actions/checkout](https://github.com/actions/checkout) from 3.0.2 to 3.1.0.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3.0.2...v3.1.0)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-11 08:57:58 +05:30
renovate[bot] 8ea2b0b63b Lock file maintenance (#875)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-10-03 18:19:58 +05:30
dependabot[bot] e170d02bff Bump linkify-html from 4.0.1 to 4.0.2 (#894)
Bumps [linkify-html](https://github.com/Hypercontext/linkifyjs/tree/HEAD/packages/linkify-html) from 4.0.1 to 4.0.2.
- [Release notes](https://github.com/Hypercontext/linkifyjs/releases)
- [Changelog](https://github.com/Hypercontext/linkifyjs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Hypercontext/linkifyjs/commits/v4.0.2/packages/linkify-html)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-03 18:05:33 +05:30
dependabot[bot] 1f872a9b0c Bump linkifyjs from 4.0.1 to 4.0.2 (#896)
Bumps [linkifyjs](https://github.com/Hypercontext/linkifyjs/tree/HEAD/packages/linkifyjs) from 4.0.1 to 4.0.2.
- [Release notes](https://github.com/Hypercontext/linkifyjs/releases)
- [Changelog](https://github.com/Hypercontext/linkifyjs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Hypercontext/linkifyjs/commits/v4.0.2/packages/linkifyjs)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-03 18:03:14 +05:30
dependabot[bot] bcdc1d8915 Bump @fontsource/inter from 4.5.12 to 4.5.13 (#895)
Bumps [@fontsource/inter](https://github.com/fontsource/fontsource/tree/HEAD/fonts/google/inter) from 4.5.12 to 4.5.13.
- [Release notes](https://github.com/fontsource/fontsource/releases)
- [Changelog](https://github.com/fontsource/fontsource/blob/main/CHANGELOG.md)
- [Commits](https://github.com/fontsource/fontsource/commits/HEAD/fonts/google/inter)

---
updated-dependencies:
- dependency-name: "@fontsource/inter"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-03 18:02:35 +05:30
dependabot[bot] f577435e98 Bump blurhash from 2.0.2 to 2.0.3 (#893)
Bumps [blurhash](https://github.com/woltapp/blurhash) from 2.0.2 to 2.0.3.
- [Release notes](https://github.com/woltapp/blurhash/releases)
- [Commits](https://github.com/woltapp/blurhash/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-03 18:00:39 +05:30
dependabot[bot] bf94550a84 Bump matrix-js-sdk from 20.0.1 to 20.0.2 (#888)
Bumps [matrix-js-sdk](https://github.com/matrix-org/matrix-js-sdk) from 20.0.1 to 20.0.2.
- [Release notes](https://github.com/matrix-org/matrix-js-sdk/releases)
- [Changelog](https://github.com/matrix-org/matrix-js-sdk/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/matrix-org/matrix-js-sdk/compare/v20.0.1...v20.0.2)

---
updated-dependencies:
- dependency-name: matrix-js-sdk
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-01 09:07:04 +05:30
dependabot[bot] a900b04254 Bump linkify-html from 4.0.0 to 4.0.1 (#883)
Bumps [linkify-html](https://github.com/Hypercontext/linkifyjs/tree/HEAD/packages/linkify-html) from 4.0.0 to 4.0.1.
- [Release notes](https://github.com/Hypercontext/linkifyjs/releases)
- [Changelog](https://github.com/Hypercontext/linkifyjs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Hypercontext/linkifyjs/commits/v4.0.1/packages/linkify-html)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-29 10:43:08 +05:30
dependabot[bot] 3fe5a9d222 Bump linkifyjs from 4.0.0 to 4.0.1 (#884)
Bumps [linkifyjs](https://github.com/Hypercontext/linkifyjs/tree/HEAD/packages/linkifyjs) from 4.0.0 to 4.0.1.
- [Release notes](https://github.com/Hypercontext/linkifyjs/releases)
- [Changelog](https://github.com/Hypercontext/linkifyjs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Hypercontext/linkifyjs/commits/v4.0.1/packages/linkifyjs)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-29 10:35:00 +05:30
renovate[bot] a07a7676b7 Update dependency matrix-js-sdk to v20.0.1 (#882)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-29 09:48:16 +05:30
renovate[bot] 593cc03962 Update dependency blurhash to v2.0.2 (#881)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-28 22:17:11 +05:30
renovate[bot] 820f255929 Update babel monorepo to v7.19.3 (#880)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-28 22:15:39 +05:30
renovate[bot] 7db4146c8d Update actions/setup-node action to v3.5.0 (#878)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-28 22:13:06 +05:30
Ajay Bura 91a6916f4c Release v2.2.2 2022-09-28 20:48:41 +05:30
renovate[bot] 78374d0301 Update dependency matrix-js-sdk to v20 (#879)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-28 20:43:56 +05:30
Krishan 9185ee0cf9 Release v2.2.1 2022-09-28 19:26:12 +05:30
renovate[bot] e2de51832c Update dependency matrix-js-sdk to v19.7.0 (#876)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-28 19:16:07 +05:30
Ajay Bura 759f16d5b9 Fix crash on space leave 2022-09-28 18:17:15 +05:30
Ajay Bura d0ddedc2b2 Wrap view source text 2022-09-28 13:54:58 +05:30
ginnyTheCat 4291005161 Handle nested lists (#853)
* Handle nested lists

* Allow heading to not be followed by an empty line

* Don't parse as inline code if contains newlines

* Use escape rule in plain as well
2022-09-25 19:31:59 +05:30
renovate[bot] ee144ccb2b Lock file maintenance (#873)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-24 12:45:50 +05:30
renovate[bot] 7fea21f221 Update dependency sass to v1.55.0 (#872)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-24 12:43:13 +05:30
renovate[bot] 9a4b40f242 Update dependency html-loader to v4.2.0 (#871)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-24 12:40:16 +05:30
renovate[bot] c2d353b973 Update dependency eslint to v8.24.0 (#870)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-24 12:37:41 +05:30
renovate[bot] 8b6cecdbf8 Update dependency webpack-dev-server to v4.11.1 (#869)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-24 12:35:29 +05:30
renovate[bot] 83d8f2821a Update dependency @khanacademy/simple-markdown to v0.8.4 (#868)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-24 12:33:28 +05:30
Krishan 0225204b4d Require approval before opening dep update PR (#865) 2022-09-19 20:32:40 +05:30
renovate[bot] 478957803d Lock file maintenance (#858)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-19 10:07:01 +05:30
renovate[bot] 0181cb26d2 Update dependency linkifyjs to v4.0.0 (#861)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-19 10:03:45 +05:30
renovate[bot] 2ddb3595c7 Update dependency sanitize-html to v2.7.2 (#862)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-19 10:02:57 +05:30
renovate[bot] 76e49d1bd0 Update dependency linkify-html to v4.0.0 (#860)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-19 10:02:15 +05:30
renovate[bot] 91f1ee748e Update babel monorepo to v7.19.1 (#859)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-19 09:13:58 +05:30
renovate[bot] 9bddf64510 Lock file maintenance (#857)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-19 08:58:19 +05:30
Ajay Bura 2200ae143e Update sdk doc link so that it's not fixed to one version 2022-09-18 20:18:23 +05:30
Krishan 80d9a2ca7d Release v2.2.0 2022-09-17 19:04:13 +05:30
ginnyTheCat cbd1bf35c6 Only escape when editing (#852)
* Only escape when editing

* Base edit change detection on rendered content
2022-09-17 16:55:26 +05:30
Ajay Bura c1be57b205 Add clear cache btn in loading screen 2022-09-17 15:48:45 +05:30
morguldir 4848bef0dd Add Clear cache and reload button (#793)
Inspired by: https://github.com/matrix-org/matrix-react-sdk/blob/3c5c2bef6dbac51ce6e1864056523815ca4c38d9/src/components/views/elements/ErrorBoundary.tsx#L61-L68

Signed-off-by: morguldir <morguldir@protonmail.com>

Signed-off-by: morguldir <morguldir@protonmail.com>
2022-09-17 13:21:22 +05:30
ginnyTheCat a8f374dd43 Parsing HTML to Markdown AST (#847)
* Force mentions to have a space after the #

* Use types for rendering

* Parse HTML

* Add code block support

* Add table support

* Allow starting heading without a space

* Escape relevant plaintext areas

* Resolve many crashes

* Use better matrix id regex

* Don't match . after id

* Don't parse mentions as links

* Add emote support

* Only emit HTML link if necessary

* Implement review changes
2022-09-16 21:21:53 +05:30
renovate[bot] d43e41e1ba Lock file maintenance (#846)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-14 19:03:59 +05:30
dependabot[bot] 437ac4c59b Bump css-minimizer-webpack-plugin from 4.0.0 to 4.1.0 (#843)
Bumps [css-minimizer-webpack-plugin](https://github.com/webpack-contrib/css-minimizer-webpack-plugin) from 4.0.0 to 4.1.0.
- [Release notes](https://github.com/webpack-contrib/css-minimizer-webpack-plugin/releases)
- [Changelog](https://github.com/webpack-contrib/css-minimizer-webpack-plugin/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/css-minimizer-webpack-plugin/compare/v4.0.0...v4.1.0)

---
updated-dependencies:
- dependency-name: css-minimizer-webpack-plugin
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-14 16:53:47 +05:30
renovate[bot] de218409ab Update dependency matrix-js-sdk to v19.5.0 (#845)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-14 16:51:02 +05:30
dependabot[bot] 060ed859d4 Bump blurhash from 1.1.5 to 2.0.0 (#842)
Bumps [blurhash](https://github.com/woltapp/blurhash) from 1.1.5 to 2.0.0.
- [Release notes](https://github.com/woltapp/blurhash/releases)
- [Commits](https://github.com/woltapp/blurhash/commits)

---
updated-dependencies:
- dependency-name: blurhash
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-14 16:48:42 +05:30
dependabot[bot] 0783c43169 Bump webpack-dev-server from 4.10.1 to 4.11.0 (#841)
Bumps [webpack-dev-server](https://github.com/webpack/webpack-dev-server) from 4.10.1 to 4.11.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.10.1...v4.11.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>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-14 16:46:11 +05:30
dependabot[bot] b5a317e021 Bump eslint from 8.23.0 to 8.23.1 (#840)
Bumps [eslint](https://github.com/eslint/eslint) from 8.23.0 to 8.23.1.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.23.0...v8.23.1)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-14 16:44:47 +05:30
ginnyTheCat 15c1f6dadf Allow rendering messages as plaintext (#805)
* Parse room input from user id and emoji

* Add more plain outputs

* Add reply support

* Always include formatted reply

* Add room mention parser

* Allow single linebreak after codeblock

* Remove margin from math display blocks

* Escape shrug

* Rewrite HTML tag function

* Normalize def keys

* Fix embedding replies into replies

* Don't add margin to file name

* Collapse spaces in HTML message body

* Don't crash with no plaintext rendering

* Add blockquote support

* Remove ref support

* Fix image html rendering

* Remove debug output

* Remove duplicate default option value

* Add table plain rendering support

* Correctly handle paragraph padding when mixed with block content

* Simplify links if possible

* Make blockquote plain rendering better

* Don't error when emojis are matching but not found

* Allow plain only messages with newlines

* Set user id as user mention fallback

* Fix mixed up variable name

* Replace replaceAll with replace
2022-09-14 14:30:06 +05:30
dependabot[bot]andAjay Bura efda9991f2 Bump sass from 1.54.5 to 1.54.9 (#837)
Bumps [sass](https://github.com/sass/dart-sass) from 1.54.5 to 1.54.9.
- [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.54.5...1.54.9)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ajay Bura <32841439+ajbura@users.noreply.github.com>
2022-09-11 18:59:31 +05:30
dependabot[bot]andAjay Bura 9fb651a04e Bump @babel/core from 7.18.13 to 7.19.0 (#824)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.18.13 to 7.19.0.
- [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.19.0/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>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ajay Bura <32841439+ajbura@users.noreply.github.com>
2022-09-11 18:59:16 +05:30
dependabot[bot]andAjay Bura 55c652a02a Bump webpack-merge from 5.7.3 to 5.8.0 (#822)
Bumps [webpack-merge](https://github.com/survivejs/webpack-merge) from 5.7.3 to 5.8.0.
- [Release notes](https://github.com/survivejs/webpack-merge/releases)
- [Changelog](https://github.com/survivejs/webpack-merge/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/survivejs/webpack-merge/compare/v5.7.3...v5.8.0)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ajay Bura <32841439+ajbura@users.noreply.github.com>
2022-09-11 18:58:33 +05:30
dependabot[bot]andAjay Bura 2be706fb3f Bump eslint-plugin-react from 7.31.1 to 7.31.8 (#838)
Bumps [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) from 7.31.1 to 7.31.8.
- [Release notes](https://github.com/jsx-eslint/eslint-plugin-react/releases)
- [Changelog](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jsx-eslint/eslint-plugin-react/compare/v7.31.1...v7.31.8)

---
updated-dependencies:
- dependency-name: eslint-plugin-react
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ajay Bura <32841439+ajbura@users.noreply.github.com>
2022-09-11 18:57:15 +05:30
dependabot[bot]andAjay Bura 3e2cc8bfae Bump @babel/preset-env from 7.18.10 to 7.19.0 (#825)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.18.10 to 7.19.0.
- [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.19.0/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>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ajay Bura <32841439+ajbura@users.noreply.github.com>
2022-09-11 18:54:24 +05:30
dependabot[bot]andAjay Bura a6c339e13a Bump html-webpack-plugin from 5.3.1 to 5.5.0 (#829)
Bumps [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin) from 5.3.1 to 5.5.0.
- [Release notes](https://github.com/jantimon/html-webpack-plugin/releases)
- [Changelog](https://github.com/jantimon/html-webpack-plugin/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jantimon/html-webpack-plugin/compare/v5.3.1...v5.5.0)

---
updated-dependencies:
- dependency-name: html-webpack-plugin
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ajay Bura <32841439+ajbura@users.noreply.github.com>
2022-09-11 18:53:03 +05:30
ginnyTheCat b0174f3acc Delete notifications after messages have been read or deleted (#830)
* Delete read notifications

* Delete notifications for deleted messages

* Correctly remove notification
2022-09-11 18:51:59 +05:30
ginnyTheCat a343d9999e Handle messages with invalid body (#833) 2022-09-11 18:51:05 +05:30
ginnyTheCat 0a2cca6e40 Change UI label (#832) 2022-09-11 16:44:39 +05:30
Ajay Bura bca00f46a9 Add plain text command 2022-09-11 12:18:32 +05:30
Ajay Bura 5848c02d50 Remove markdown icon from input 2022-09-11 09:19:22 +05:30
Ajay Bura 29ddcfa1f9 Update command strings 2022-09-11 08:27:59 +05:30
Krishan 831bb83f4e Update and simplify actions (#831)
* Replace action with one we use already

* Simplify PR actions

* fix name
2022-09-07 13:46:44 +05:30
Ajay Bura b8a8babc88 Fix emojiboard icon background 2022-09-07 13:24:26 +05:30
Ajay Bura 4a35aa7272 Fix crash in manage device 2022-09-07 13:14:15 +05:30
Ajay Bura 2ded7d9b1f Fix crash with unknown mime type 2022-09-07 08:40:10 +05:30
Ajay Bura 19f674cf5f Fix unwanted changes 2022-09-06 14:25:13 +05:30
Ajay Bura 790bf5eac3 Fix wrong notification count 2022-09-06 14:22:56 +05:30
renovate[bot]andKrishan e1adc6a3bc Configure Renovate (#819)
* Add renovate.json

* Add renovate config

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Krishan <33421343+kfiven@users.noreply.github.com>
2022-09-05 19:43:11 +05:30
Krishan bcedab5113 Add lockfile changes action (#818) 2022-09-05 19:26:28 +05:30
Krishan adca914d67 Copy Olm directly from node modules (fixes #206) (#817) 2022-09-05 12:26:44 +05:30
Ajay Bura 8583ab19f0 Manage ignored users (#814)
* Add options to display/ignore usersId's

* Update string

* Hide search icon in encrypted rooms (#763)

* Fix styles
2022-09-05 08:30:45 +05:30
Krishan 1aa16a43ee Pin all deps for greatest reliability/predictability (#812) 2022-09-04 19:51:58 +05:30
Ajay Bura e6661d3b0d Remove favicons-webpack-plugin (#811)
* Remove favicons-webpack-plugin

* Copy android/* icons to dist

* Add favicon ico
2022-09-04 19:23:02 +05:30
ginnyTheCat 678e0dc6ac Allow mimetypes with suffix in safe check (#808) 2022-09-04 19:15:07 +05:30
Ajay Bura bdc10fb729 Fix multiple favicon changing request 2022-09-04 13:33:41 +05:30
Ajay Bura 584fa87bbd Notification settings (#807)
* Add account data hook

* Add options to change global notification

* Add options to add keywords

* Fix wrong notification count

* Show unread badge in favicon (#251)

* Fix favicon badge

* Fix bug

* Fix favicon not updating

* Add favicon svg's

* remove dead code
2022-09-04 13:10:07 +05:30
Ajay Bura ac155bbf4c Fix commands (#791)
* Fix commands and added more

* Add /me & /shrug commands

* Add help command

* Fix cmd descriptions

* Add reason in command
2022-09-03 21:46:40 +05:30
Krishan 0f6f65045d Add npmrc so that newer node/npm version works (#806)
* Add .npmrc so that it works with newer npm

* Remove engine upper limit as it works with npmrc

* Lockfile maintainace, created new mapping with npm install

* Add npmrc so Docker doesnt fail on new npm version

* Revert 8a1946d558 will set renovate
2022-09-03 21:36:47 +05:30
dependabot[bot] 843b9ddffd Bump katex from 0.16.0 to 0.16.2 (#802)
Bumps [katex](https://github.com/KaTeX/KaTeX) from 0.16.0 to 0.16.2.
- [Release notes](https://github.com/KaTeX/KaTeX/releases)
- [Changelog](https://github.com/KaTeX/KaTeX/blob/main/CHANGELOG.md)
- [Commits](https://github.com/KaTeX/KaTeX/compare/v0.16.0...v0.16.2)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-02 19:31:28 +05:30
dependabot[bot]andAjay Bura e283d4cd21 Bump eslint from 8.22.0 to 8.23.0 (#799)
Bumps [eslint](https://github.com/eslint/eslint) from 8.22.0 to 8.23.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.22.0...v8.23.0)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ajay Bura <32841439+ajbura@users.noreply.github.com>
2022-09-02 19:21:45 +05:30
dependabot[bot]andAjay Bura 4fe02d27c8 Bump webpack-dev-server from 4.10.0 to 4.10.1 (#800)
Bumps [webpack-dev-server](https://github.com/webpack/webpack-dev-server) from 4.10.0 to 4.10.1.
- [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.10.0...v4.10.1)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ajay Bura <32841439+ajbura@users.noreply.github.com>
2022-09-02 19:16:28 +05:30
dependabot[bot]andAjay Bura 5a269c68ae Bump html-react-parser from 3.0.1 to 3.0.4 (#797)
Bumps [html-react-parser](https://github.com/remarkablemark/html-react-parser) from 3.0.1 to 3.0.4.
- [Release notes](https://github.com/remarkablemark/html-react-parser/releases)
- [Changelog](https://github.com/remarkablemark/html-react-parser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/remarkablemark/html-react-parser/compare/v3.0.1...v3.0.4)

---
updated-dependencies:
- dependency-name: html-react-parser
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ajay Bura <32841439+ajbura@users.noreply.github.com>
2022-09-02 19:15:59 +05:30
dependabot[bot]andAjay Bura 570a1c85af Bump eslint-plugin-react from 7.30.1 to 7.31.1 (#796)
Bumps [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) from 7.30.1 to 7.31.1.
- [Release notes](https://github.com/jsx-eslint/eslint-plugin-react/releases)
- [Changelog](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jsx-eslint/eslint-plugin-react/compare/v7.30.1...v7.31.1)

---
updated-dependencies:
- dependency-name: eslint-plugin-react
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ajay Bura <32841439+ajbura@users.noreply.github.com>
2022-09-02 19:15:28 +05:30
dependabot[bot]andAjay Bura f7ff1ef2bd Bump actions/github-script from 6.1.1 to 6.2.0 (#794)
Bumps [actions/github-script](https://github.com/actions/github-script) from 6.1.1 to 6.2.0.
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](https://github.com/actions/github-script/compare/v6.1.1...v6.2.0)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ajay Bura <32841439+ajbura@users.noreply.github.com>
2022-09-02 19:15:03 +05:30
dependabot[bot]andAjay Bura 04530a801c Bump @babel/core from 7.18.10 to 7.18.13 (#783)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.18.10 to 7.18.13.
- [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.18.13/packages/babel-core)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ajay Bura <32841439+ajbura@users.noreply.github.com>
2022-09-02 19:14:34 +05:30
dependabot[bot]andAjay Bura 756cd0921b Bump sass from 1.54.4 to 1.54.5 (#781)
Bumps [sass](https://github.com/sass/dart-sass) from 1.54.4 to 1.54.5.
- [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.54.4...1.54.5)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ajay Bura <32841439+ajbura@users.noreply.github.com>
2022-09-02 19:14:14 +05:30
Krishan 292eee33b9 Release v2.1.3 2022-08-31 21:51:50 +05:30
Ajay Bura 583c834ba8 Bump matrix-js-sdk from 19.2.0 to 19.4.0 2022-08-31 21:51:02 +05:30
jameskitt616 33949dbdb1 Implement cancel replyto on escape key press (#777) 2022-08-27 08:21:41 +05:30
Krishan fd79ea4b9b Simplify readme and add various helpful links (#776)
* Simplyfy readme and add various helpful links

* update intro

* Add desktop app link
2022-08-22 08:29:47 +05:30
Ajay Bura b3bff6b43f Edit last message with up arrow key (#774) 2022-08-21 19:41:48 +05:30
ginnyTheCat 80aa55b706 Rework Markdown parsing (#719)
* Switch markdown parser

* Add inline maths

* Basic plain text rendering

* Add display math support

* Remove unnecessary <p> tag

* Fixed spoiler not working

* Add spoiler reason input support

* Make paragraphs display with newline in between

* Handle single newlines

* Fix typo when allowing start attribute

* Cleanup for merge

* Remove unused import
2022-08-21 19:34:09 +05:30
Ajay Bura 76c16ce294 Fix open room from search always open same space 2022-08-21 08:51:13 +05:30
Ajay Bura 715e6648ae Fix image lightbox height 2022-08-21 08:33:47 +05:30
dependabot[bot] 984fad811c Bump actions/github-script from 6.1.0 to 6.1.1 (#755)
Bumps [actions/github-script](https://github.com/actions/github-script) from 6.1.0 to 6.1.1.
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](https://github.com/actions/github-script/compare/v6.1.0...v6.1.1)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-20 21:09:36 +05:30
dependabot[bot] eafd2c8a13 Bump eslint from 8.21.0 to 8.22.0 (#756)
Bumps [eslint](https://github.com/eslint/eslint) from 8.21.0 to 8.22.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.21.0...v8.22.0)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-20 21:09:08 +05:30
Ajay Bura 82fb243ffe Fix room not selecting with bad emoji data (#772) 2022-08-20 21:07:20 +05:30
dependabot[bot]andKrishan 6cbf1b2eac Bump sass from 1.54.3 to 1.54.4 (#757)
Bumps [sass](https://github.com/sass/dart-sass) from 1.54.3 to 1.54.4.
- [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.54.3...1.54.4)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Krishan <33421343+kfiven@users.noreply.github.com>
2022-08-20 21:05:35 +05:30
dependabot[bot]andKrishan 043e411a98 Bump webpack-dev-server from 4.9.3 to 4.10.0 (#758)
Bumps [webpack-dev-server](https://github.com/webpack/webpack-dev-server) from 4.9.3 to 4.10.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.9.3...v4.10.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>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Krishan <33421343+kfiven@users.noreply.github.com>
2022-08-20 21:03:02 +05:30
KrishanandAjay Bura f93b666bbf Push Docker image to ghcr registry (#764)
* Push Docker image to ghcr registry

* Fix secret name

* add permission to token to write package to ghcr

Co-authored-by: Ajay Bura <32841439+ajbura@users.noreply.github.com>
2022-08-20 20:59:02 +05:30
Ajay BuraandKrishan 7e28aa1474 Update sidebar on room/space switch (#768)
* Select last room on space/tab change (#353)

* Update sidbar on room select from search (#374)

* Select last room on space/tab change (#353)

* Update sidbar on room select from search (#374)

* Fix wrong space gets selected with some rooms

* Fix auto select room in categorized space

* Fix room remain selected on leave

* Fix leaved room appear in category & search

* Remove globally exposed vars

* Hide pin spaces from home

* Fix selecting dm always open dm tab

* Order category by AtoZ (#769)

Co-authored-by: Krishan <33421343+kfiven@users.noreply.github.com>
2022-08-20 20:51:37 +05:30
jameskitt616 1deef51df0 Add cancel edit-message on Escape Key press (#765) 2022-08-20 18:56:37 +05:30
Ajay Bura 6f7934badc Fix more css bugs 2022-08-19 15:19:12 +05:30
Ajay Bura 2f2680be3c Fix minor css bugs 2022-08-19 13:57:24 +05:30
Ajay Bura 4cd8f4a94c Open image in lightbox (#767)
* Add lightbox

* Fix vertical media height (#467)

* Update dialog animation

* Fix overlay opacity

* Fix dialog animation

* Update open in new tab icon
2022-08-19 12:15:22 +05:30
James a417980a81 Improve MIME type handling on File Upload and in Message Component (#688)
* move allowed MIME types to own util file

* add check for safe MIME type before choosing how to upload

* check for allowed blob type to decide what component to load

* re-add check for safe mimetype

* fix bracket positioning
2022-08-14 16:31:17 +05:30
Andrew Morgan af69955801 Fix grammar of read receipt text (#744)
'other' should be plural in this context.
2022-08-12 16:03:56 +05:30
Ajay Bura 214d49f1d9 Release v2.1.2 2022-08-11 19:10:12 +05:30
dependabot[bot] c4e36a1f97 Bump @fontsource/inter from 4.5.11 to 4.5.12 (#726)
Bumps [@fontsource/inter](https://github.com/fontsource/fontsource/tree/HEAD/fonts/google/inter) from 4.5.11 to 4.5.12.
- [Release notes](https://github.com/fontsource/fontsource/releases)
- [Changelog](https://github.com/fontsource/fontsource/blob/main/CHANGELOG.md)
- [Commits](https://github.com/fontsource/fontsource/commits/HEAD/fonts/google/inter)

---
updated-dependencies:
- dependency-name: "@fontsource/inter"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-11 18:46:19 +05:30
dependabot[bot] 5de6a1bea6 Bump @fontsource/roboto from 4.5.7 to 4.5.8 (#727)
Bumps [@fontsource/roboto](https://github.com/fontsource/fontsource/tree/HEAD/fonts/google/roboto) from 4.5.7 to 4.5.8.
- [Release notes](https://github.com/fontsource/fontsource/releases)
- [Changelog](https://github.com/fontsource/fontsource/blob/main/CHANGELOG.md)
- [Commits](https://github.com/fontsource/fontsource/commits/HEAD/fonts/google/roboto)

---
updated-dependencies:
- dependency-name: "@fontsource/roboto"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-11 18:44:00 +05:30
dependabot[bot] 74a20a0e14 Bump sass from 1.54.1 to 1.54.3 (#728)
Bumps [sass](https://github.com/sass/dart-sass) from 1.54.1 to 1.54.3.
- [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.54.1...1.54.3)

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

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-11 18:43:31 +05:30
Ajay Bura 820d08017a Fix image not loading without h/w data (#738) 2022-08-11 18:41:09 +05:30
Ajay Bura 258afec391 Only render mxc images in markdown 2022-08-11 17:20:55 +05:30
Ajay Bura 0cf5aac591 Fix emoji board style 2022-08-11 16:31:02 +05:30
Ajay Bura 59fd34a4b4 Replace space by underscore in emoji shortcodes 2022-08-11 16:24:22 +05:30
Ajay Bura 1da3d252e8 Add navigation bar to sticker board 2022-08-11 16:13:53 +05:30
Ajay Bura 3c1cc59d59 Escape html with markdown off (#732) 2022-08-11 14:28:39 +05:30
Ajay Bura 1692098d5d Fix logout not working when server offline 2022-08-11 13:41:07 +05:30
Ajay Bura fbab53af22 Merge branch 'dev' of https://github.com/ajbura/cinny into dev 2022-08-11 13:33:59 +05:30
Ajay Bura ce1e263d57 Only scale image bigger than 512px (#731) 2022-08-11 13:33:54 +05:30
dependabot[bot] 9f99320fda Bump docker/build-push-action from 3.1.0 to 3.1.1 (#725)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 3.1.0 to 3.1.1.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v3.1.0...v3.1.1)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  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>
2022-08-09 09:30:34 +05:30
Ajay Bura 20e1df43d0 Release v2.1.1 2022-08-07 20:21:16 +05:30
Ajay Bura 728c5434bb Fix blurhash visible under transparent img (#721) 2022-08-07 20:14:47 +05:30
Ajay Bura 542ac4f4e1 Update olm 2022-08-07 20:01:31 +05:30
Ajay Bura d23fc228d7 Release v2.1.0 2022-08-07 19:04:38 +05:30
dependabot[bot]andAjay Bura 4ff3e47d54 Bump matrix-js-sdk from 18.1.0 to 19.2.0 (#711)
* Bump matrix-js-sdk from 18.1.0 to 19.2.0

Bumps [matrix-js-sdk](https://github.com/matrix-org/matrix-js-sdk) from 18.1.0 to 19.2.0.
- [Release notes](https://github.com/matrix-org/matrix-js-sdk/releases)
- [Changelog](https://github.com/matrix-org/matrix-js-sdk/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/matrix-org/matrix-js-sdk/compare/v18.1.0...v19.2.0)

---
updated-dependencies:
- dependency-name: matrix-js-sdk
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Remove session store

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ajay Bura <32841439+ajbura@users.noreply.github.com>
2022-08-07 14:51:56 +05:30
anyone00andKrishan 96b22eb557 Support RTL text in the input fields (#720)
* Support RTL text in the room input field

set the correct direction for text according to the language written in

* Make all input RTLable

Co-authored-by: Krishan <33421343+kfiven@users.noreply.github.com>
2022-08-07 14:41:56 +05:30
Ajay Bura 9187107751 Stop sending mxid in body for pills 2022-08-07 14:28:49 +05:30
Ajay Bura c6812b5b11 Reset read receipt on sending sticker 2022-08-06 12:50:23 +05:30
Ajay Bura adb584623e Support RTL text in messages (#717) 2022-08-06 12:40:24 +05:30
Ajay Bura 120e8de9d1 Remove unused import 2022-08-06 12:21:20 +05:30
ginnyTheCat 21726b63f8 Show full timestamp on hover (#714)
* Show full timestamp on hover

* Not always display time

* Always show full timestamp in search
2022-08-06 09:35:56 +05:30
ginnyTheCatandAjay Bura 04f910ee03 Blurhash support (#701)
* Generate blurhash client side

* Make blurhash generation faster

* Simple blurhash display support

* Make image display simpler

* Support non square images

* Don't attach video blurhash to thumbnail

* Add video display support

* Ignore alt tag missing warning

Co-authored-by: Ajay Bura <32841439+ajbura@users.noreply.github.com>
2022-08-06 09:26:26 +05:30
Ajay Bura edace32213 Custom emoji & Sticker support (#686)
* Remove comments

* Show custom emoji first in suggestions

* Show global image packs in emoji picker

* Display emoji and sticker in room settings

* Fix some pack not visible in emojiboard

* WIP

* Add/delete/rename images to exisitng packs

* Change pack avatar, name & attribution

* Add checkbox to make pack global

* Bug fix

* Create or delete pack

* Add personal emoji in settings

* Show global pack selector in settings

* Show space emoji in emojiboard

* Send custom emoji reaction as mxc

* Render stickers as stickers

* Fix sticker jump bug

* Fix reaction width

* Fix stretched custom emoji

* Fix sending space emoji in message

* Remove unnessesary comments

* Send user pills

* Fix pill generating regex

* Add support for sending stickers
2022-08-06 09:04:23 +05:30
ginnyTheCat 5e527e434a Fix shortcuts on non QWERTY keyboards (#715)
* Use key instead of keyCode or code

* Use key for Escape
2022-08-05 19:12:25 +05:30
ginnyTheCat 1d90f7588b Allow removing the room name (#702) 2022-08-03 19:59:56 +05:30
dependabot[bot] f8b8a35152 Bump html-react-parser from 2.0.0 to 3.0.1 (#675)
Bumps [html-react-parser](https://github.com/remarkablemark/html-react-parser) from 2.0.0 to 3.0.1.
- [Release notes](https://github.com/remarkablemark/html-react-parser/releases)
- [Changelog](https://github.com/remarkablemark/html-react-parser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/remarkablemark/html-react-parser/compare/v2.0.0...v3.0.1)

---
updated-dependencies:
- dependency-name: html-react-parser
  dependency-type: direct:production
  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>
2022-08-03 19:52:50 +05:30
dependabot[bot] fa4c95a9b6 Bump html-loader from 3.1.2 to 4.1.0 (#677)
Bumps [html-loader](https://github.com/webpack-contrib/html-loader) from 3.1.2 to 4.1.0.
- [Release notes](https://github.com/webpack-contrib/html-loader/releases)
- [Changelog](https://github.com/webpack-contrib/html-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/html-loader/compare/v3.1.2...v4.1.0)

---
updated-dependencies:
- dependency-name: html-loader
  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>
2022-08-03 19:36:36 +05:30
dependabot[bot] a478fc4805 Bump sass from 1.53.0 to 1.54.1 (#712)
Bumps [sass](https://github.com/sass/dart-sass) from 1.53.0 to 1.54.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.53.0...1.54.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>
2022-08-03 19:33:54 +05:30
dependabot[bot]andKrishan febb28e9c4 Bump katex from 0.15.6 to 0.16.0 (#616)
* Bump katex from 0.15.6 to 0.16.0

Bumps [katex](https://github.com/KaTeX/KaTeX) from 0.15.6 to 0.16.0.
- [Release notes](https://github.com/KaTeX/KaTeX/releases)
- [Changelog](https://github.com/KaTeX/KaTeX/blob/main/CHANGELOG.md)
- [Commits](https://github.com/KaTeX/KaTeX/compare/v0.15.6...v0.16.0)

---
updated-dependencies:
- dependency-name: katex
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Remove copy-tex.css as it no longer required

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Krishan <33421343+kfiven@users.noreply.github.com>
2022-08-03 19:28:54 +05:30
dependabot[bot] c78a39af50 Bump webpack from 5.73.0 to 5.74.0 (#696)
Bumps [webpack](https://github.com/webpack/webpack) from 5.73.0 to 5.74.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.73.0...v5.74.0)

---
updated-dependencies:
- dependency-name: webpack
  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>
2022-08-03 19:27:07 +05:30
dependabot[bot] 21e6049c16 Bump sanitize-html from 2.7.0 to 2.7.1 (#698)
Bumps [sanitize-html](https://github.com/apostrophecms/sanitize-html) from 2.7.0 to 2.7.1.
- [Release notes](https://github.com/apostrophecms/sanitize-html/releases)
- [Changelog](https://github.com/apostrophecms/sanitize-html/blob/main/CHANGELOG.md)
- [Commits](https://github.com/apostrophecms/sanitize-html/compare/2.7.0...2.7.1)

---
updated-dependencies:
- dependency-name: sanitize-html
  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>
2022-08-03 19:25:02 +05:30
dependabot[bot] 6e418337cc Bump eslint-plugin-jsx-a11y from 6.6.0 to 6.6.1 (#699)
Bumps [eslint-plugin-jsx-a11y](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y) from 6.6.0 to 6.6.1.
- [Release notes](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/releases)
- [Changelog](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/compare/v6.6.0...v6.6.1)

---
updated-dependencies:
- dependency-name: eslint-plugin-jsx-a11y
  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>
2022-08-03 19:23:17 +05:30
dependabot[bot] 48f34053ab Bump eslint from 8.20.0 to 8.21.0 (#704)
Bumps [eslint](https://github.com/eslint/eslint) from 8.20.0 to 8.21.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.20.0...v8.21.0)

---
updated-dependencies:
- dependency-name: eslint
  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>
2022-08-03 19:21:10 +05:30
dependabot[bot] abfe263750 Bump @babel/core from 7.18.9 to 7.18.10 (#705)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.18.9 to 7.18.10.
- [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.18.10/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  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>
2022-08-03 19:18:22 +05:30
dependabot[bot] 9ba003b16d Bump @babel/preset-env from 7.18.9 to 7.18.10 (#707)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.18.9 to 7.18.10.
- [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.18.10/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  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>
2022-08-03 19:12:15 +05:30
dependabot[bot] 48793f3a95 Bump docker/build-push-action from 3.0.0 to 3.1.0 (#695)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 3.0.0 to 3.1.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v3.0.0...v3.1.0)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  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>
2022-07-27 14:04:59 +05:30
dependabot[bot] d8cf98fd64 Bump nginx from 1.23.0-alpine to 1.23.1-alpine (#694)
Bumps nginx from 1.23.0-alpine to 1.23.1-alpine.

---
updated-dependencies:
- dependency-name: nginx
  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>
2022-07-27 14:03:41 +05:30
Ava PekandMaple 78e12d5bee Add mark as read button to space options (#667)
This allows users to mark all rooms in a space as read, matching similar
features found in other popular chat applications.

We opted to place the mark as read button at the top of the list instead
of next to the add user button like in room options since we felt this
will be the most-used button in the list.

Fixes #645.

Co-authored-by: Maple <mapletree.dv@gmail.com>

Co-authored-by: Maple <mapletree.dv@gmail.com>
2022-07-25 11:41:56 +05:30
dependabot[bot] bdb8bdf76c Bump cross-fetch from 3.1.4 to 3.1.5 (#512)
Bumps [cross-fetch](https://github.com/lquixada/cross-fetch) from 3.1.4 to 3.1.5.
- [Release notes](https://github.com/lquixada/cross-fetch/releases)
- [Commits](https://github.com/lquixada/cross-fetch/compare/v3.1.4...v3.1.5)

---
updated-dependencies:
- dependency-name: cross-fetch
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 13:18:12 +05:30
dependabot[bot] 88b79eb3a5 Bump @babel/core from 7.18.6 to 7.18.9 (#690)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.18.6 to 7.18.9.
- [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.18.9/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  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>
2022-07-19 17:56:48 +05:30
dependabot[bot] b6428197ac Bump eslint from 8.19.0 to 8.20.0 (#691)
Bumps [eslint](https://github.com/eslint/eslint) from 8.19.0 to 8.20.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.19.0...v8.20.0)

---
updated-dependencies:
- dependency-name: eslint
  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>
2022-07-19 17:52:17 +05:30
dependabot[bot] a46138c8b9 Bump @babel/preset-env from 7.18.6 to 7.18.9 (#692)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.18.6 to 7.18.9.
- [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.18.9/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  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>
2022-07-19 17:51:13 +05:30
Dean Bassett 1211ca277b Support mark as read by ESC while in room input (#669)
fixes #cinnyapp/cinny/668
2022-07-18 22:06:51 +05:30
James e6f395c643 Add support to play .mov files (#672)
* update allowed mimetypes

* fix .mov files failing to play in Chromium

* add check for  before passing to FileReader

* add missing semi-colon
2022-07-18 22:03:11 +05:30
dependabot[bot] 1979646b4b Bump actions/setup-node from 3.3.0 to 3.4.1 (#687)
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 3.3.0 to 3.4.1.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v3.3.0...v3.4.1)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  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>
2022-07-16 17:11:48 +05:30
Ajay Bura 5c0eb20cb4 Follow system theme by default 2022-07-09 18:08:35 +05:30
Ajay Bura 009966a5c7 Fix wrong power level in room permission 2022-07-09 16:32:42 +05:30
Ajay Bura 4427b3b291 Accept mxid on login (#187) 2022-07-09 13:58:57 +05:30
Ajay Bura 3dda4d6540 Add toggle to show password in auth page (#73) 2022-07-09 10:35:17 +05:30
Ajay Bura c9df0be874 Fix captcha loop issue in registration form (#664) 2022-07-08 21:07:14 +05:30
Krishan ca2627d3cf Bump linkifyjs 2.1.9 to 4.0.0-beta.5 (#665) 2022-07-08 20:29:07 +05:30
Krishan 47e6527b0e Don't enable e2ee from profileViewer for bridge users (#666) 2022-07-08 20:24:35 +05:30
dependabot[bot] 7decbb6eef Bump webpack-dev-server from 4.9.2 to 4.9.3 (#662)
Bumps [webpack-dev-server](https://github.com/webpack/webpack-dev-server) from 4.9.2 to 4.9.3.
- [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.9.2...v4.9.3)

---
updated-dependencies:
- dependency-name: webpack-dev-server
  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>
2022-07-05 10:08:25 +05:30
dependabot[bot] 68da1d0551 Bump eslint from 8.18.0 to 8.19.0 (#663)
Bumps [eslint](https://github.com/eslint/eslint) from 8.18.0 to 8.19.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.18.0...v8.19.0)

---
updated-dependencies:
- dependency-name: eslint
  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>
2022-07-05 10:06:53 +05:30
Chuang Zhu a6f21b6606 Fix parsing encoded matrix.to URL (#660)
From https://spec.matrix.org/v1.3/appendices/#matrixto-navigation:

	The components of the matrix.to URI (<identifier> and <extra parameter>) are to be percent-encoded as per RFC 3986.

	Historically, clients have not produced URIs which are fully encoded. Clients should try to interpret these cases to the best of their ability. For example, an unencoded room alias should still work within the client if possible
2022-07-04 19:50:11 +05:30
ginnyTheCat 06a4e0c93b Add emoji name fallback (#658) 2022-06-29 18:19:43 +05:30
dependabot[bot] 0ca1df24ed Bump @babel/preset-react from 7.17.12 to 7.18.6 (#656)
Bumps [@babel/preset-react](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-react) from 7.17.12 to 7.18.6.
- [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.18.6/packages/babel-preset-react)

---
updated-dependencies:
- dependency-name: "@babel/preset-react"
  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>
2022-06-28 20:39:44 +05:30
dependabot[bot] 1d12a906d4 Bump @babel/preset-env from 7.18.2 to 7.18.6 (#654)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.18.2 to 7.18.6.
- [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.18.6/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  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>
2022-06-28 20:31:52 +05:30
dependabot[bot] 7bd7518963 Bump @babel/core from 7.18.5 to 7.18.6 (#653)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.18.5 to 7.18.6.
- [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.18.6/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  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>
2022-06-28 15:54:07 +05:30
dependabot[bot] a9c5765be5 Bump sass from 1.52.3 to 1.53.0 (#655)
Bumps [sass](https://github.com/sass/dart-sass) from 1.52.3 to 1.53.0.
- [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.52.3...1.53.0)

---
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>
2022-06-28 15:53:23 +05:30
dependabot[bot] 2292f63fb6 Bump eslint-plugin-jsx-a11y from 6.5.1 to 6.6.0 (#652)
Bumps [eslint-plugin-jsx-a11y](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y) from 6.5.1 to 6.6.0.
- [Release notes](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/releases)
- [Changelog](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/compare/v6.5.1...v6.6.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-jsx-a11y
  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>
2022-06-28 15:52:31 +05:30
dependabot[bot] db92b9f5ff Bump sass-loader from 13.0.0 to 13.0.2 (#651)
Bumps [sass-loader](https://github.com/webpack-contrib/sass-loader) from 13.0.0 to 13.0.2.
- [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/v13.0.0...v13.0.2)

---
updated-dependencies:
- dependency-name: sass-loader
  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>
2022-06-28 15:28:24 +05:30
dependabot[bot] f538639882 Bump eslint-plugin-react from 7.30.0 to 7.30.1 (#650)
Bumps [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) from 7.30.0 to 7.30.1.
- [Release notes](https://github.com/jsx-eslint/eslint-plugin-react/releases)
- [Changelog](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jsx-eslint/eslint-plugin-react/compare/v7.30.0...v7.30.1)

---
updated-dependencies:
- dependency-name: eslint-plugin-react
  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>
2022-06-28 15:27:40 +05:30
dependabot[bot] 56bc8c2890 Bump nginx from 1.21.6-alpine to 1.23.0-alpine (#649)
Bumps nginx from 1.21.6-alpine to 1.23.0-alpine.

---
updated-dependencies:
- dependency-name: nginx
  dependency-type: direct:production
  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>
2022-06-28 15:27:20 +05:30
dependabot[bot] 1cba4d3fa7 Bump html-loader from 3.1.0 to 3.1.2 (#643)
Bumps [html-loader](https://github.com/webpack-contrib/html-loader) from 3.1.0 to 3.1.2.
- [Release notes](https://github.com/webpack-contrib/html-loader/releases)
- [Changelog](https://github.com/webpack-contrib/html-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/html-loader/compare/v3.1.0...v3.1.2)

---
updated-dependencies:
- dependency-name: html-loader
  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>
2022-06-21 17:39:36 +05:30
dependabot[bot] 4c7820ceac Bump html-react-parser from 1.4.14 to 2.0.0 (#641)
Bumps [html-react-parser](https://github.com/remarkablemark/html-react-parser) from 1.4.14 to 2.0.0.
- [Release notes](https://github.com/remarkablemark/html-react-parser/releases)
- [Changelog](https://github.com/remarkablemark/html-react-parser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/remarkablemark/html-react-parser/compare/v1.4.14...v2.0.0)

---
updated-dependencies:
- dependency-name: html-react-parser
  dependency-type: direct:production
  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>
2022-06-21 17:33:58 +05:30
dependabot[bot] 118dcd8fa0 Bump eslint-plugin-react-hooks from 4.5.0 to 4.6.0 (#642)
Bumps [eslint-plugin-react-hooks](https://github.com/facebook/react/tree/HEAD/packages/eslint-plugin-react-hooks) from 4.5.0 to 4.6.0.
- [Release notes](https://github.com/facebook/react/releases)
- [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/react/commits/HEAD/packages/eslint-plugin-react-hooks)

---
updated-dependencies:
- dependency-name: eslint-plugin-react-hooks
  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>
2022-06-21 17:31:58 +05:30
dependabot[bot] a142ade923 Bump mini-css-extract-plugin from 2.6.0 to 2.6.1 (#640)
Bumps [mini-css-extract-plugin](https://github.com/webpack-contrib/mini-css-extract-plugin) from 2.6.0 to 2.6.1.
- [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.6.0...v2.6.1)

---
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>
2022-06-21 17:30:23 +05:30
dependabot[bot] 57ab10a87c Bump eslint from 8.17.0 to 8.18.0 (#638)
Bumps [eslint](https://github.com/eslint/eslint) from 8.17.0 to 8.18.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.17.0...v8.18.0)

---
updated-dependencies:
- dependency-name: eslint
  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>
2022-06-21 17:28:44 +05:30
Krishan 8c1c3cd634 Fix mozilla homerserver domain (#199) (#629) 2022-06-15 12:07:14 +05:30
168 changed files with 10105 additions and 22785 deletions

No files matched your search

-3
View File
@@ -1,5 +1,2 @@
webpack.common.js
webpack.dev.js
webpack.prod.js
experiment
node_modules
+33 -2
View File
@@ -4,25 +4,56 @@ module.exports = {
es2021: true,
},
extends: [
'plugin:react/recommended',
"eslint:recommended",
"plugin:react/recommended",
"plugin:react-hooks/recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
'airbnb',
'prettier',
],
parser: "@typescript-eslint/parser",
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 12,
ecmaVersion: 'latest',
sourceType: 'module',
},
plugins: [
'react',
'@typescript-eslint'
],
rules: {
'linebreak-style': 0,
'no-underscore-dangle': 0,
"import/prefer-default-export": "off",
"import/extensions": "off",
"import/no-unresolved": "off",
"import/no-extraneous-dependencies": [
"error",
{
devDependencies: true,
},
],
'react/no-unstable-nested-components': [
'error',
{ allowAsProps: true },
],
"react/jsx-filename-extension": [
"error",
{
extensions: [".tsx", ".jsx"],
},
],
"react/require-default-props": "off",
"react/jsx-props-no-spreading": "off",
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "error",
"@typescript-eslint/no-unused-vars": "error",
},
};
+1 -1
View File
@@ -1,4 +1,4 @@
<!-- Please read https://github.com/ajbura/cinny/CONTRIBUTING.md before submitting your pull request -->
<!-- Please read https://github.com/ajbura/cinny/blob/dev/CONTRIBUTING.md before submitting your pull request -->
### Description
<!-- Please include a summary of the change. Please also include relevant motivation and context. List any dependencies that are required for this change. -->
+15
View File
@@ -0,0 +1,15 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:base",
":dependencyDashboardApproval"
],
"labels": [ "Dependencies" ],
"packageRules": [
{
"matchUpdateTypes": [ "lockFileMaintenance" ]
}
],
"lockFileMaintenance": { "enabled": true },
"dependencyDashboard": true
}
+17 -17
View File
@@ -1,4 +1,4 @@
name: 'Build pull request'
name: Build pull request
on:
pull_request:
@@ -6,33 +6,33 @@ on:
jobs:
build-pull-request:
name: Build pull request
runs-on: ubuntu-latest
env:
PR_NUMBER: ${{github.event.number}}
steps:
- name: Checkout repository
uses: actions/checkout@v3.0.2
uses: actions/checkout@v3.2.0
- name: Setup node
uses: actions/setup-node@v3.3.0
uses: actions/setup-node@v3.5.1
with:
node-version: 17.9.0
node-version: 18.12.1
cache: "npm"
- name: Install dependencies
run: npm ci
- name: Build app
run: npm ci && npm run build
run: npm run build
- name: Upload artifact
uses: actions/upload-artifact@v3.1.0
uses: actions/upload-artifact@v3.1.1
with:
name: previewbuild
name: preview
path: dist
retention-days: 1
- name: Get PR info
uses: actions/github-script@v6.1.0
- name: Save pr number
run: echo ${PR_NUMBER} > ./pr.txt
- name: Upload pr number
uses: actions/upload-artifact@v3.1.1
with:
script: |
var fs = require('fs');
fs.writeFileSync('${{github.workspace}}/pr.json', JSON.stringify(context.payload.pull_request));
- name: Upload PR Info
uses: actions/upload-artifact@v3.1.0
with:
name: pr.json
path: pr.json
name: pr
path: ./pr.txt
retention-days: 1
+32 -57
View File
@@ -1,81 +1,56 @@
name: Upload Preview Build to Netlify
name: Deploy PR to Netlify
on:
workflow_run:
workflows: ["Build pull request"]
types:
- completed
types: [completed]
jobs:
get-build-and-deploy:
deploy-pull-request:
name: Deploy pull request
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
if: >
${{ github.event.workflow_run.conclusion == 'success' }}
if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps:
# There's a 'download artifact' action but it hasn't been updated for the
# workflow_run action (https://github.com/actions/download-artifact/issues/60)
# so instead we get this mess:
- name: Download pr number
uses: dawidd6/action-download-artifact@e6e25ac3a2b93187502a8be1ef9e9603afc34925
with:
workflow: ${{ github.event.workflow.id }}
run_id: ${{ github.event.workflow_run.id }}
name: pr
- name: Output pr number
id: pr
run: echo "id=$(<pr.txt)" >> $GITHUB_OUTPUT
- name: Download artifact
uses: actions/github-script@v6.1.0
uses: dawidd6/action-download-artifact@e6e25ac3a2b93187502a8be1ef9e9603afc34925
with:
script: |
var artifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: ${{github.event.workflow_run.id }},
});
var matchArtifact = artifacts.data.artifacts.filter((artifact) => {
return artifact.name == "previewbuild"
})[0];
var download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: matchArtifact.id,
archive_format: 'zip',
});
var fs = require('fs');
fs.writeFileSync('${{github.workspace}}/previewbuild.zip', Buffer.from(download.data));
var prInfoArtifact = artifacts.data.artifacts.filter((artifact) => {
return artifact.name == "pr.json"
})[0];
var download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: prInfoArtifact.id,
archive_format: 'zip',
});
var fs = require('fs');
fs.writeFileSync('${{github.workspace}}/pr.json.zip', Buffer.from(download.data));
- name: Extract Artifacts
run: unzip -d dist previewbuild.zip && rm previewbuild.zip && unzip pr.json.zip && rm pr.json.zip
- name: Read PR Info
id: readctx
uses: actions/github-script@v6.1.0
with:
script: |
var fs = require('fs');
var pr = JSON.parse(fs.readFileSync('${{github.workspace}}/pr.json'));
console.log(`::set-output name=prnumber::${pr.number}`);
workflow: ${{ github.event.workflow.id }}
run_id: ${{ github.event.workflow_run.id }}
name: preview
path: dist
- name: Deploy to Netlify
id: netlify
uses: nwtgck/actions-netlify@b7c1504e00c6b8a249d1848cc1b522a4865eed99
uses: nwtgck/actions-netlify@5da65c9f74c7961c5501a3ba329b8d0912f39c03
with:
publish-dir: dist
deploy-message: "Deploy from GitHub Actions"
deploy-message: "Deploy PR ${{ steps.pr.outputs.id }}"
alias: ${{ steps.pr.outputs.id }}
# These don't work because we're in workflow_run
enable-pull-request-comment: false
enable-commit-comment: false
env:
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE3_ID }}
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID_PR_CINNY }}
timeout-minutes: 1
- name: Edit PR Description
uses: Beakyn/gha-comment-pull-request@2167a7aee24f9e61ce76a23039f322e49a990409
- name: Comment preview on PR
uses: thollander/actions-comment-pull-request@c22fb302208b7b170d252a61a505d2ea27245eff
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
pull-request-number: ${{ steps.readctx.outputs.prnumber }}
description-message: |
pr_number: ${{ steps.pr.outputs.id }}
comment_tag: ${{ steps.pr.outputs.id }}
message: |
Preview: ${{ steps.netlify.outputs.deploy-url }}
⚠️ Exercise caution. Use test accounts. ⚠️
⚠️ Exercise caution. Use test accounts. ⚠️
+2 -4
View File
@@ -9,13 +9,11 @@ on:
jobs:
docker-build:
runs-on: ubuntu-latest
env:
PR_NUMBER: ${{github.event.number}}
steps:
- name: Checkout repository
uses: actions/checkout@v3.0.2
uses: actions/checkout@v3.2.0
- name: Build Docker image
uses: docker/build-push-action@v3.0.0
uses: docker/build-push-action@v3.2.0
with:
context: .
push: false
+26
View File
@@ -0,0 +1,26 @@
name: NPM Lockfile Changes
on:
pull_request:
paths:
- 'package-lock.json'
jobs:
lockfile_changes:
runs-on: ubuntu-latest
# Permission overwrite is required for Dependabot PRs, see "Common issues" below.
permissions:
contents: read
pull-requests: write
steps:
- name: Checkout
uses: actions/checkout@v3.2.0
- name: NPM Lockfile Changes
uses: codepunkt/npm-lockfile-changes@b40543471c36394409466fdb277a73a0856d7891
with:
token: ${{ secrets.GITHUB_TOKEN }}
# Optional inputs, can be deleted safely if you are happy with default values.
collapsibleThreshold: 25
failOnDowngrade: false
path: package-lock.json
updateComment: true
+22 -14
View File
@@ -1,4 +1,4 @@
name: 'Deploy to Netlify (dev)'
name: Deploy to Netlify (dev)
on:
push:
@@ -7,23 +7,31 @@ on:
jobs:
deploy-to-netlify:
name: 'Deploy'
name: Deploy to Netlify
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@v3.0.2
uses: actions/checkout@v3.2.0
- name: Setup node
uses: actions/setup-node@v3.3.0
uses: actions/setup-node@v3.5.1
with:
node-version: 17.9.0
- name: Build and deploy to Netlify
uses: jsmrcaga/action-netlify-deploy@53de32e559b0b3833615b9788c7a090cd2fddb03
node-version: 18.12.1
cache: "npm"
- name: Install dependencies
run: npm ci
- name: Build app
run: npm run build
- name: Deploy to Netlify
uses: nwtgck/actions-netlify@5da65c9f74c7961c5501a3ba329b8d0912f39c03
with:
install_command: "npm ci"
publish-dir: dist
deploy-message: "Dev deploy ${{ github.sha }}"
enable-commit-comment: false
github-token: ${{ secrets.GITHUB_TOKEN }}
production-deploy: true
github-deployment-environment: nightly
github-deployment-description: 'Nightly deployment on each commit to dev branch'
env:
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE2_ID }}
BUILD_DIRECTORY: "dist"
NETLIFY_DEPLOY_MESSAGE: "Dev deploy v${{ github.ref }}"
NETLIFY_DEPLOY_TO_PROD: true
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID_DEV }}
timeout-minutes: 1
+45 -43
View File
@@ -1,27 +1,42 @@
name: 'Production deploy'
name: Production deploy
on:
release:
types: [published]
jobs:
create-release-tar:
name: 'Create release tar'
deploy-and-tarball:
name: Netlify deploy and tarball
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3.0.2
uses: actions/checkout@v3.2.0
- name: Setup node
uses: actions/setup-node@v3.3.0
uses: actions/setup-node@v3.5.1
with:
node-version: 17.9.0
- name: Build
run: |
npm ci
npm run build
node-version: 18.12.1
cache: "npm"
- name: Install dependencies
run: npm ci
- name: Build app
run: npm run build
- name: Deploy to Netlify
uses: nwtgck/actions-netlify@5da65c9f74c7961c5501a3ba329b8d0912f39c03
with:
publish-dir: dist
deploy-message: "Prod deploy ${{ github.ref_name }}"
enable-commit-comment: false
github-token: ${{ secrets.GITHUB_TOKEN }}
production-deploy: true
github-deployment-environment: stable
github-deployment-description: 'Stable deployment on each release'
env:
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID_APP }}
timeout-minutes: 1
- name: Get version from tag
id: vars
run: echo ::set-output name=tag::${GITHUB_REF#refs/*/}
run: echo "tag=${GITHUB_REF#refs/*/}" >> $GITHUB_OUTPUT
- name: Create tar.gz
run: tar -czvf cinny-${{ steps.vars.outputs.tag }}.tar.gz dist
- name: Sign tar.gz
@@ -35,58 +50,45 @@ jobs:
gpg --export | xxd -p
echo '${{ secrets.GNUPG_PASSPHRASE }}' | gpg --batch --yes --pinentry-mode loopback --passphrase-fd 0 --armor --detach-sign cinny-${{ steps.vars.outputs.tag }}.tar.gz
- name: Upload tagged release
uses: softprops/action-gh-release@1e07f4398721186383de40550babbdf2b84acfc5
uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844
with:
files: |
cinny-${{ steps.vars.outputs.tag }}.tar.gz
cinny-${{ steps.vars.outputs.tag }}.tar.gz.asc
deploy-to-netlify:
name: 'Deploy to Netlify'
publish-image:
name: Push Docker image to Docker Hub, ghcr
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v3.0.2
- name: Setup node
uses: actions/setup-node@v3.3.0
with:
node-version: 17.9.0
- name: Build and deploy to Netlify
uses: jsmrcaga/action-netlify-deploy@53de32e559b0b3833615b9788c7a090cd2fddb03
with:
install_command: "npm ci"
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
BUILD_DIRECTORY: "dist"
NETLIFY_DEPLOY_MESSAGE: "Prod deploy v${{ github.ref }}"
NETLIFY_DEPLOY_TO_PROD: true
push-to-dockerhub:
name: Push Docker image to Docker Hub
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@v3.0.2
uses: actions/checkout@v3.2.0
- name: Set up QEMU
uses: docker/setup-qemu-action@v2.0.0
uses: docker/setup-qemu-action@v2.1.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2.0.0
uses: docker/setup-buildx-action@v2.2.1
- name: Login to Docker Hub
uses: docker/login-action@v2.0.0
uses: docker/login-action@v2.1.0
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to the Container registry
uses: docker/login-action@v2.1.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v4.0.1
uses: docker/metadata-action@v4.1.1
with:
images: ajbura/cinny
images: |
${{ secrets.DOCKER_USERNAME }}/cinny
ghcr.io/${{ github.repository }}
- name: Build and push Docker image
uses: docker/build-push-action@v3.0.0
uses: docker/build-push-action@v3.2.0
with:
context: .
platforms: linux/amd64,linux/arm64
+3
View File
@@ -0,0 +1,3 @@
legacy-peer-deps=true
save-exact=true
@matrix-org:registry=https://gitlab.matrix.org/api/v4/projects/27/packages/npm/
+6
View File
@@ -0,0 +1,6 @@
dist
node_modules
package.json
package-lock.json
LICENSE
README.md
+4
View File
@@ -0,0 +1,4 @@
{
"printWidth": 100,
"singleQuote": true
}
+3
View File
@@ -0,0 +1,3 @@
{
"recommendations": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"]
}
+5
View File
@@ -0,0 +1,5 @@
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"typescript.tsdk": "node_modules/typescript/lib"
}
+6 -1
View File
@@ -36,4 +36,9 @@ It is not always possible to phrase every change in such a manner, but it is des
Also, we use [ESLint](https://eslint.org/) for clean and stylistically consistent code syntax, so make sure your pull request follow it.
**For any query or design discussion, join our [Matrix room](https://matrix.to/#/#cinny:matrix.org).**
**For any query or design discussion, join our [Matrix room](https://matrix.to/#/#cinny:matrix.org).**
## Helpful links
- [BEM methodology](http://getbem.com/introduction/)
- [Atomic design](https://bradfrost.com/blog/post/atomic-web-design/)
- [Matrix JavaScript SDK documentation](https://matrix-org.github.io/matrix-js-sdk/index.html)
+3 -3
View File
@@ -1,16 +1,16 @@
## Builder
FROM node:17.9.0-alpine3.15 as builder
FROM node:18.12.1-alpine3.15 as builder
WORKDIR /src
COPY package.json package-lock.json /src/
COPY .npmrc package.json package-lock.json /src/
RUN npm ci
COPY . /src/
RUN npm run build
## App
FROM nginx:1.21.6-alpine
FROM nginx:1.23.3-alpine
COPY --from=builder /src/dist /app
+2 -2
View File
@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2021 Ajay Bura (ajbura)
Copyright (c) 2021-present Ajay Bura (ajbura)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
SOFTWARE.
+30 -34
View File
@@ -1,9 +1,5 @@
<p align="center">
<img src="https://raw.githubusercontent.com/ajbura/cinny/dev/public/res/svg/cinny.svg?sanitize=true"
height="16">
<span><b>Cinny</b></span>
</p>
<p align="center">
# Cinny
<p>
<a href="https://github.com/ajbura/cinny/releases">
<img alt="GitHub release downloads" src="https://img.shields.io/github/downloads/ajbura/cinny/total?logo=github&style=social"></a>
<a href="https://hub.docker.com/r/ajbura/cinny">
@@ -16,21 +12,30 @@
<img alt="Sponsor Cinny" src="https://img.shields.io/opencollective/all/cinny?logo=opencollective&style=social"></a>
</p>
**Cinny** is a Matrix client focusing primarily on simple, elegant and secure interface. The main goal is to have a client that is easy on end user
and feels a modern chat application.
- [Contributing](./CONTRIBUTING.md)
A Matrix client focusing primarily on simple, elegant and secure interface. The main goal is to have an instant messaging application that is easy on people and has a modern touch.
- [Roadmap](https://github.com/ajbura/cinny/projects/11)
- [Contributing](./CONTRIBUTING.md)
## Building and Running
## Getting started
Web app is available at https://app.cinny.in and gets updated on each new release. The `dev` branch is continuously deployed at https://dev.cinny.in but keep in mind that it could have things broken.
### Running pre-compiled
You can also download our desktop app from [cinny-desktop repository](https://github.com/cinnyapp/cinny-desktop).
A tarball of pre-compiled version of the app is provided with each [release](https://github.com/ajbura/cinny/releases).
You can serve the application with a webserver of your choosing by simply copying `dist/` directory to the webroot.
To host Cinny on your own, download tarball of the app from [GitHub release](https://github.com/cinnyapp/cinny/releases/latest).
You can serve the application with a webserver of your choice by simply copying `dist/` directory to the webroot.
To set default Homeserver on login and register page, place a customized [`config.json`](config.json) in webroot of your choice.
Alternatively you can just pull the [DockerHub image](https://hub.docker.com/r/ajbura/cinny) by:
```
docker pull ajbura/cinny
```
or [ghcr image](https://github.com/cinnyapp/cinny/pkgs/container/cinny) by:
```
docker pull ghcr.io/cinnyapp/cinny:latest
```
<details>
<summary>PGP Public Key to verify pre-compiled tarball</summary>
<summary>PGP Public Key to verify tarball</summary>
```
-----BEGIN PGP PUBLIC KEY BLOCK-----
@@ -77,48 +82,39 @@ UeGsouhyuITLwEhScounZDqop+Dx
```
</details>
### Building from source
## Local development
> We recommend using a version manager as versions change very quickly. You will likely need to switch
between multiple Node.js versions based on the needs of different projects you're working on. [NVM on windows](https://github.com/coreybutler/nvm-windows#installation--upgrades) on Windows and [nvm](https://github.com/nvm-sh/nvm) on Linux/macOS are pretty good choices. Also recommended nodejs version is 16.15.0 LTS.
Execute the following commands to compile the app from its source code:
between multiple Node.js versions based on the needs of different projects you're working on. [NVM on windows](https://github.com/coreybutler/nvm-windows#installation--upgrades) on Windows and [nvm](https://github.com/nvm-sh/nvm) on Linux/macOS are pretty good choices. Also recommended nodejs version Hydrogen LTS (v18).
Execute the following commands to start a development server:
```sh
npm ci # Installs all dependencies
npm start # Serve a development version
```
To build the app:
```sh
npm run build # Compiles the app into the dist/ directory
```
You can then copy the files to a webserver's webroot of your choice.
To serve a development version of the app locally for testing, you need to use the command `npm start`.
### Running with Docker
This repository includes a Dockerfile, which builds the application from source and serves it with Nginx on port 80. To
use this locally, you can build the container like so:
```
docker build -t cinny:latest .
```
You can then run the container you've built with a command similar to this:
```
docker run -p 8080:80 cinny:latest
```
This will forward your `localhost` port 8080 to the container's port 80. You can visit the app in your browser by
navigating to `http://localhost:8080`.
This will forward your `localhost` port 8080 to the container's port 80. You can visit the app in your browser by navigating to `http://localhost:8080`.
Alternatively you can just pull the [DockerHub image](https://hub.docker.com/r/ajbura/cinny) by `docker pull ajbura/cinny`.
### Configuring default Homeserver
To set default Homeserver on login and register page, place a customized [`config.json`](config.json) in webroot of your choice.
## License
Copyright (c) 2021 Ajay Bura (ajbura)
Copyright (c) 2021-present Ajay Bura (ajbura)
Code licensed under the MIT License: <http://opensource.org/licenses/MIT>
+3 -3
View File
@@ -1,12 +1,12 @@
{
"defaultHomeserver": 4,
"defaultHomeserver": 3,
"homeserverList": [
"converser.eu",
"envs.net",
"halogen.city",
"kde.org",
"matrix.icarus.today",
"matrix.org",
"chat.mozilla.org"
"mozilla.org"
],
"allowCustomHomeservers": true
}
+101
View File
@@ -0,0 +1,101 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Cinny</title>
<meta name="name" content="Cinny" />
<meta name="author" content="Ajay Bura" />
<meta
name="description"
content="A Matrix client where you can enjoy the conversation using simple, elegant and secure interface protected by e2ee with the power of open source."
/>
<meta
name="keywords"
content="cinny, cinnyapp, cinnychat, matrix, matrix client, matrix.org, element"
/>
<meta property="og:title" content="Cinny" />
<meta property="og:url" content="https://cinny.in" />
<meta property="og:image" content="https://cinny.in/assets/favicon-48x48.png" />
<meta
property="og:description"
content="A Matrix client where you can enjoy the conversation using simple, elegant and secure interface protected by e2ee with the power of open source."
/>
<meta name="theme-color" content="#000000" />
<link id="favicon" rel="shortcut icon" href="./public/favicon.ico" />
<link rel="manifest" href="./manifest.json" />
<meta name="mobile-web-app-capable" content="yes" />
<meta name="application-name" content="Cinny" />
<meta name="apple-mobile-web-app-title" content="Cinny" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<link
rel="apple-touch-icon"
sizes="57x57"
href="./public/res/apple/apple-touch-icon-57x57.png"
/>
<link
rel="apple-touch-icon"
sizes="60x60"
href="./public/res/apple/apple-touch-icon-60x60.png"
/>
<link
rel="apple-touch-icon"
sizes="72x72"
href="./public/res/apple/apple-touch-icon-72x72.png"
/>
<link
rel="apple-touch-icon"
sizes="76x76"
href="./public/res/apple/apple-touch-icon-76x76.png"
/>
<link
rel="apple-touch-icon"
sizes="114x114"
href="./public/res/apple/apple-touch-icon-114x114.png"
/>
<link
rel="apple-touch-icon"
sizes="120x120"
href="./public/res/apple/apple-touch-icon-120x120.png"
/>
<link
rel="apple-touch-icon"
sizes="144x144"
href="./public/res/apple/apple-touch-icon-144x144.png"
/>
<link
rel="apple-touch-icon"
sizes="152x152"
href="./public/res/apple/apple-touch-icon-152x152.png"
/>
<link
rel="apple-touch-icon"
sizes="167x167"
href="./public/res/apple/apple-touch-icon-167x167.png"
/>
<link
rel="apple-touch-icon"
sizes="180x180"
href="./public/res/apple/apple-touch-icon-180x180.png"
/>
</head>
<body id="appBody">
<script>
window.global ||= window;
</script>
<div id="root"></div>
<audio id="notificationSound">
<source src="./public/sound/notification.ogg" type="audio/ogg" />
</audio>
<audio id="inviteSound">
<source src="./public/sound/invite.ogg" type="audio/ogg" />
</audio>
<script type="module" src="./src/index.jsx"></script>
</body>
</html>
BIN
View File
Binary file not shown.
+1935 -21037
View File
File diff suppressed because it is too large. Load diff
+67 -71
View File
@@ -1,87 +1,83 @@
{
"name": "cinny",
"version": "2.0.4",
"version": "2.2.4",
"description": "Yet another matrix client",
"main": "index.js",
"engines": {
"npm": ">=6.14.8 <=8.5.5",
"node": ">=14.15.0 <=17.9.0"
"node": ">=16.0.0"
},
"scripts": {
"start": "webpack serve --config ./webpack.dev.js --open",
"build": "webpack --config ./webpack.prod.js"
"start": "vite",
"build": "vite build",
"lint": "yarn check:eslint && yarn check:prettier",
"check:eslint": "eslint src/*",
"check:prettier": "prettier --check .",
"fix:prettier": "prettier --write .",
"typecheck": "tsc --noEmit"
},
"keywords": [],
"author": "Ajay Bura",
"license": "MIT",
"dependencies": {
"@fontsource/inter": "^4.5.11",
"@fontsource/roboto": "^4.5.7",
"@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.8.tgz",
"@tippyjs/react": "^4.2.6",
"babel-polyfill": "^6.26.0",
"browser-encrypt-attachment": "^0.3.0",
"dateformat": "^5.0.3",
"emojibase-data": "^7.0.1",
"file-saver": "^2.0.5",
"flux": "^4.0.3",
"formik": "^2.2.9",
"html-react-parser": "^1.4.14",
"katex": "^0.15.6",
"linkifyjs": "^2.1.9",
"matrix-js-sdk": "^18.1.0",
"micromark": "^3.0.10",
"micromark-extension-gfm": "^2.0.1",
"micromark-extension-math": "^2.0.2",
"micromark-util-chunked": "^1.0.0",
"micromark-util-resolve-all": "^1.0.0",
"micromark-util-symbol": "^1.0.1",
"prop-types": "^15.8.1",
"react": "^17.0.2",
"react-autosize-textarea": "^7.1.0",
"react-dnd": "^15.1.2",
"react-dnd-html5-backend": "^15.1.3",
"react-dom": "^17.0.2",
"react-google-recaptcha": "^2.1.0",
"react-modal": "^3.15.1",
"sanitize-html": "^2.7.0",
"tippy.js": "^6.3.7",
"twemoji": "^14.0.2"
"@fontsource/inter": "4.5.14",
"@fontsource/roboto": "4.5.8",
"@khanacademy/simple-markdown": "0.8.6",
"@lzy1960/google-translate": "0.2.6",
"@matrix-org/olm": "3.2.14",
"@tippyjs/react": "4.2.6",
"blurhash": "2.0.4",
"browser-encrypt-attachment": "0.3.0",
"dateformat": "5.0.3",
"emojibase-data": "7.0.1",
"file-saver": "2.0.5",
"flux": "4.0.3",
"formik": "2.2.9",
"google-translate-api-browser": "3.0.0",
"html-react-parser": "3.0.4",
"i18next": "22.4.9",
"i18next-browser-languagedetector": "7.0.1",
"i18next-http-backend": "2.1.1",
"katex": "0.16.4",
"linkify-html": "4.0.2",
"linkifyjs": "4.0.2",
"matrix-js-sdk": "22.0.0",
"prop-types": "15.8.1",
"react": "17.0.2",
"react-autosize-textarea": "7.1.0",
"react-blurhash": "0.2.0",
"react-dnd": "15.1.2",
"react-dnd-html5-backend": "15.1.3",
"react-dom": "17.0.2",
"react-google-recaptcha": "2.1.0",
"react-i18next": "12.1.5",
"react-modal": "3.16.1",
"sanitize-html": "2.8.0",
"tippy.js": "6.3.7",
"twemoji": "14.0.2"
},
"devDependencies": {
"@babel/core": "^7.18.5",
"@babel/preset-env": "^7.18.2",
"@babel/preset-react": "^7.17.12",
"assert": "^2.0.0",
"babel-loader": "^8.2.5",
"browserify-fs": "^1.0.0",
"buffer": "^6.0.3",
"clean-webpack-plugin": "^4.0.0",
"copy-webpack-plugin": "^11.0.0",
"crypto-browserify": "^3.12.0",
"css-loader": "^6.7.1",
"css-minimizer-webpack-plugin": "^4.0.0",
"eslint": "^8.17.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-react": "^7.30.0",
"eslint-plugin-react-hooks": "^4.5.0",
"favicons": "^6.2.2",
"favicons-webpack-plugin": "^5.0.2",
"html-loader": "^3.1.0",
"html-webpack-plugin": "^5.3.1",
"mini-css-extract-plugin": "^2.6.0",
"path-browserify": "^1.0.1",
"sass": "^1.52.3",
"sass-loader": "^13.0.0",
"stream-browserify": "^3.0.0",
"style-loader": "^3.3.1",
"url": "^0.11.0",
"util": "^0.12.4",
"webpack": "^5.73.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.9.2",
"webpack-merge": "^5.7.3"
"@esbuild-plugins/node-globals-polyfill": "0.2.3",
"@rollup/plugin-inject": "5.0.3",
"@rollup/plugin-wasm": "6.1.1",
"@types/node": "18.11.18",
"@types/react": "18.0.26",
"@types/react-dom": "18.0.9",
"@typescript-eslint/eslint-plugin": "5.46.1",
"@typescript-eslint/parser": "5.46.1",
"@vitejs/plugin-react": "3.0.0",
"buffer": "6.0.3",
"eslint": "8.29.0",
"eslint-config-airbnb": "19.0.4",
"eslint-config-prettier": "8.5.0",
"eslint-plugin-import": "2.26.0",
"eslint-plugin-jsx-a11y": "6.6.1",
"eslint-plugin-react": "7.31.11",
"eslint-plugin-react-hooks": "4.6.0",
"mini-svg-data-uri": "1.4.4",
"prettier": "2.8.1",
"sass": "1.56.2",
"typescript": "4.9.4",
"vite": "4.0.1",
"vite-plugin-static-copy": "0.13.0"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

-28
View File
@@ -1,28 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cinny</title>
<meta name="name" content="Cinny">
<meta name="author" content="Ajay Bura">
<meta name="description" content="A Matrix client where you can enjoy the conversation using simple, elegant and secure interface protected by e2ee with the power of open source.">
<meta name="keywords" content="cinny, cinnyapp, cinnychat, matrix, matrix client, matrix.org, element">
<meta property="og:title" content="Cinny">
<meta property="og:url" content="https://cinny.in">
<meta property="og:image" content="https://cinny.in/assets/favicon-48x48.png">
<meta property="og:description" content="A Matrix client where you can enjoy the conversation using simple, elegant and secure interface protected by e2ee with the power of open source.">
<meta name="theme-color" content="#000000">
</head>
<body id="appBody">
<div id="root"></div>
<audio id="notificationSound">
<source src="./sound/notification.ogg" type="audio/ogg" />
</audio>
<audio id="inviteSound">
<source src="./sound/invite.ogg" type="audio/ogg" />
</audio>
</body>
</html>
+889
View File
@@ -0,0 +1,889 @@
{
"translation": {
"common": {
"close": "Close",
"open": "Open",
"leave": "Leave",
"options": "Options",
"cinny": "Cinny",
"slogan": "Yet another matrix client",
"source_code": "Source code",
"sponsor": "Support",
"retry": "Retry",
"delete": "Delete",
"continue": "Continue",
"cancel": "Cancel",
"save": "Save",
"view_more": "View more",
"view_less": "View less",
"copy": "Copy",
"upload": "Upload",
"download": "Download",
"or": "Or",
"reset": "Reset",
"setup": "Setup",
"search": "Search",
"loading": "Loading...",
"joining": "Joining...",
"join": "Join",
"remove": "Remove",
"send": "Send",
"homeserver": "Homeserver",
"invite": "Invite",
"uninvite": "Uninvite",
"invited": "Invited",
"inviting": "Inviting...",
"uninviting": "Uninviting...",
"change": "Change",
"edit": "Edit",
"message_prompt": "Message"
},
"errors": {
"browser_not_supported": "Not supported in this browser",
"generic": "Something went wrong!"
},
"Organisms": {
"Welcome": {
"heading": "Welcome to Cinny!",
"subheading": "Yet another Matrix client"
},
"ViewSource": {
"title": "View Source",
"original_source": "Original source",
"decrypted_source": "Decrypted source"
},
"SpaceManage": {
"subtitle": "manage rooms",
"load_more": "Load more",
"rooms_and_spaces": "Rooms and spaces",
"private_rooms_message": "Either the space contains private rooms or you need to join space to view it's rooms.",
"items_selected_zero": "No selected items",
"items_selected_one": "{{count}} selected item",
"items_selected_other": "{{count}} selected items",
"room_members_zero": "No room members",
"room_members_one": "{{count}} room member",
"room_members_other": "{{count}} room members",
"mark_suggested_zero": "Marking no rooms as suggested",
"mark_suggested_one": "Marking {{count}} room as suggested",
"mark_suggested_other": "Marking {{count}} rooms as suggested",
"mark_not_suggested_zero": "Marking no rooms as suggested",
"mark_not_suggested_one": "Marking {{count}} room as suggested",
"mark_not_suggested_other": "Marking {{count}} rooms as suggested",
"remove_zero": "Removing no items",
"remove_one": "Removing {{count}} item",
"remove_other": "Removing {{count}} items.",
"suggested": "Suggested",
"mark_as_suggested": "Mark as suggested",
"mark_as_not_suggested": "Mark as not suggested"
},
"SpaceSettings": {
"subtitle": "space settings",
"leave": {
"leave_space": "Leave Space",
"leave_dialog_title": "Leave Space",
"leave_dialog_message": "Are you sure you want to leave {{space}}?"
},
"visibility": {
"header": "Space visibility (who can join)"
},
"addresses": {
"header": "Space addresses"
},
"categorize_subspaces": "Categorize subspaces",
"uncategorize_subspaces": "Uncategorize subspaces",
"pin_sidebar": "Pin to sidebar",
"unpin_sidebar": "Unpin from sidebar"
},
"Settings": {
"title": "Settings",
"theme": {
"follow_system": {
"title": "Follow system theme",
"description": "Use light or dark mode based on the system settings."
},
"title": "Theme",
"theme_light": "Light",
"theme_silver": "Silver",
"theme_dark": "Dark",
"theme_butter": "Butter"
},
"markdown": {
"title": "Markdown formatting",
"description": "Format messages with markdown before sending"
},
"hide_membership_events": {
"title": "Hide membership events",
"description": "Hide membership change messages from room timeline. (Join, Leave, Invite, Kick and Ban)"
},
"hide_nickname_avatar_events": {
"title": "Hide nick/avatar events",
"description": "Hide nickname and avatar change messages from the room timeline."
},
"notifications_and_sound": {
"title": "Notifications & Sound",
"desktop": {
"title": "Desktop notifications",
"description": "Show desktop notifications when new messages arrive."
},
"sound": {
"title": "Notification sound",
"description": "Play a sound when new messages arrive."
}
},
"security": {
"cross_signing": {
"title": "Cross signing and backup"
},
"export_import_encryption_keys": {
"title": "Export / Import encryption keys"
},
"export_encryption_keys": {
"title": "Export E2E room keys",
"description": "Export end-to-end encryption room keys to decrypt old messages in other session. In order to encrypt keys you need to set a password, which will be used while importing."
},
"import_encryption_keys": {
"title": "Import E2E room keys",
"description": "To decrypt older messages, Export E2EE room keys from Element (Settings > Security & Privacy > Encryption > Cryptography) and import them here. Imported keys are encrypted so you\\'ll have to enter the password you set in order to decrypt it."
}
},
"logout": {
"title": "Logout",
"dialog": {
"title": "Logout",
"description": "Are you sure that you want to logout your session?",
"confirm": "Logout"
}
},
"about": {
"application": "Application",
"credits": "Credits"
}
},
"ShortcutSpaces": {
"header": "Pin Spaces",
"pinned_spaces": "Pinned spaces",
"no_pinned_spaces": "No pinned spaces",
"unpinned_spaces": "Unpinned spaces",
"no_unpinned_spaces": "No unpinned spaces",
"spaces_selected_zero": "No selected spaces",
"spaces_selected_one": "{{count}} selected space",
"spaces_selected_other": "{{count}} selected spaces",
"pin_button": "Pin"
},
"SecretStorageAccess": {
"incorrect_security_key": "Incorrect security key",
"incorrect_security_phrase": "Incorrect security phrase",
"security_phrase": "Security Phrase",
"security_key": "Security Key",
"use_security_key": "Use Security Key",
"use_security_phrase": "Use Security Phrase"
},
"KeyBackup": {
"create_backup_title": "Create key backup",
"create_backup_tooltip": "Create backup",
"creating_backup": "Creating Backup...",
"backup_created": "Successfully created backup",
"backup_failed": "Failed to create backup",
"restoring": "Restoring backup keys...",
"restoring_progress": "Restoring backup keys... ({{progress}}/{{total}}",
"restore_backup_title": "Restore Key Backup",
"restore_backup_tooltip": "Restore Key Backup",
"restore_complete": "Successfully restored backup keys ({{progress}}/{{total}})",
"restore_failed_bad_key": "Failed to restore backup. Key is invalid!",
"restore_failed_unknown": "Failed to restore backup.",
"delete_key_backup_title": "Delete key backup",
"delete_key_backup_tooltip": "Delete backup",
"delete_key_backup_subtitle": "Deleting key backup is permanent.",
"delete_key_backup_message": "All encrypted message keys stored on the server will be permanently deleted.",
"encrypted_messages_backup_description": "Online backup your encrypted messages keys with your account data in case you lose access to your sessions. Your keys will be secured with a unique Security Key.",
"encrypted_messages_backup_title": "Encrypted messages backup",
"encrypted_messages_backup_cross_signing_disabled": "Setup cross signing to backup your encrypted messages."
},
"DeviceManage": {
"edit_session_name_title": "Edit session name",
"edit_session_name_subtitle": "Session name",
"edit_session_name_tooltip": "Edit session name",
"current_device_label": "Current",
"verify_session_button": "Verify",
"unverified_sessions_title": "Unverified sessions",
"unverified_sessions_none": "No unverified sessions",
"unencrypted_sessions_title": "Sessions without encryption support",
"verified_sessions_title": "Verified sessions",
"verified_sessions_none": "No verified sessions",
"setup_cross_signing_message": "Setup cross signing in case you lose all your sessions",
"loading_devices": "Loading devices...",
"logout_device_title": "Logout {{device}}",
"logout_device_message": "You are about to log out the session for {{device}}",
"logout_device_confirm": "Logout",
"logout_device_tooltip": "Remove session",
"session_verification_title": "Session Verification",
"session_name_privacy_message": "Session names are visible to everyone, so do not put any private info here."
},
"CrossSigning": {
"title": "Cross Signing",
"setup_failed": "Failed to setup cross signing. Please try again",
"setup": "Setup cross signing",
"save_security_key_message": "Please save this security key somewhere safe",
"security_key_dialog_title": "Security Key",
"security_key_generation_message": "We will generate a Security Key, which you can use to manage message backups and session verification.",
"security_key_generation_button": "Generate Key",
"security_phrase_message": "Alternatively you can set a 'Security Phrase' so you don't have to remember the long Security Key, and optionally save the key as a backup",
"security_phrase_label": "Security Phrase",
"security_phrase_confirm_label": "Confirm Security Phrase",
"security_phrase_set_button": "Set Phrase & Generate Key",
"setup_dialog_title": "Setup cross signing",
"setup_message": "Setup to verify and keep track of all your sessions. Also required to backup encrypted message.",
"reset_keys_subtitle": "Resetting cross-signing keys is permanent.",
"reset_keys_message": "Anyone you have verified with will see security alerts and your message backup will lost. You almost certainly do not want to do this, unless you have lost Security Key or Phrase and every session you can cross-sign from."
},
"AuthRequest": {
"wrong_password": "Wrong password. Please enter the correct password",
"request_failed": "Request failed!",
"password_label": "Account password"
},
"Search": {
"description": "Type # for rooms, @ for DMs and * for spaces. Hotkey: Ctrl + k"
},
"RoomViewInput": {
"upload_progress": "Uploading: {{progress}}/{{total}} ({{percent}}%)",
"tombstone_replaced": "This room has been replaced, and is no longer active.",
"tombstone_permission_denied": "You do not have permission to post to this room",
"send_message_placeholder": "Send a message...",
"emoji_tooltip": "Emoji",
"file_size": "Size: {{size}}",
"cancel_reply_tooltip": "Cancel reply"
},
"RoomViewHeader": {
"search_tooltip": "Search",
"people_tooltip": "People",
"members_tooltip": "Members"
},
"RoomViewFloating": {
"jump_unread": "Jump to unread messages",
"mark_read": "Mark as read",
"jump_latest": "Jump to latest",
"user_typing_1": "<bold><user_one/></bold> is typing...",
"user_typing_2": "<bold><user_one/></bold> and <bold><user_two/></bold> are typing...",
"user_typing_3": "<bold><user_one/></bold>, <bold><user_two/></bold> and <bold><user_three/></bold> are typing...",
"user_typing_4": "<bold><user_one/></bold>, <bold><user_two/></bold>, <bold><user_three/></bold> and <bold><user_four/></bold> are typing...",
"user_typing_other": "<bold>Several people</bold> are typing..."
},
"RoomViewContent": {
"welcome_to_room": "Welcome to {{room_name}}!",
"beginning_room": "This is the beginning of the <bold>{{room_name}}</bold> room.",
"beginning_dm": "This is the beginning of your direct message history with <bold>@{{user_name}}</bold>.",
"created_on": "Created on {{date, datetime}}",
"new_messages": "New messages"
},
"RoomSettings": {
"leave_room": "Leave room",
"leave_room_confirm_message": "Are you sure you want to leave {{room_name}}?",
"leave_room_confirm_button": "Leave",
"notification_header": "Notifications (Changing this will only affect you)",
"visibility_header": "Room visibility (Who can join)",
"address_header": "Room addresses",
"encryption_header": "Encryption",
"message_history_header": "Message history visibility",
"room_settings_subtitle": "room settings"
},
"RoomCommon": {
"user_joined": "<bold><user/></bold> joined the room",
"user_left": "<bold><user/></bold> left the room",
"user_left_reason": "<bold><user/></bold> left the room: <reason/>",
"user_invited": "<bold><inviter/></bold> invited <bold><user/></bold>",
"invite_cancelled": "<bold><inviter/></bold> cancelled <bold><user/>'s</bold> invite",
"invite_rejected": "<bold><user/></bold> rejected the invitation",
"user_kicked": "<bold><actor/></bold> kicked <bold><user/></bold>",
"user_kicked_reason": "<bold><actor/></bold> kicked <bold><user/></bold>: <reason/>",
"user_banned": "<bold><actor/></bold> banned <bold><user/></bold>",
"user_banned_reason": "<bold><actor/></bold> banned <bold><user/></bold>: <reason/>",
"user_unbanned": "<bold><actor/> unbanned <bold><user/></bold>",
"avatar_set": "<bold><user/></bold> set an avatar",
"avatar_changed": "<bold><user/></bold> changed their avatar",
"avatar_removed": "<bold><user/></bold> removed their avatar",
"name_set": "<bold><user/></bold> set their display name to <bold><new_name/></bold>",
"name_changed": "<bold><user/></bold> changed their display name to <bold><new_name/></bold>",
"name_removed": "<bold><user/></bold> removed their display name <bold><last_name/></bold>"
},
"PublicRooms": {
"could_not_join_alias": "Unable to join {{alias}}. Either the room is private or doesn't exist",
"try_joining_alias": "Try joining {{alias}}",
"joining_alias": "Joining {{alias}}...",
"no_public_rooms": "No public rooms on {{homeserver}}",
"no_result_found": "No result found for '{{input}}' on {{homeserver}}",
"title": "Public Rooms",
"search_room_name_alias": "Room name or alias",
"search_button": "Search",
"loading": "Loading public rooms from {{homeserver}}...",
"searching": "Searching for '{{query}}' on {{homeserver}}...",
"result_title": "Public rooms on {{homeserver}}",
"search_result_title": "Search result for '{{query}}' on {{homeserver}}"
},
"ProfileViewer": {
"kick_button": "Kick",
"kick_reason_label": "Kick Reason",
"ban_button": "Ban",
"ban_reason_label": "Ban reason",
"loading_sessions": "Loading sessions...",
"no_sessions_found": "No sessions found.",
"view_sessions_one": "View session",
"view_sessions_other": "View {{count}} sessions",
"send_direct_message_button": "Message",
"creating_dm_room": "Creating room...",
"ignore": "Ignore",
"ignoring": "Ignoring...",
"unignore": "Unignore",
"unignoring": "Unignoring...",
"change_power_level": "Change power level",
"shared_power_message": "You will not be able to undo this change as you are promoting the user to have the same power level as yourself. Are you sure?",
"demoting_self_message": "You will not be able to undo this change as you are demoting yourself. Are you sure?"
},
"PeopleDrawer": {
"title": "People",
"members_one": "{{count}} member",
"members_other": "{{count}} members",
"joined": "Joined",
"invited": "Invited",
"banned": "Banned",
"search_no_results": "No results found",
"view_more": "View more",
"placeholder": "Search",
"invite_tooltip": "Invite"
},
"ProfileEditor": {
"remove_avatar": "Remove avatar",
"remove_avatar_confirmation": "Are you sure that you want to remove your avatar?",
"display_name_message": "Display name of {{user_name}}"
},
"DrawerBreadcrumb": {
"home": "Home"
},
"DrawerHeader": {
"add_rooms_or_spaces": "Add rooms or spaces",
"create_new_space": "Create new space",
"create_new_room": "Create new room",
"join_public_room": "Join public room",
"join_with_address": "Join with address",
"add_existing": "Add existing",
"manage_rooms": "Manage rooms",
"home": "Home",
"direct_messages": "Direct messages",
"start_dm_tooltip": "Start DM",
"add_rooms_spaces_tooltip": "Add rooms/spaces"
},
"SideBar": {
"settings_tooltip": "Settings",
"unverified_sessions_one": "{{count}} unverified session",
"unverified_sessions_other": "{{count}} unverified sessions",
"home_tooltip": "Home",
"direct_messages_tooltip": "People",
"pin_spaces_tooltip": "Pin spaces",
"search_tooltip": "Search",
"invites_tooltip": "Invites"
},
"JoinAlias": {
"invalid_address": "Invalid address.",
"looking_for_address": "Looking for address...",
"joining_alias": "Joining {{alias_name}}...",
"couldnt_find_room_or_space_alias": "Unable to find room/space with {{alias_name}}. Either the room/space is private or doesn't exist.",
"couldnt_find_room_or_space": "Unable to join {{alias_name}}. Either the room/space is private or doesn't exist.",
"address_label": "Address",
"title": "Join with address"
},
"InviteUser": {
"user_not_found": "{{user_name}} not found!",
"no_matches_found": "No matches found for {{user_name}}",
"invite_result": {
"invited": "Invited",
"already_joined": "Already joined",
"already_invited": "Already invited",
"banned": "Banned"
},
"search_label": "Name or User ID",
"search_result_title": "Search result for user {{user_name}}",
"searching_for_user": "Searching for user {{user_name}}...",
"invite_to_room": "Invite to {{room}}",
"invite_to_dm": "Direct Message"
},
"InviteList": {
"accept_invite": "Accept",
"reject_invite": "Reject",
"direct_messages_title": "Direct Messages",
"rooms_title": "Rooms",
"spaces_title": "Spaces",
"title": "Invites"
},
"EmojiVerification": {
"waiting_for_response": "Waiting for response from other device...",
"confirmation_prompt": "Confirm the emoji below are displayed on both devices, in the same order:",
"emojis_match_button": "They match",
"emojis_dont_match_button": "They don't match",
"accept_request_from_other_device_message": "Please accept the request from other device.",
"begin_verification_process_message": "Click accept to start the verification process.",
"begin_verification_button_text": "Accept",
"title": "Emoji Verification"
},
"DragDrop": {
"drop_file_to_upload_prompt": "Drop file to upload"
},
"CreateRoom": {
"private_room_short": "Private",
"restricted_room_short": "Restricted",
"public_room_short": "Public",
"private_room_long": "Private (invite only)",
"restricted_room_long": "Restricted (space member can join)",
"public_room_long": "Public (anyone can join)",
"visibility_title": "Visibility",
"visibility_message": "Visibility (who can join)",
"select_who_can_join_space": "Select who can join this space",
"select_who_can_join_room": "Select who can join this room",
"space_address": "Space address",
"room_address": "Room address",
"room_address_already_in_use": "{{room_address}} is already in use",
"e2e_title": "Enable end-to-end encryption",
"e2e_message": "You can’t disable this later. Bridges & most bots won’t work yet.",
"role_title": "Select your role",
"role_message": "Selecting 'Admin' sets your power level to 100 whereas 'Founder' sets it to 101.",
"creating_room": "Creating room...",
"creating_space": "Creating space...",
"topic_label": "Topic (optional)",
"space_name": "Space name",
"room_name": "Room name",
"role_admin": "Admin",
"role_founder": "Founder",
"create_room": "Create room",
"create_space": "Create space",
"home": "Home"
}
},
"Molecules": {
"ConfirmDialog": {
"cancel": "Cancel"
},
"ReusableDialog": {
"close_tooltip": "Close"
},
"FollowingMembers": {
"users_following_1": "<bold><user_one/></bold> is following the conversation",
"users_following_2": "<bold><user_one/></bold> and <bold><user_two/></bold> are following the conversation",
"users_following_3": "<bold><user_one/></bold>, <bold><user_two/></bold>, and <bold><user_three/></bold> are following the conversation",
"users_following_other": "<bold><user_one/></bold>, <bold><user_two/></bold>, <bold><user_three/></bold> and {{other_count}} others are following the conversation"
},
"ImageUpload": {
"prompt": "Upload",
"cancel": "Cancel",
"remove": "Remove"
},
"ExportE2ERoomKeys": {
"getting_keys": "Getting keys...",
"encrypting_keys": "Encrypting Keys...",
"password_does_not_match": "Password does not match.",
"export_success": "Successfully exported all keys.",
"export_failed": "Failed to export keys. Please try again.",
"button_text": "Export"
},
"ImportE2ERoomKeys": {
"decrypting_file": "Decrypting file...",
"decrypting_messages": "Decrypting messages...",
"import_success": "Successfully imported all keys",
"import_failed": "Failed tp decrypt keys. Please try again",
"import_keys_button": "Import Keys",
"decrypt_button": "Decrypt"
},
"Media": {
"open_new_tab": "Open in new tab",
"download": "Download",
"play_audio": "Play audio",
"play_video": "Play video"
},
"Message": {
"message_deleted": "*** This message has been deleted ***",
"unable_to_load_reply": "*** Unable to load reply ***",
"unknown_user": "** Unknown user **",
"edited": "(edited)",
"edit_placeholder": "Edit message",
"user_reacted_1": "<bold><user_one/></bold> reacted with <emoji/>",
"user_reacted_2": "<bold><user_one/></bold> and <bold><user_two/></bold> reacted with <emoji/>",
"user_reacted_3": "<bold><user_one/></bold>, <bold><user_two/></bold> and <bold><user_three/></bold> reacted with <emoji/>",
"user_reacted_other": "<bold><user_one/></bold>, <bold><user_two/></bold>, <bold><user_three/></bold> and {{other_count}} others reacted with <emoji/>",
"add_reaction_tooltip": "Add reaction",
"reply_tooltip": "Reply",
"edit_tooltip": "Edit",
"options_header": "Options",
"options_tooltip": "Options",
"read_receipts": "Read receipts",
"view_source": "View source",
"delete_message_prompt": "Delete message",
"delete_message_confirmation": "Are you sure that you want to delete this message?",
"delete_message_button": "Delete"
},
"PopupWindow": {
"close_tooltip": "Back"
},
"PowerLevelSelector": {
"placeholder": "Power level"
},
"RoomAliases": {
"invalid_characters": "Invalid character: only letter, numbers and _- are allowed.",
"validating_alias": "validating {{alias}}...",
"alias_available": "{{alias}} is available.",
"alias_unavailable": "{{alias}} is unavailable.",
"deleting_alias": "Deleting...",
"set_main_alias": "Set as Main",
"publish_alias": "Publish",
"unpublish_alias": "Unpublish",
"delete_alias": "Delete",
"main_alias": "Main",
"publish_to_room_directory": {
"title": "Publish to room directory",
"publish_room_message": "Publish this room to the {{homeserver}} publish directory?",
"publish_space_message": "Publish this space to the {{homeserver}} publish directory?"
},
"published_addresses": {
"title": "Published addresses",
"none": "No published addresses",
"no_main_address": "No main address (select one from below)",
"message_room": "Published addresses can be used by anyone on any server to join your room. To publish an address, it needs to be set as a local address first.",
"message_space": "Published addresses can be used by anyone on any server to join your space. To publish an address, it needs to be set as a local address first."
},
"local_addresses": {
"title": "Local addresses",
"none": "No local addresses",
"message_room": "Set local addresses for this room so users can find this room through your homeserver.",
"message_space": "Set local addresses for this space so users can find this space through your homeserver.",
"add": "Add local address",
"add_button": "Add",
"placeholder_room": "my_room_address",
"placeholder_space": "my_space_address",
"hide": "Hide local addresses",
"view": "View local addresses"
}
},
"RoomEncryption": {
"encryption_public_room_message": "It is not recommended to add encryption in public room. Anyone can find and join public rooms, so anyone should be able to read messages in them.",
"encryption_message": "Once enabled, encryption for a room cannot be disabled. Messages sent in an encrypted room cannot be seen by the server, only by the participants of the room. Enabling encryption may prevent many bots and bridges from working correctly",
"encryption_cannot_be_disabled": "Once enabled, encryption cannot be disabled.",
"enable_room_encryption": "Enable room encryption",
"enable_encryption_prompt": "Enable Encryption",
"enable_encryption_button": "Enable",
"continue_button": "Continue"
},
"RoomHistoryVisibility": {
"world_readable": "Anyone (including guests)",
"shared": "Members (all messages)",
"invited": "Members (messages after invite)",
"joined": "Members (messages after join)",
"changes_only_affect_future": "Changes to history visibility will only apply to future messages. The visibility of existing history will have no effect."
},
"RoomMembers": {
"search_title": "Search member",
"found_members_one": "Found — one member",
"found_members_other": "Found — {{count}} members",
"no_results": "No results found for {{term}}",
"no_members": "No members to display",
"view_more": "View more",
"joined": "Joined",
"invited": "Invited",
"banned": "Banned",
"search_placeholder": "Search for name"
},
"RoomNotification": {
"default": "Global",
"all_messages": "All messages",
"mentions_and_keywords": "Mentions & Keywords",
"mute": "Mute"
},
"RoomOptions": {
"title": "Options for {{room_name}}",
"leave": {
"title": "Leave room",
"subtitle": "Are you sure you want to leave the {{room_name}} room?",
"button_text": "Leave"
},
"mark_as_read": "Mark as read",
"notifications_heading": "Notifications",
"invite": "Invite"
},
"RoomPermissions": {
"default_role": {
"name": "Default role",
"description": "Set default role for all members"
},
"send_messages": {
"name": "Send messages",
"description": "Set minimum power level to send messages in a room"
},
"reactions": {
"name": "Send reactions",
"description": "Set minimum power level to send reactions in a room"
},
"delete": {
"name": "Delete messages sent by others",
"description": "Set minumum power level to delete messages in a room"
},
"notifications": {
"name": "Ping room",
"description": "Set minimum power level to ping room"
},
"manage_rooms": {
"name": "Manage rooms in space",
"description": "Set minimum power level to manage rooms in space"
},
"invite": {
"name": "Invite",
"description": "Set minimum power level to invite members"
},
"kick": {
"name": "Kick",
"description": "Set minimum power level to kick members"
},
"ban": {
"name": "Ban",
"description": "Set minimum power level to ban members"
},
"change_avatar": {
"name": "Change avatar",
"description": "Set minimum power level to change room/space avatar"
},
"change_name": {
"name": "Change name",
"description": "Set minimum power evel to change room/space name"
},
"change_topic": {
"name": "Change topic",
"description": "Set minimum power level to change room/space topic"
},
"change_settings": {
"name": "Change settings",
"description": "Set minimum power level to change settings"
},
"change_published_address": {
"name": "Change published address",
"description": "Set minimum power level to publish and set main address"
},
"change_permissions": {
"name": "Change permissions",
"description": "Set minimum power level to change permissions"
},
"enable_room_encryption": {
"name": "Enable room encryption",
"description": "Set minimum power level to enable room encryption"
},
"change_history_visibility": {
"name": "Change history visibility",
"description": "Set minimum power level to change room message history visibility"
},
"upgrade_room": {
"name": "Upgrade room",
"description": "Set minimum power level to upgrade room"
},
"pin_messages": {
"name": "Pin messages",
"description": "Set minimum power level to pin messages in a room"
},
"change_acls": {
"name": "Change server ACLs",
"description": "Set minimum power level to change server ACLs"
},
"modify_widgets": {
"name": "Modify widgets",
"description": "Set minimum power level to modify room widgets"
},
"groups": {
"general": "General permissions",
"manage_members": "Manage members permissions",
"room": "Room profile permissions",
"space": "Space profile permissions",
"other": "Other permissions",
"settings": "Settings permissions"
}
},
"RoomProfile": {
"saving_room_name": "Saving room name...",
"saving_room_topic": "Saving room topic...",
"save_success": "Saved successfully",
"save_failed": "Unable to save",
"remove_avatar_title": "Remove avatar",
"remove_avatar_subtitle": "Are you sure that you want to remove room avatar?",
"remove_avatar_button": "Remove",
"permission_change_room_name": "You have permission to change room name only",
"permission_change_room_topic": "You have permission to change room topic only",
"permission_change_space_name": "You have permission to change space name only",
"permission_change_space_topic": "You have permission to change space topic only",
"name_label": "Name",
"topic_label": "Topic"
},
"RoomSearch": {
"title": "Room search",
"placeholder": "Search for keywords",
"search_button": "Search",
"searching": "Searching room messages...",
"subtitle": "Search room messages",
"failed": "Failed to search messages",
"no_results": "No results found",
"encrypted_room": "Search does not work in encrypted room",
"load_more": "Load more",
"results_one": "{{count}} result for {{term}}",
"results_other": "{{count}} results for {{term}}"
},
"RoomTile": {
"invited_by_user_zero": "Invited by {{inviter}} to {{id}}",
"invited_by_user_one": "Invited by {{inviter}} to {{id}} • {{member_count}} member",
"invited_by_user_other": "Invited by {{inviter}} to {{id}} • {{member_count}} members",
"invited_zero": "{{id}}",
"invited_one": "{{id}} • {{member_count}} member",
"invited_other": "{{id}} • {{member_count}} members"
},
"RoomVisibility": {
"private": "Private (invite only)",
"restricted": "Restricted (space members can join)",
"restricted_unsupported": "Restricted (Unsupported: room required upgrade)",
"public": "Public (anyone can join)"
},
"RoomEmojis": {
"header": "Create Pack",
"submit_button": "Create pack",
"name_placeholder": "Pack Name",
"no_packs": "No emoji or sticker packs."
},
"ImagePack": {
"rename_title": "Rename",
"rename_button": "Rename",
"shortcode_label": "Shortcode",
"delete_item_title": "Delete",
"delete_item_message": "Are you sure that you want to delete {{key}}?",
"delete_item_button": "Delete",
"delete_pack_title": "Delete Pack",
"delete_pack_message": "Are you sure that you want to delete {{pack_name}}?",
"delete_pack_button": "Delete",
"image_title": "Image",
"image_shortcode": "Shortcode",
"image_usage": "Usage",
"view_more": "View {{count}} more",
"view_less": "View less",
"use_globally": "Use globally",
"use_globally_description": "Add this pack to your account to use in all rooms.",
"no_global_packs": "No global packs",
"default_personal_pack_name": "Personal"
},
"ImagePackItem": {
"rename_tooltip": "Rename",
"delete_tooltip": "Delete"
},
"ImagePackUsageSelector": {
"header": "Usage",
"type_emoji": "Emoji",
"type_sticker": "Sticker",
"type_both": "Both"
},
"ImagePackUpload": {
"remove_file_tooltip": "Remove file",
"import_image_button": "Import image",
"shortcode_placeholder": "shortcode",
"upload_button": "Upload",
"upload_button_progress": "Uploading..."
},
"ImagePackProfile": {
"attribution_prompt": "Attribution",
"name_prompt": "Name",
"edit_tooltip": "Edit",
"usage_header": "Usage",
"pack_usage": "Pack usage"
},
"SpaceAddExisting": {
"adding_items_one": "Adding one item...",
"adding_items_other": "Adding {{count}} items...",
"items_selected_one": "{{count}} item selected",
"items_selected_other": "{{count}} items selected",
"search_rooms_placeholder": "Search rooms",
"no_results": "No results found",
"add_button": "Add",
"subtitle": "add existing rooms"
},
"SpaceOptions": {
"leave_space": "Leave Space",
"leave_space_confirmation": "Are you sure that you want to leave the {{space}} space?",
"leave_space_confirm": "Leave",
"invite": "Invite",
"manage_rooms": "Manage rooms",
"settings": "Settings",
"leave": "Leave"
},
"SSOButtons": {
"login_with": "Login with {{idp_name}}"
}
},
"Templates": {
"Auth": {
"loading_homeserver_list": "Loading homeserver list...",
"looking_for_homeserver": "Looking for homeserver...",
"connecting_to_homeserver": "Connecting to {{homeserver}}...",
"unable_to_connect": "Unable to connect. Please check your input",
"username_taken": "Username is already taken",
"registration_in_progress": "Registration in progress...",
"link_about": "About",
"link_twitter": "Twitter",
"link_matrix": "Powered by Matrix",
"dont_have_an_account": "Dont have an account?",
"already_have_an_account": "Already have an account?",
"register_link": "Register",
"login_link": "Login",
"redirecting": "Redirecting...",
"login_in_progress": "Login in progress...",
"bad_localpart_error": "Username can only contain characters a-z, 0-9, or '=_-./'",
"user_id_too_long_error": "Your user ID, including the hostname, can't be more than 255 characters long.",
"bad_password_error": "Password must contain at least 1 lowercase, 1 uppercase, 1 number, 1 non-alphanumeric character, 8-127 characters with no space.",
"confirm_password_error": "Passwords don't match.",
"bad_email_error": "Invalid email address",
"invalid_password": "Invalid password",
"check_credentials": "Please check your credentials",
"login_types": {
"username": "Username",
"email": "Email"
},
"homeserver_form": {
"title": "Homeserver",
"header": "Homeserver list"
},
"login_form": {
"title": "Login",
"prompt_email": "Email",
"prompt_username": "Username",
"prompt_password": "Password",
"login_button": "Login"
},
"register_form": {
"title": "Register",
"prompt_email_required": "Email (Required)",
"prompt_email_optional": "Email",
"prompt_username": "Username",
"prompt_password": "Password",
"prompt_confirm_password": "Confirm password",
"register_button": "Register"
},
"terms_and_conditions": {
"title": "Agree with terms",
"description": "In order to complete registration, you need to agree to the terms and conditions.",
"accept": "I accept <a>Terms and Conditions</a>",
"submit_button": "Submit"
},
"validate_email": {
"title": "Verify email",
"continue_button": "Continue",
"message": "Please check your email <bold>{{email_address}}</bold> and validate before continuing further"
},
"captcha": {
"message": "Pleace check the box below to proceed"
}
},
"Client": {
"loading_messages": {
"default": "Heating up",
"message_one": "Almost there...",
"message_two": "Looks like you have a lot of stuff to heat up!"
},
"logout_prompt": "Logout"
}
}
}
}
+889
View File
@@ -0,0 +1,889 @@
{
"translation": {
"common": {
"close": "Close",
"open": "Open",
"leave": "Leave",
"options": "Options",
"cinny": "Cinny",
"slogan": "Yet another matrix client",
"source_code": "Source code",
"sponsor": "Support",
"retry": "Retry",
"delete": "Delete",
"continue": "Continue",
"cancel": "Cancel",
"save": "Save",
"view_more": "View more",
"view_less": "View less",
"copy": "Copy",
"upload": "Upload",
"download": "Download",
"or": "Or",
"reset": "Reset",
"setup": "Setup",
"search": "Search",
"loading": "Loading...",
"joining": "Joining...",
"join": "Join",
"remove": "Remove",
"send": "Send",
"homeserver": "Homeserver",
"invite": "Invite",
"uninvite": "Uninvite",
"invited": "Invited",
"inviting": "Inviting...",
"uninviting": "Uninviting...",
"change": "Change",
"edit": "Edit",
"message_prompt": "Message"
},
"errors": {
"browser_not_supported": "Not supported in this browser",
"generic": "Something went wrong!"
},
"Organisms": {
"Welcome": {
"heading": "Welcome to Cinny!",
"subheading": "Yet another Matrix client"
},
"ViewSource": {
"title": "View Source",
"original_source": "Original source",
"decrypted_source": "Decrypted source"
},
"SpaceManage": {
"subtitle": "manage rooms",
"load_more": "Load more",
"rooms_and_spaces": "Rooms and spaces",
"private_rooms_message": "Either the space contains private rooms or you need to join space to view it's rooms.",
"items_selected_zero": "No selected items",
"items_selected_one": "{{count}} selected item",
"items_selected_other": "{{count}} selected items",
"room_members_zero": "No room members",
"room_members_one": "{{count}} room member",
"room_members_other": "{{count}} room members",
"mark_suggested_zero": "Marking no rooms as suggested",
"mark_suggested_one": "Marking {{count}} room as suggested",
"mark_suggested_other": "Marking {{count}} rooms as suggested",
"mark_not_suggested_zero": "Marking no rooms as suggested",
"mark_not_suggested_one": "Marking {{count}} room as suggested",
"mark_not_suggested_other": "Marking {{count}} rooms as suggested",
"remove_zero": "Removing no items",
"remove_one": "Removing {{count}} item",
"remove_other": "Removing {{count}} items.",
"suggested": "Suggested",
"mark_as_suggested": "Mark as suggested",
"mark_as_not_suggested": "Mark as not suggested"
},
"SpaceSettings": {
"subtitle": "space settings",
"leave": {
"leave_space": "Leave Space",
"leave_dialog_title": "Leave Space",
"leave_dialog_message": "Are you sure you want to leave {{space}}?"
},
"visibility": {
"header": "Space visibility (who can join)"
},
"addresses": {
"header": "Space addresses"
},
"categorize_subspaces": "Categorize subspaces",
"uncategorize_subspaces": "Uncategorize subspaces",
"pin_sidebar": "Pin to sidebar",
"unpin_sidebar": "Unpin from sidebar"
},
"Settings": {
"title": "设置",
"theme": {
"follow_system": {
"title": "Follow system theme",
"description": "Use light or dark mode based on the system settings."
},
"title": "主题",
"theme_light": "Light",
"theme_silver": "Silver",
"theme_dark": "Dark",
"theme_butter": "Butter"
},
"markdown": {
"title": "Markdown formatting",
"description": "Format messages with markdown before sending"
},
"hide_membership_events": {
"title": "Hide membership events",
"description": "Hide membership change messages from room timeline. (Join, Leave, Invite, Kick and Ban)"
},
"hide_nickname_avatar_events": {
"title": "Hide nick/avatar events",
"description": "Hide nickname and avatar change messages from the room timeline."
},
"notifications_and_sound": {
"title": "Notifications & Sound",
"desktop": {
"title": "Desktop notifications",
"description": "Show desktop notifications when new messages arrive."
},
"sound": {
"title": "Notification sound",
"description": "Play a sound when new messages arrive."
}
},
"security": {
"cross_signing": {
"title": "Cross signing and backup"
},
"export_import_encryption_keys": {
"title": "Export / Import encryption keys"
},
"export_encryption_keys": {
"title": "Export E2E room keys",
"description": "Export end-to-end encryption room keys to decrypt old messages in other session. In order to encrypt keys you need to set a password, which will be used while importing."
},
"import_encryption_keys": {
"title": "Import E2E room keys",
"description": "To decrypt older messages, Export E2EE room keys from Element (Settings > Security & Privacy > Encryption > Cryptography) and import them here. Imported keys are encrypted so you\\'ll have to enter the password you set in order to decrypt it."
}
},
"logout": {
"title": "Logout",
"dialog": {
"title": "Logout",
"description": "Are you sure that you want to logout your session?",
"confirm": "Logout"
}
},
"about": {
"application": "Application",
"credits": "Credits"
}
},
"ShortcutSpaces": {
"header": "Pin Spaces",
"pinned_spaces": "Pinned spaces",
"no_pinned_spaces": "No pinned spaces",
"unpinned_spaces": "Unpinned spaces",
"no_unpinned_spaces": "No unpinned spaces",
"spaces_selected_zero": "No selected spaces",
"spaces_selected_one": "{{count}} selected space",
"spaces_selected_other": "{{count}} selected spaces",
"pin_button": "Pin"
},
"SecretStorageAccess": {
"incorrect_security_key": "Incorrect security key",
"incorrect_security_phrase": "Incorrect security phrase",
"security_phrase": "Security Phrase",
"security_key": "Security Key",
"use_security_key": "Use Security Key",
"use_security_phrase": "Use Security Phrase"
},
"KeyBackup": {
"create_backup_title": "Create key backup",
"create_backup_tooltip": "Create backup",
"creating_backup": "Creating Backup...",
"backup_created": "Successfully created backup",
"backup_failed": "Failed to create backup",
"restoring": "Restoring backup keys...",
"restoring_progress": "Restoring backup keys... ({{progress}}/{{total}}",
"restore_backup_title": "Restore Key Backup",
"restore_backup_tooltip": "Restore Key Backup",
"restore_complete": "Successfully restored backup keys ({{progress}}/{{total}})",
"restore_failed_bad_key": "Failed to restore backup. Key is invalid!",
"restore_failed_unknown": "Failed to restore backup.",
"delete_key_backup_title": "Delete key backup",
"delete_key_backup_tooltip": "Delete backup",
"delete_key_backup_subtitle": "Deleting key backup is permanent.",
"delete_key_backup_message": "All encrypted message keys stored on the server will be permanently deleted.",
"encrypted_messages_backup_description": "Online backup your encrypted messages keys with your account data in case you lose access to your sessions. Your keys will be secured with a unique Security Key.",
"encrypted_messages_backup_title": "Encrypted messages backup",
"encrypted_messages_backup_cross_signing_disabled": "Setup cross signing to backup your encrypted messages."
},
"DeviceManage": {
"edit_session_name_title": "Edit session name",
"edit_session_name_subtitle": "Session name",
"edit_session_name_tooltip": "Edit session name",
"current_device_label": "Current",
"verify_session_button": "Verify",
"unverified_sessions_title": "Unverified sessions",
"unverified_sessions_none": "No unverified sessions",
"unencrypted_sessions_title": "Sessions without encryption support",
"verified_sessions_title": "Verified sessions",
"verified_sessions_none": "No verified sessions",
"setup_cross_signing_message": "Setup cross signing in case you lose all your sessions",
"loading_devices": "Loading devices...",
"logout_device_title": "Logout {{device}}",
"logout_device_message": "You are about to log out the session for {{device}}",
"logout_device_confirm": "Logout",
"logout_device_tooltip": "Remove session",
"session_verification_title": "Session Verification",
"session_name_privacy_message": "Session names are visible to everyone, so do not put any private info here."
},
"CrossSigning": {
"title": "Cross Signing",
"setup_failed": "Failed to setup cross signing. Please try again",
"setup": "Setup cross signing",
"save_security_key_message": "Please save this security key somewhere safe",
"security_key_dialog_title": "Security Key",
"security_key_generation_message": "We will generate a Security Key, which you can use to manage message backups and session verification.",
"security_key_generation_button": "Generate Key",
"security_phrase_message": "Alternatively you can set a 'Security Phrase' so you don't have to remember the long Security Key, and optionally save the key as a backup",
"security_phrase_label": "Security Phrase",
"security_phrase_confirm_label": "Confirm Security Phrase",
"security_phrase_set_button": "Set Phrase & Generate Key",
"setup_dialog_title": "Setup cross signing",
"setup_message": "Setup to verify and keep track of all your sessions. Also required to backup encrypted message.",
"reset_keys_subtitle": "Resetting cross-signing keys is permanent.",
"reset_keys_message": "Anyone you have verified with will see security alerts and your message backup will lost. You almost certainly do not want to do this, unless you have lost Security Key or Phrase and every session you can cross-sign from."
},
"AuthRequest": {
"wrong_password": "Wrong password. Please enter the correct password",
"request_failed": "Request failed!",
"password_label": "Account password"
},
"Search": {
"description": "Type # for rooms, @ for DMs and * for spaces. Hotkey: Ctrl + k"
},
"RoomViewInput": {
"upload_progress": "Uploading: {{progress}}/{{total}} ({{percent}}%)",
"tombstone_replaced": "This room has been replaced, and is no longer active.",
"tombstone_permission_denied": "You do not have permission to post to this room",
"send_message_placeholder": "Send a message...",
"emoji_tooltip": "Emoji",
"file_size": "Size: {{size}}",
"cancel_reply_tooltip": "Cancel reply"
},
"RoomViewHeader": {
"search_tooltip": "Search",
"people_tooltip": "People",
"members_tooltip": "Members"
},
"RoomViewFloating": {
"jump_unread": "Jump to unread messages",
"mark_read": "Mark as read",
"jump_latest": "Jump to latest",
"user_typing_1": "<bold><user_one/></bold> is typing...",
"user_typing_2": "<bold><user_one/></bold> and <bold><user_two/></bold> are typing...",
"user_typing_3": "<bold><user_one/></bold>, <bold><user_two/></bold> and <bold><user_three/></bold> are typing...",
"user_typing_4": "<bold><user_one/></bold>, <bold><user_two/></bold>, <bold><user_three/></bold> and <bold><user_four/></bold> are typing...",
"user_typing_other": "<bold>Several people</bold> are typing..."
},
"RoomViewContent": {
"welcome_to_room": "Welcome to {{room_name}}!",
"beginning_room": "This is the beginning of the <bold>{{room_name}}</bold> room.",
"beginning_dm": "This is the beginning of your direct message history with <bold>@{{user_name}}</bold>.",
"created_on": "Created on {{date, datetime}}",
"new_messages": "New messages"
},
"RoomSettings": {
"leave_room": "Leave room",
"leave_room_confirm_message": "Are you sure you want to leave {{room_name}}?",
"leave_room_confirm_button": "Leave",
"notification_header": "Notifications (Changing this will only affect you)",
"visibility_header": "Room visibility (Who can join)",
"address_header": "Room addresses",
"encryption_header": "Encryption",
"message_history_header": "Message history visibility",
"room_settings_subtitle": "room settings"
},
"RoomCommon": {
"user_joined": "<bold><user/></bold> joined the room",
"user_left": "<bold><user/></bold> left the room",
"user_left_reason": "<bold><user/></bold> left the room: <reason/>",
"user_invited": "<bold><inviter/></bold> invited <bold><user/></bold>",
"invite_cancelled": "<bold><inviter/></bold> cancelled <bold><user/>'s</bold> invite",
"invite_rejected": "<bold><user/></bold> rejected the invitation",
"user_kicked": "<bold><actor/></bold> kicked <bold><user/></bold>",
"user_kicked_reason": "<bold><actor/></bold> kicked <bold><user/></bold>: <reason/>",
"user_banned": "<bold><actor/></bold> banned <bold><user/></bold>",
"user_banned_reason": "<bold><actor/></bold> banned <bold><user/></bold>: <reason/>",
"user_unbanned": "<bold><actor/> unbanned <bold><user/></bold>",
"avatar_set": "<bold><user/></bold> set an avatar",
"avatar_changed": "<bold><user/></bold> changed their avatar",
"avatar_removed": "<bold><user/></bold> removed their avatar",
"name_set": "<bold><user/></bold> set their display name to <bold><new_name/></bold>",
"name_changed": "<bold><user/></bold> changed their display name to <bold><new_name/></bold>",
"name_removed": "<bold><user/></bold> removed their display name <bold><last_name/></bold>"
},
"PublicRooms": {
"could_not_join_alias": "Unable to join {{alias}}. Either the room is private or doesn't exist",
"try_joining_alias": "Try joining {{alias}}",
"joining_alias": "Joining {{alias}}...",
"no_public_rooms": "No public rooms on {{homeserver}}",
"no_result_found": "No result found for '{{input}}' on {{homeserver}}",
"title": "Public Rooms",
"search_room_name_alias": "Room name or alias",
"search_button": "Search",
"loading": "Loading public rooms from {{homeserver}}...",
"searching": "Searching for '{{query}}' on {{homeserver}}...",
"result_title": "Public rooms on {{homeserver}}",
"search_result_title": "Search result for '{{query}}' on {{homeserver}}"
},
"ProfileViewer": {
"kick_button": "Kick",
"kick_reason_label": "Kick Reason",
"ban_button": "Ban",
"ban_reason_label": "Ban reason",
"loading_sessions": "Loading sessions...",
"no_sessions_found": "No sessions found.",
"view_sessions_one": "View session",
"view_sessions_other": "View {{count}} sessions",
"send_direct_message_button": "Message",
"creating_dm_room": "Creating room...",
"ignore": "Ignore",
"ignoring": "Ignoring...",
"unignore": "Unignore",
"unignoring": "Unignoring...",
"change_power_level": "Change power level",
"shared_power_message": "You will not be able to undo this change as you are promoting the user to have the same power level as yourself. Are you sure?",
"demoting_self_message": "You will not be able to undo this change as you are demoting yourself. Are you sure?"
},
"PeopleDrawer": {
"title": "People",
"members_one": "{{count}} member",
"members_other": "{{count}} members",
"joined": "Joined",
"invited": "Invited",
"banned": "Banned",
"search_no_results": "No results found",
"view_more": "View more",
"placeholder": "Search",
"invite_tooltip": "Invite"
},
"ProfileEditor": {
"remove_avatar": "Remove avatar",
"remove_avatar_confirmation": "Are you sure that you want to remove your avatar?",
"display_name_message": "Display name of {{user_name}}"
},
"DrawerBreadcrumb": {
"home": "Home"
},
"DrawerHeader": {
"add_rooms_or_spaces": "Add rooms or spaces",
"create_new_space": "Create new space",
"create_new_room": "Create new room",
"join_public_room": "Join public room",
"join_with_address": "Join with address",
"add_existing": "Add existing",
"manage_rooms": "Manage rooms",
"home": "Home",
"direct_messages": "Direct messages",
"start_dm_tooltip": "Start DM",
"add_rooms_spaces_tooltip": "Add rooms/spaces"
},
"SideBar": {
"settings_tooltip": "Settings",
"unverified_sessions_one": "{{count}} unverified session",
"unverified_sessions_other": "{{count}} unverified sessions",
"home_tooltip": "Home",
"direct_messages_tooltip": "People",
"pin_spaces_tooltip": "Pin spaces",
"search_tooltip": "Search",
"invites_tooltip": "Invites"
},
"JoinAlias": {
"invalid_address": "Invalid address.",
"looking_for_address": "Looking for address...",
"joining_alias": "Joining {{alias_name}}...",
"couldnt_find_room_or_space_alias": "Unable to find room/space with {{alias_name}}. Either the room/space is private or doesn't exist.",
"couldnt_find_room_or_space": "Unable to join {{alias_name}}. Either the room/space is private or doesn't exist.",
"address_label": "Address",
"title": "Join with address"
},
"InviteUser": {
"user_not_found": "{{user_name}} not found!",
"no_matches_found": "No matches found for {{user_name}}",
"invite_result": {
"invited": "Invited",
"already_joined": "Already joined",
"already_invited": "Already invited",
"banned": "Banned"
},
"search_label": "Name or User ID",
"search_result_title": "Search result for user {{user_name}}",
"searching_for_user": "Searching for user {{user_name}}...",
"invite_to_room": "Invite to {{room}}",
"invite_to_dm": "Direct Message"
},
"InviteList": {
"accept_invite": "Accept",
"reject_invite": "Reject",
"direct_messages_title": "Direct Messages",
"rooms_title": "Rooms",
"spaces_title": "Spaces",
"title": "Invites"
},
"EmojiVerification": {
"waiting_for_response": "Waiting for response from other device...",
"confirmation_prompt": "Confirm the emoji below are displayed on both devices, in the same order:",
"emojis_match_button": "They match",
"emojis_dont_match_button": "They don't match",
"accept_request_from_other_device_message": "Please accept the request from other device.",
"begin_verification_process_message": "Click accept to start the verification process.",
"begin_verification_button_text": "Accept",
"title": "Emoji Verification"
},
"DragDrop": {
"drop_file_to_upload_prompt": "Drop file to upload"
},
"CreateRoom": {
"private_room_short": "Private",
"restricted_room_short": "Restricted",
"public_room_short": "Public",
"private_room_long": "Private (invite only)",
"restricted_room_long": "Restricted (space member can join)",
"public_room_long": "Public (anyone can join)",
"visibility_title": "Visibility",
"visibility_message": "Visibility (who can join)",
"select_who_can_join_space": "Select who can join this space",
"select_who_can_join_room": "Select who can join this room",
"space_address": "Space address",
"room_address": "Room address",
"room_address_already_in_use": "{{room_address}} is already in use",
"e2e_title": "Enable end-to-end encryption",
"e2e_message": "You can’t disable this later. Bridges & most bots won’t work yet.",
"role_title": "Select your role",
"role_message": "Selecting 'Admin' sets your power level to 100 whereas 'Founder' sets it to 101.",
"creating_room": "Creating room...",
"creating_space": "Creating space...",
"topic_label": "Topic (optional)",
"space_name": "Space name",
"room_name": "Room name",
"role_admin": "Admin",
"role_founder": "Founder",
"create_room": "Create room",
"create_space": "Create space",
"home": "Home"
}
},
"Molecules": {
"ConfirmDialog": {
"cancel": "Cancel"
},
"ReusableDialog": {
"close_tooltip": "Close"
},
"FollowingMembers": {
"users_following_1": "<bold><user_one/></bold> is following the conversation",
"users_following_2": "<bold><user_one/></bold> and <bold><user_two/></bold> are following the conversation",
"users_following_3": "<bold><user_one/></bold>, <bold><user_two/></bold>, and <bold><user_three/></bold> are following the conversation",
"users_following_other": "<bold><user_one/></bold>, <bold><user_two/></bold>, <bold><user_three/></bold> and {{other_count}} others are following the conversation"
},
"ImageUpload": {
"prompt": "Upload",
"cancel": "Cancel",
"remove": "Remove"
},
"ExportE2ERoomKeys": {
"getting_keys": "Getting keys...",
"encrypting_keys": "Encrypting Keys...",
"password_does_not_match": "Password does not match.",
"export_success": "Successfully exported all keys.",
"export_failed": "Failed to export keys. Please try again.",
"button_text": "Export"
},
"ImportE2ERoomKeys": {
"decrypting_file": "Decrypting file...",
"decrypting_messages": "Decrypting messages...",
"import_success": "Successfully imported all keys",
"import_failed": "Failed tp decrypt keys. Please try again",
"import_keys_button": "Import Keys",
"decrypt_button": "Decrypt"
},
"Media": {
"open_new_tab": "Open in new tab",
"download": "Download",
"play_audio": "Play audio",
"play_video": "Play video"
},
"Message": {
"message_deleted": "*** This message has been deleted ***",
"unable_to_load_reply": "*** Unable to load reply ***",
"unknown_user": "** Unknown user **",
"edited": "(edited)",
"edit_placeholder": "Edit message",
"user_reacted_1": "<bold><user_one/></bold> reacted with <emoji/>",
"user_reacted_2": "<bold><user_one/></bold> and <bold><user_two/></bold> reacted with <emoji/>",
"user_reacted_3": "<bold><user_one/></bold>, <bold><user_two/></bold> and <bold><user_three/></bold> reacted with <emoji/>",
"user_reacted_other": "<bold><user_one/></bold>, <bold><user_two/></bold>, <bold><user_three/></bold> and {{other_count}} others reacted with <emoji/>",
"add_reaction_tooltip": "Add reaction",
"reply_tooltip": "Reply",
"edit_tooltip": "Edit",
"options_header": "Options",
"options_tooltip": "Options",
"read_receipts": "Read receipts",
"view_source": "View source",
"delete_message_prompt": "Delete message",
"delete_message_confirmation": "Are you sure that you want to delete this message?",
"delete_message_button": "Delete"
},
"PopupWindow": {
"close_tooltip": "Back"
},
"PowerLevelSelector": {
"placeholder": "Power level"
},
"RoomAliases": {
"invalid_characters": "Invalid character: only letter, numbers and _- are allowed.",
"validating_alias": "validating {{alias}}...",
"alias_available": "{{alias}} is available.",
"alias_unavailable": "{{alias}} is unavailable.",
"deleting_alias": "Deleting...",
"set_main_alias": "Set as Main",
"publish_alias": "Publish",
"unpublish_alias": "Unpublish",
"delete_alias": "Delete",
"main_alias": "Main",
"publish_to_room_directory": {
"title": "Publish to room directory",
"publish_room_message": "Publish this room to the {{homeserver}} publish directory?",
"publish_space_message": "Publish this space to the {{homeserver}} publish directory?"
},
"published_addresses": {
"title": "Published addresses",
"none": "No published addresses",
"no_main_address": "No main address (select one from below)",
"message_room": "Published addresses can be used by anyone on any server to join your room. To publish an address, it needs to be set as a local address first.",
"message_space": "Published addresses can be used by anyone on any server to join your space. To publish an address, it needs to be set as a local address first."
},
"local_addresses": {
"title": "Local addresses",
"none": "No local addresses",
"message_room": "Set local addresses for this room so users can find this room through your homeserver.",
"message_space": "Set local addresses for this space so users can find this space through your homeserver.",
"add": "Add local address",
"add_button": "Add",
"placeholder_room": "my_room_address",
"placeholder_space": "my_space_address",
"hide": "Hide local addresses",
"view": "View local addresses"
}
},
"RoomEncryption": {
"encryption_public_room_message": "It is not recommended to add encryption in public room. Anyone can find and join public rooms, so anyone should be able to read messages in them.",
"encryption_message": "Once enabled, encryption for a room cannot be disabled. Messages sent in an encrypted room cannot be seen by the server, only by the participants of the room. Enabling encryption may prevent many bots and bridges from working correctly",
"encryption_cannot_be_disabled": "Once enabled, encryption cannot be disabled.",
"enable_room_encryption": "Enable room encryption",
"enable_encryption_prompt": "Enable Encryption",
"enable_encryption_button": "Enable",
"continue_button": "Continue"
},
"RoomHistoryVisibility": {
"world_readable": "Anyone (including guests)",
"shared": "Members (all messages)",
"invited": "Members (messages after invite)",
"joined": "Members (messages after join)",
"changes_only_affect_future": "Changes to history visibility will only apply to future messages. The visibility of existing history will have no effect."
},
"RoomMembers": {
"search_title": "Search member",
"found_members_one": "Found — one member",
"found_members_other": "Found — {{count}} members",
"no_results": "No results found for {{term}}",
"no_members": "No members to display",
"view_more": "View more",
"joined": "Joined",
"invited": "Invited",
"banned": "Banned",
"search_placeholder": "Search for name"
},
"RoomNotification": {
"default": "Global",
"all_messages": "All messages",
"mentions_and_keywords": "Mentions & Keywords",
"mute": "Mute"
},
"RoomOptions": {
"title": "Options for {{room_name}}",
"leave": {
"title": "Leave room",
"subtitle": "Are you sure you want to leave the {{room_name}} room?",
"button_text": "Leave"
},
"mark_as_read": "Mark as read",
"notifications_heading": "Notifications",
"invite": "Invite"
},
"RoomPermissions": {
"default_role": {
"name": "Default role",
"description": "Set default role for all members"
},
"send_messages": {
"name": "Send messages",
"description": "Set minimum power level to send messages in a room"
},
"reactions": {
"name": "Send reactions",
"description": "Set minimum power level to send reactions in a room"
},
"delete": {
"name": "Delete messages sent by others",
"description": "Set minumum power level to delete messages in a room"
},
"notifications": {
"name": "Ping room",
"description": "Set minimum power level to ping room"
},
"manage_rooms": {
"name": "Manage rooms in space",
"description": "Set minimum power level to manage rooms in space"
},
"invite": {
"name": "Invite",
"description": "Set minimum power level to invite members"
},
"kick": {
"name": "Kick",
"description": "Set minimum power level to kick members"
},
"ban": {
"name": "Ban",
"description": "Set minimum power level to ban members"
},
"change_avatar": {
"name": "Change avatar",
"description": "Set minimum power level to change room/space avatar"
},
"change_name": {
"name": "Change name",
"description": "Set minimum power evel to change room/space name"
},
"change_topic": {
"name": "Change topic",
"description": "Set minimum power level to change room/space topic"
},
"change_settings": {
"name": "Change settings",
"description": "Set minimum power level to change settings"
},
"change_published_address": {
"name": "Change published address",
"description": "Set minimum power level to publish and set main address"
},
"change_permissions": {
"name": "Change permissions",
"description": "Set minimum power level to change permissions"
},
"enable_room_encryption": {
"name": "Enable room encryption",
"description": "Set minimum power level to enable room encryption"
},
"change_history_visibility": {
"name": "Change history visibility",
"description": "Set minimum power level to change room message history visibility"
},
"upgrade_room": {
"name": "Upgrade room",
"description": "Set minimum power level to upgrade room"
},
"pin_messages": {
"name": "Pin messages",
"description": "Set minimum power level to pin messages in a room"
},
"change_acls": {
"name": "Change server ACLs",
"description": "Set minimum power level to change server ACLs"
},
"modify_widgets": {
"name": "Modify widgets",
"description": "Set minimum power level to modify room widgets"
},
"groups": {
"general": "General permissions",
"manage_members": "Manage members permissions",
"room": "Room profile permissions",
"space": "Space profile permissions",
"other": "Other permissions",
"settings": "Settings permissions"
}
},
"RoomProfile": {
"saving_room_name": "Saving room name...",
"saving_room_topic": "Saving room topic...",
"save_success": "Saved successfully",
"save_failed": "Unable to save",
"remove_avatar_title": "Remove avatar",
"remove_avatar_subtitle": "Are you sure that you want to remove room avatar?",
"remove_avatar_button": "Remove",
"permission_change_room_name": "You have permission to change room name only",
"permission_change_room_topic": "You have permission to change room topic only",
"permission_change_space_name": "You have permission to change space name only",
"permission_change_space_topic": "You have permission to change space topic only",
"name_label": "Name",
"topic_label": "Topic"
},
"RoomSearch": {
"title": "Room search",
"placeholder": "Search for keywords",
"search_button": "Search",
"searching": "Searching room messages...",
"subtitle": "Search room messages",
"failed": "Failed to search messages",
"no_results": "No results found",
"encrypted_room": "Search does not work in encrypted room",
"load_more": "Load more",
"results_one": "{{count}} result for {{term}}",
"results_other": "{{count}} results for {{term}}"
},
"RoomTile": {
"invited_by_user_zero": "Invited by {{inviter}} to {{id}}",
"invited_by_user_one": "Invited by {{inviter}} to {{id}} • {{member_count}} member",
"invited_by_user_other": "Invited by {{inviter}} to {{id}} • {{member_count}} members",
"invited_zero": "{{id}}",
"invited_one": "{{id}} • {{member_count}} member",
"invited_other": "{{id}} • {{member_count}} members"
},
"RoomVisibility": {
"private": "Private (invite only)",
"restricted": "Restricted (space members can join)",
"restricted_unsupported": "Restricted (Unsupported: room required upgrade)",
"public": "Public (anyone can join)"
},
"RoomEmojis": {
"header": "Create Pack",
"submit_button": "Create pack",
"name_placeholder": "Pack Name",
"no_packs": "No emoji or sticker packs."
},
"ImagePack": {
"rename_title": "Rename",
"rename_button": "Rename",
"shortcode_label": "Shortcode",
"delete_item_title": "Delete",
"delete_item_message": "Are you sure that you want to delete {{key}}?",
"delete_item_button": "Delete",
"delete_pack_title": "Delete Pack",
"delete_pack_message": "Are you sure that you want to delete {{pack_name}}?",
"delete_pack_button": "Delete",
"image_title": "Image",
"image_shortcode": "Shortcode",
"image_usage": "Usage",
"view_more": "View {{count}} more",
"view_less": "View less",
"use_globally": "Use globally",
"use_globally_description": "Add this pack to your account to use in all rooms.",
"no_global_packs": "No global packs",
"default_personal_pack_name": "Personal"
},
"ImagePackItem": {
"rename_tooltip": "Rename",
"delete_tooltip": "Delete"
},
"ImagePackUsageSelector": {
"header": "Usage",
"type_emoji": "Emoji",
"type_sticker": "Sticker",
"type_both": "Both"
},
"ImagePackUpload": {
"remove_file_tooltip": "Remove file",
"import_image_button": "Import image",
"shortcode_placeholder": "shortcode",
"upload_button": "Upload",
"upload_button_progress": "Uploading..."
},
"ImagePackProfile": {
"attribution_prompt": "Attribution",
"name_prompt": "Name",
"edit_tooltip": "Edit",
"usage_header": "Usage",
"pack_usage": "Pack usage"
},
"SpaceAddExisting": {
"adding_items_one": "Adding one item...",
"adding_items_other": "Adding {{count}} items...",
"items_selected_one": "{{count}} item selected",
"items_selected_other": "{{count}} items selected",
"search_rooms_placeholder": "Search rooms",
"no_results": "No results found",
"add_button": "Add",
"subtitle": "add existing rooms"
},
"SpaceOptions": {
"leave_space": "Leave Space",
"leave_space_confirmation": "Are you sure that you want to leave the {{space}} space?",
"leave_space_confirm": "Leave",
"invite": "Invite",
"manage_rooms": "Manage rooms",
"settings": "Settings",
"leave": "Leave"
},
"SSOButtons": {
"login_with": "Login with {{idp_name}}"
}
},
"Templates": {
"Auth": {
"loading_homeserver_list": "Loading homeserver list...",
"looking_for_homeserver": "Looking for homeserver...",
"connecting_to_homeserver": "Connecting to {{homeserver}}...",
"unable_to_connect": "Unable to connect. Please check your input",
"username_taken": "Username is already taken",
"registration_in_progress": "Registration in progress...",
"link_about": "About",
"link_twitter": "Twitter",
"link_matrix": "Powered by Matrix",
"dont_have_an_account": "Dont have an account?",
"already_have_an_account": "Already have an account?",
"register_link": "Register",
"login_link": "Login",
"redirecting": "Redirecting...",
"login_in_progress": "Login in progress...",
"bad_localpart_error": "Username can only contain characters a-z, 0-9, or '=_-./'",
"user_id_too_long_error": "Your user ID, including the hostname, can't be more than 255 characters long.",
"bad_password_error": "Password must contain at least 1 lowercase, 1 uppercase, 1 number, 1 non-alphanumeric character, 8-127 characters with no space.",
"confirm_password_error": "Passwords don't match.",
"bad_email_error": "Invalid email address",
"invalid_password": "Invalid password",
"check_credentials": "Please check your credentials",
"login_types": {
"username": "Username",
"email": "Email"
},
"homeserver_form": {
"title": "Homeserver",
"header": "Homeserver list"
},
"login_form": {
"title": "Login",
"prompt_email": "Email",
"prompt_username": "Username",
"prompt_password": "Password",
"login_button": "Login"
},
"register_form": {
"title": "Register",
"prompt_email_required": "Email (Required)",
"prompt_email_optional": "Email",
"prompt_username": "Username",
"prompt_password": "Password",
"prompt_confirm_password": "Confirm password",
"register_button": "Register"
},
"terms_and_conditions": {
"title": "Agree with terms",
"description": "In order to complete registration, you need to agree to the terms and conditions.",
"accept": "I accept <a>Terms and Conditions</a>",
"submit_button": "Submit"
},
"validate_email": {
"title": "Verify email",
"continue_button": "Continue",
"message": "Please check your email <bold>{{email_address}}</bold> and validate before continuing further"
},
"captcha": {
"message": "Pleace check the box below to proceed"
}
},
"Client": {
"loading_messages": {
"default": "Heating up",
"message_one": "Almost there...",
"message_two": "Looks like you have a lot of stuff to heat up!"
},
"logout_prompt": "Logout"
}
}
}
}
+59
View File
@@ -0,0 +1,59 @@
{
"name": "Cinny",
"short_name": "Cinny",
"description": "Yet another matrix client",
"dir": "auto",
"lang": "en-US",
"display": "standalone",
"orientation": "portrait",
"start_url": "/",
"background_color": "#fff",
"theme_color": "#fff",
"icons": [
{
"src": "/public/android/android-chrome-36x36.png",
"sizes": "36x36",
"type": "image/png"
},
{
"src": "/public/android/android-chrome-48x48.png",
"sizes": "48x48",
"type": "image/png"
},
{
"src": "/public/android/android-chrome-72x72.png",
"sizes": "72x72",
"type": "image/png"
},
{
"src": "/public/android/android-chrome-96x96.png",
"sizes": "96x96",
"type": "image/png"
},
{
"src": "/public/android/android-chrome-144x144.png",
"sizes": "144x144",
"type": "image/png"
},
{
"src": "/public/android/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/public/android/android-chrome-256x256.png",
"sizes": "256x256",
"type": "image/png"
},
{
"src": "/public/android/android-chrome-384x384.png",
"sizes": "384x384",
"type": "image/png"
},
{
"src": "/public/android/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}
+1 -1
View File
@@ -1,4 +1,4 @@
Graphics (c) by Ajay Bura (ajbura)
Copyright (c) 2021-present Ajay Bura (ajbura)
Graphic content is licensed under a
Creative Commons Attribution 4.0 International License.
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

+3 -11
View File
@@ -1,12 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve">
<g>
<polygon points="14,3 14,5 17.8,5 12.9,9.9 14.3,11.3 19,6.6 19,10.2 21,10.2 21,3 "/>
<path d="M3,10.2h2V5h5V3H5C3.9,3,3,3.9,3,5V10.2z"/>
<path d="M5,14.2H3V19c0,1.1,0.9,2,2,2h5v-2H5V14.2z"/>
<path d="M19,19h-5v2h5c1.1,0,2-0.9,2-2v-4.8h-2V19z"/>
</g>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14 3V5H17.8L12.9 9.9L14.3 11.3L19 6.6V10.2H21V3H14Z" fill="black"/>
<path d="M5 5H10V3H5C3.9 3 3 3.9 3 5V19C3 20.1 3.9 21 5 21H19C20.1 21 21 20.1 21 19V14.2H19V19H5V5Z" fill="black"/>
</svg>

Before

Width:  |  Height:  |  Size: 703 B

After

Width:  |  Height:  |  Size: 297 B

+4
View File
@@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.92896 3.51471L3.51474 4.92892L5.97515 7.38933C4.46742 8.5776 3.32116 9.93994 2.7 10.8C2.1 11.5 2.1 12.5 2.7 13.2C4 15 7.6 19 12 19C13.5709 19 15.0398 18.4902 16.3384 17.7526L19.0711 20.4853L20.4853 19.0711L4.92896 3.51471ZM4.2 12C4.68291 11.3561 5.85678 9.9637 7.39721 8.81139L9.29238 10.7066C9.10496 11.0982 9 11.5368 9 12C9 13.6569 10.3431 15 12 15C12.4632 15 12.9018 14.895 13.2934 14.7076L14.8573 16.2715C13.9566 16.7128 12.9896 17 12 17C8.4 17 5.1 13.2 4.2 12Z" fill="black"/>
<path d="M9.6226 5.37995L11.2906 7.04797C11.5254 7.01661 11.762 7 12 7C15.6 7 18.9 10.8 19.8 12C19.493 12.4094 18.9066 13.1213 18.1244 13.8817L19.5194 15.2768C20.2973 14.4974 20.9049 13.7471 21.3 13.2C21.9 12.5 21.9 11.5 21.3 10.8C20 9 16.4 5 12 5C11.1762 5 10.3805 5.14021 9.6226 5.37995Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 943 B

+3 -12
View File
@@ -1,13 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve">
<g>
<g>
<path d="M12,19c-4.4,0-8-4-9.3-5.8c-0.6-0.7-0.6-1.7,0-2.4C4,9,7.6,5,12,5s8,4,9.3,5.8c0.6,0.7,0.6,1.7,0,2.4C20,15,16.4,19,12,19
z M12,7c-3.6,0-6.9,3.8-7.8,5c0.9,1.2,4.2,5,7.8,5s6.9-3.8,7.8-5C18.9,10.8,15.6,7,12,7z"/>
</g>
<circle cx="12" cy="12" r="3"/>
</g>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 19C7.6 19 4 15 2.7 13.2C2.1 12.5 2.1 11.5 2.7 10.8C4 9 7.6 5 12 5C16.4 5 20 9 21.3 10.8C21.9 11.5 21.9 12.5 21.3 13.2C20 15 16.4 19 12 19ZM12 7C8.4 7 5.1 10.8 4.2 12C5.1 13.2 8.4 17 12 17C15.6 17 18.9 13.2 19.8 12C18.9 10.8 15.6 7 12 7Z" fill="black"/>
<path d="M12 15C13.6569 15 15 13.6569 15 12C15 10.3431 13.6569 9 12 9C10.3431 9 9 10.3431 9 12C9 13.6569 10.3431 15 12 15Z" fill="black"/>
</svg>

Before

Width:  |  Height:  |  Size: 718 B

After

Width:  |  Height:  |  Size: 508 B

+4
View File
@@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M16 3L21 8V19C21 20.1046 20.1046 21 19 21H5C3.89543 21 3 20.1046 3 19V5C3 3.89543 3.89543 3 5 3H16ZM19 9H17C15.8954 9 15 8.10457 15 7V5H5V19H19V9Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M9 12C9 13.6569 10.3431 15 12 15C13.6569 15 15 13.6569 15 12H17C17 14.7614 14.7614 17 12 17C9.23858 17 7 14.7614 7 12H9Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 501 B

+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5 8L10 13M4 14L10 8L12 5M2 5H14M7 2H8M12.913 17H20.087M12.913 17L11 21M12.913 17L15.7783 11.009C16.0092 10.5263 16.1246 10.2849 16.2826 10.2086C16.4199 10.1423 16.5801 10.1423 16.7174 10.2086C16.8754 10.2849 16.9908 10.5263 17.2217 11.009L20.087 17M20.087 17L22 21" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 586 B

+13
View File
@@ -0,0 +1,13 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_2707_1961)">
<path d="M10.5867 17.3522C10.0727 17.4492 9.54226 17.5 9 17.5C4.30558 17.5 0.5 13.6944 0.5 9C0.5 4.30558 4.30558 0.5 9 0.5C13.6944 0.5 17.5 4.30558 17.5 9C17.5 9.54226 17.4492 10.0727 17.3522 10.5867C16.6511 10.2123 15.8503 10 15 10C12.2386 10 10 12.2386 10 15C10 15.8503 10.2123 16.6511 10.5867 17.3522Z" fill="white"/>
<path d="M10 6.39999C10 6.67614 9.77614 6.89999 9.5 6.89999C9.22386 6.89999 9 6.67614 9 6.39999C9 6.12385 9.22386 5.89999 9.5 5.89999C9.77614 5.89999 10 6.12385 10 6.39999Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M9 0C4 0 0 4 0 9C0 14 4 18 9 18C9.63967 18 10.263 17.9345 10.8636 17.8099C10.3186 17.0091 10 16.0417 10 15C10 12.2386 12.2386 10 15 10C16.0417 10 17.0091 10.3186 17.8099 10.8636C17.9345 10.263 18 9.63967 18 9C18 4 14 0 9 0ZM1.2 10.8L4.7 8.5V8.2C4.7 6.4 6 5 7.8 4.8H8.2C9.4 4.8 10.5 5.4 11.1 6.4C11.4 6.3 11.7 6.3 12 6.3C12.4 6.3 12.8 6.3 13.2 6.4C13.9 6.6 14.6 6.9 15.2 7.3C14.6 7.1 14 7 13.3 7C12.1 7 11.1 7.4 10.4 8.4C9.7 9.3 9.3 10.4 9.3 11.6C9.3 13.1 8.9 14.5 8 15.8C7.93744 15.8834 7.87923 15.9625 7.82356 16.0381C7.6123 16.325 7.43739 16.5626 7.2 16.8C4.2 16.1 1.9 13.8 1.2 10.8Z" fill="black"/>
<path d="M18 15C18 16.6569 16.6569 18 15 18C13.3431 18 12 16.6569 12 15C12 13.3431 13.3431 12 15 12C16.6569 12 18 13.3431 18 15Z" fill="#45B83B"/>
</g>
<defs>
<clipPath id="clip0_2707_1961">
<rect width="18" height="18" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

+13
View File
@@ -0,0 +1,13 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_2707_2015)">
<path d="M10.5867 17.3522C10.0727 17.4492 9.54226 17.5 9 17.5C4.30558 17.5 0.5 13.6944 0.5 9C0.5 4.30558 4.30558 0.5 9 0.5C13.6944 0.5 17.5 4.30558 17.5 9C17.5 9.54226 17.4492 10.0727 17.3522 10.5867C16.6511 10.2123 15.8503 10 15 10C12.2386 10 10 12.2386 10 15C10 15.8503 10.2123 16.6511 10.5867 17.3522Z" fill="white"/>
<path d="M10 6.39999C10 6.67614 9.77614 6.89999 9.5 6.89999C9.22386 6.89999 9 6.67614 9 6.39999C9 6.12385 9.22386 5.89999 9.5 5.89999C9.77614 5.89999 10 6.12385 10 6.39999Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M9 0C4 0 0 4 0 9C0 14 4 18 9 18C9.63967 18 10.263 17.9345 10.8636 17.8099C10.3186 17.0091 10 16.0417 10 15C10 12.2386 12.2386 10 15 10C16.0417 10 17.0091 10.3186 17.8099 10.8636C17.9345 10.263 18 9.63967 18 9C18 4 14 0 9 0ZM1.2 10.8L4.7 8.5V8.2C4.7 6.4 6 5 7.8 4.8H8.2C9.4 4.8 10.5 5.4 11.1 6.4C11.4 6.3 11.7 6.3 12 6.3C12.4 6.3 12.8 6.3 13.2 6.4C13.9 6.6 14.6 6.9 15.2 7.3C14.6 7.1 14 7 13.3 7C12.1 7 11.1 7.4 10.4 8.4C9.7 9.3 9.3 10.4 9.3 11.6C9.3 13.1 8.9 14.5 8 15.8C7.93744 15.8834 7.87923 15.9625 7.82356 16.0381C7.6123 16.325 7.43739 16.5626 7.2 16.8C4.2 16.1 1.9 13.8 1.2 10.8Z" fill="black"/>
<path d="M18 15C18 16.6569 16.6569 18 15 18C13.3431 18 12 16.6569 12 15C12 13.3431 13.3431 12 15 12C16.6569 12 18 13.3431 18 15Z" fill="#989898"/>
</g>
<defs>
<clipPath id="clip0_2707_2015">
<rect width="18" height="18" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

+1 -5
View File
@@ -1,8 +1,4 @@
import { avatarInitials } from '../../../util/common';
function cssVar(name) {
return getComputedStyle(document.body).getPropertyValue(name);
}
import { avatarInitials, cssVar } from '../../../util/common';
// renders the avatar and returns it as an URL
export default async function renderAvatar({
+4 -4
View File
@@ -26,10 +26,10 @@
&--icon {
@include dir.side(padding, var(--sp-tight), var(--sp-loose));
.ic-raw {
@include dir.side(margin, 0, var(--sp-extra-tight));
flex-shrink: 0;
}
}
.ic-raw {
@include dir.side(margin, 0, var(--sp-extra-tight));
flex-shrink: 0;
}
}
+2
View File
@@ -16,6 +16,7 @@ function Input({
{ resizable
? (
<TextareaAutosize
dir="auto"
style={{ minHeight: `${minHeight}px` }}
name={name}
id={id}
@@ -34,6 +35,7 @@ function Input({
/>
) : (
<input
dir="auto"
ref={forwardRef}
id={id}
name={name}
+1 -1
View File
@@ -1,11 +1,11 @@
import React, { useEffect, useRef } from 'react';
import PropTypes from 'prop-types';
import './Math.scss';
import katex from 'katex';
import 'katex/dist/katex.min.css';
import 'katex/dist/contrib/copy-tex';
import 'katex/dist/contrib/copy-tex.css';
const Math = React.memo(({
content, throwOnError, errorColor, displayMode,
+3
View File
@@ -0,0 +1,3 @@
.katex-display {
margin: 0 !important;
}
-1
View File
@@ -42,7 +42,6 @@ function RawModal({
shouldCloseOnEsc={closeFromOutside}
shouldCloseOnOverlayClick={closeFromOutside}
shouldReturnFocusAfterClose={false}
closeTimeoutMS={300}
>
{children}
</Modal>
+29 -26
View File
@@ -1,33 +1,9 @@
.ReactModal__Overlay {
opacity: 0;
transition: opacity 200ms var(--fluid-slide-up);
}
.ReactModal__Overlay--after-open{
opacity: 1;
}
.ReactModal__Overlay--before-close{
opacity: 0;
}
.ReactModal__Content {
transform: translateY(100%);
transition: transform 200ms var(--fluid-slide-up);
}
.ReactModal__Content--after-open{
transform: translateY(0);
}
.ReactModal__Content--before-close{
transform: translateY(100%);
}
.raw-modal {
--small-modal-width: 525px;
--medium-modal-width: 712px;
--large-modal-width: 1024px;
position: relative;
width: 100%;
max-height: 100%;
border-radius: var(--bo-radius);
@@ -60,4 +36,31 @@
height: 100%;
background-color: var(--bg-overlay);
}
}
}
.ReactModal__Overlay {
animation: raw-modal--overlay 150ms;
}
.ReactModal__Content {
animation: raw-modal--content 150ms;
}
@keyframes raw-modal--content {
0% {
transform: translateY(100px);
opacity: .5;
}
100% {
transform: translateY(0);
opacity: 1;
}
}
@keyframes raw-modal--overlay {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
+5 -7
View File
@@ -2,20 +2,18 @@ import React from 'react';
import PropTypes from 'prop-types';
import './RawIcon.scss';
function RawIcon({
color, size, src, isImage,
}) {
function RawIcon({ color, size, src, isImage }) {
const style = {};
if (color !== null) style.backgroundColor = color;
if (isImage) {
style.backgroundColor = 'transparent';
style.backgroundImage = `url(${src})`;
style.backgroundImage = `url("${src}")`;
} else {
style.WebkitMaskImage = `url(${src})`;
style.maskImage = `url(${src})`;
style.WebkitMaskImage = `url("${src}")`;
style.maskImage = `url("${src}")`;
}
return <span className={`ic-raw ic-raw-${size}`} style={style}> </span>;
return <span className={`ic-raw ic-raw-${size}`} style={style} />;
}
RawIcon.defaultProps = {
+44
View File
@@ -0,0 +1,44 @@
import React from 'react';
import PropTypes from 'prop-types';
import dateFormat from 'dateformat';
import { isInSameDay } from '../../../util/common';
function Time({ timestamp, fullTime }) {
const date = new Date(timestamp);
const formattedFullTime = dateFormat(date, 'dd mmmm yyyy, hh:MM TT');
let formattedDate = formattedFullTime;
if (!fullTime) {
const compareDate = new Date();
const isToday = isInSameDay(date, compareDate);
compareDate.setDate(compareDate.getDate() - 1);
const isYesterday = isInSameDay(date, compareDate);
formattedDate = dateFormat(date, isToday || isYesterday ? 'hh:MM TT' : 'dd/mm/yyyy');
if (isYesterday) {
formattedDate = `Yesterday, ${formattedDate}`;
}
}
return (
<time
dateTime={date.toISOString()}
title={formattedFullTime}
>
{formattedDate}
</time>
);
}
Time.defaultProps = {
fullTime: false,
};
Time.propTypes = {
timestamp: PropTypes.number.isRequired,
fullTime: PropTypes.bool,
};
export default Time;
+22
View File
@@ -0,0 +1,22 @@
/* eslint-disable import/prefer-default-export */
import { useState, useEffect } from 'react';
import initMatrix from '../../client/initMatrix';
export function useAccountData(eventType) {
const mx = initMatrix.matrixClient;
const [event, setEvent] = useState(mx.getAccountData(eventType));
useEffect(() => {
const handleChange = (mEvent) => {
if (mEvent.getType() !== eventType) return;
setEvent(mEvent);
};
mx.on('accountData', handleChange);
return () => {
mx.removeListener('accountData', handleChange);
};
}, [eventType]);
return event;
}
+26
View File
@@ -0,0 +1,26 @@
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import Backend from 'i18next-http-backend'
i18n
.use(Backend)
// detect user language
// learn more: https://github.com/i18next/i18next-browser-languageDetector
.use(LanguageDetector)
// pass the i18n instance to react-i18next.
.use(initReactI18next)
// init i18next
// for all options read: https://www.i18next.com/overview/configuration-options
.init({
debug: true,
fallbackLng: 'en',
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
},
backend: {
loadPath: '/public/locales/{{lng}}/translation.json',
}
});
export default i18n;
@@ -0,0 +1,174 @@
import React from 'react';
import initMatrix from '../../../client/initMatrix';
import { openReusableContextMenu } from '../../../client/action/navigation';
import { getEventCords } from '../../../util/common';
import Text from '../../atoms/text/Text';
import Button from '../../atoms/button/Button';
import { MenuHeader } from '../../atoms/context-menu/ContextMenu';
import SettingTile from '../setting-tile/SettingTile';
import NotificationSelector from './NotificationSelector';
import ChevronBottomIC from '../../../../public/res/ic/outlined/chevron-bottom.svg';
import { useAccountData } from '../../hooks/useAccountData';
export const notifType = {
ON: 'on',
OFF: 'off',
NOISY: 'noisy',
};
export const typeToLabel = {
[notifType.ON]: 'On',
[notifType.OFF]: 'Off',
[notifType.NOISY]: 'Noisy',
};
Object.freeze(notifType);
const DM = '.m.rule.room_one_to_one';
const ENC_DM = '.m.rule.encrypted_room_one_to_one';
const ROOM = '.m.rule.message';
const ENC_ROOM = '.m.rule.encrypted';
export function getActionType(rule) {
const { actions } = rule;
if (actions.find((action) => action?.set_tweak === 'sound')) return notifType.NOISY;
if (actions.find((action) => action?.set_tweak === 'highlight')) return notifType.ON;
if (actions.find((action) => action === 'dont_notify')) return notifType.OFF;
return notifType.OFF;
}
export function getTypeActions(type, highlightValue = false) {
if (type === notifType.OFF) return ['dont_notify'];
const highlight = { set_tweak: 'highlight' };
if (typeof highlightValue === 'boolean') highlight.value = highlightValue;
if (type === notifType.ON) return ['notify', highlight];
const sound = { set_tweak: 'sound', value: 'default' };
return ['notify', sound, highlight];
}
function useGlobalNotif() {
const mx = initMatrix.matrixClient;
const pushRules = useAccountData('m.push_rules')?.getContent();
const underride = pushRules?.global?.underride ?? [];
const rulesToType = {
[DM]: notifType.ON,
[ENC_DM]: notifType.ON,
[ROOM]: notifType.NOISY,
[ENC_ROOM]: notifType.NOISY,
};
const getRuleCondition = (rule) => {
const condition = [];
if (rule === DM || rule === ENC_DM) {
condition.push({ kind: 'room_member_count', is: '2' });
}
condition.push({
kind: 'event_match',
key: 'type',
pattern: [ENC_DM, ENC_ROOM].includes(rule) ? 'm.room.encrypted' : 'm.room.message',
});
return condition;
};
const setRule = (rule, type) => {
const content = pushRules ?? {};
if (!content.global) content.global = {};
if (!content.global.underride) content.global.underride = [];
const ur = content.global.underride;
let ruleContent = ur.find((action) => action?.rule_id === rule);
if (!ruleContent) {
ruleContent = {
conditions: getRuleCondition(type),
actions: [],
rule_id: rule,
default: true,
enabled: true,
};
ur.push(ruleContent);
}
ruleContent.actions = getTypeActions(type);
mx.setAccountData('m.push_rules', content);
};
const dmRule = underride.find((rule) => rule.rule_id === DM);
const encDmRule = underride.find((rule) => rule.rule_id === ENC_DM);
const roomRule = underride.find((rule) => rule.rule_id === ROOM);
const encRoomRule = underride.find((rule) => rule.rule_id === ENC_ROOM);
if (dmRule) rulesToType[DM] = getActionType(dmRule);
if (encDmRule) rulesToType[ENC_DM] = getActionType(encDmRule);
if (roomRule) rulesToType[ROOM] = getActionType(roomRule);
if (encRoomRule) rulesToType[ENC_ROOM] = getActionType(encRoomRule);
return [rulesToType, setRule];
}
function GlobalNotification() {
const [rulesToType, setRule] = useGlobalNotif();
const onSelect = (evt, rule) => {
openReusableContextMenu(
'bottom',
getEventCords(evt, '.btn-surface'),
(requestClose) => (
<NotificationSelector
value={rulesToType[rule]}
onSelect={(value) => {
if (rulesToType[rule] !== value) setRule(rule, value);
requestClose();
}}
/>
),
);
};
return (
<div className="global-notification">
<MenuHeader>Global Notifications</MenuHeader>
<SettingTile
title="Direct messages"
options={(
<Button onClick={(evt) => onSelect(evt, DM)} iconSrc={ChevronBottomIC}>
{ typeToLabel[rulesToType[DM]] }
</Button>
)}
content={<Text variant="b3">Default notification settings for all direct message.</Text>}
/>
<SettingTile
title="Encrypted direct messages"
options={(
<Button onClick={(evt) => onSelect(evt, ENC_DM)} iconSrc={ChevronBottomIC}>
{typeToLabel[rulesToType[ENC_DM]]}
</Button>
)}
content={<Text variant="b3">Default notification settings for all encrypted direct message.</Text>}
/>
<SettingTile
title="Rooms messages"
options={(
<Button onClick={(evt) => onSelect(evt, ROOM)} iconSrc={ChevronBottomIC}>
{typeToLabel[rulesToType[ROOM]]}
</Button>
)}
content={<Text variant="b3">Default notification settings for all room message.</Text>}
/>
<SettingTile
title="Encrypted rooms messages"
options={(
<Button onClick={(evt) => onSelect(evt, ENC_ROOM)} iconSrc={ChevronBottomIC}>
{typeToLabel[rulesToType[ENC_ROOM]]}
</Button>
)}
content={<Text variant="b3">Default notification settings for all encrypted room message.</Text>}
/>
</div>
);
}
export default GlobalNotification;
@@ -0,0 +1,64 @@
import React from 'react';
import './IgnoreUserList.scss';
import initMatrix from '../../../client/initMatrix';
import * as roomActions from '../../../client/action/room';
import Text from '../../atoms/text/Text';
import Chip from '../../atoms/chip/Chip';
import Input from '../../atoms/input/Input';
import Button from '../../atoms/button/Button';
import { MenuHeader } from '../../atoms/context-menu/ContextMenu';
import SettingTile from '../setting-tile/SettingTile';
import CrossIC from '../../../../public/res/ic/outlined/cross.svg';
import { useAccountData } from '../../hooks/useAccountData';
function IgnoreUserList() {
useAccountData('m.ignored_user_list');
const ignoredUsers = initMatrix.matrixClient.getIgnoredUsers();
const handleSubmit = (evt) => {
evt.preventDefault();
const { ignoreInput } = evt.target.elements;
const value = ignoreInput.value.trim();
const userIds = value.split(' ').filter((v) => v.match(/^@\S+:\S+$/));
if (userIds.length === 0) return;
ignoreInput.value = '';
roomActions.ignore(userIds);
};
return (
<div className="ignore-user-list">
<MenuHeader>Ignored users</MenuHeader>
<SettingTile
title="Ignore user"
content={(
<div className="ignore-user-list__users">
<Text variant="b3">Ignore userId if you do not want to receive their messages or invites.</Text>
<form onSubmit={handleSubmit}>
<Input name="ignoreInput" required />
<Button variant="primary" type="submit">Ignore</Button>
</form>
{ignoredUsers.length > 0 && (
<div>
{ignoredUsers.map((uId) => (
<Chip
iconSrc={CrossIC}
key={uId}
text={uId}
iconColor={CrossIC}
onClick={() => roomActions.unignore([uId])}
/>
))}
</div>
)}
</div>
)}
/>
</div>
);
}
export default IgnoreUserList;
@@ -0,0 +1,17 @@
.ignore-user-list {
&__users {
& form,
& > div:last-child {
display: flex;
flex-wrap: wrap;
gap: var(--sp-tight);
}
& form {
margin: var(--sp-extra-tight) 0 var(--sp-normal);
.input-container {
flex-grow: 1;
}
}
}
}
@@ -0,0 +1,239 @@
import React from 'react';
import './KeywordNotification.scss';
import initMatrix from '../../../client/initMatrix';
import { openReusableContextMenu } from '../../../client/action/navigation';
import { getEventCords } from '../../../util/common';
import Text from '../../atoms/text/Text';
import Chip from '../../atoms/chip/Chip';
import Input from '../../atoms/input/Input';
import Button from '../../atoms/button/Button';
import { MenuHeader } from '../../atoms/context-menu/ContextMenu';
import SettingTile from '../setting-tile/SettingTile';
import NotificationSelector from './NotificationSelector';
import ChevronBottomIC from '../../../../public/res/ic/outlined/chevron-bottom.svg';
import CrossIC from '../../../../public/res/ic/outlined/cross.svg';
import { useAccountData } from '../../hooks/useAccountData';
import {
notifType, typeToLabel, getActionType, getTypeActions,
} from './GlobalNotification';
const DISPLAY_NAME = '.m.rule.contains_display_name';
const ROOM_PING = '.m.rule.roomnotif';
const USERNAME = '.m.rule.contains_user_name';
const KEYWORD = 'keyword';
function useKeywordNotif() {
const mx = initMatrix.matrixClient;
const pushRules = useAccountData('m.push_rules')?.getContent();
const override = pushRules?.global?.override ?? [];
const content = pushRules?.global?.content ?? [];
const rulesToType = {
[DISPLAY_NAME]: notifType.NOISY,
[ROOM_PING]: notifType.NOISY,
[USERNAME]: notifType.NOISY,
};
const setRule = (rule, type) => {
const evtContent = pushRules ?? {};
if (!evtContent.global) evtContent.global = {};
if (!evtContent.global.override) evtContent.global.override = [];
if (!evtContent.global.content) evtContent.global.content = [];
const or = evtContent.global.override;
const ct = evtContent.global.content;
if (rule === DISPLAY_NAME || rule === ROOM_PING) {
let orRule = or.find((r) => r?.rule_id === rule);
if (!orRule) {
orRule = {
conditions: [],
actions: [],
rule_id: rule,
default: true,
enabled: true,
};
or.push(orRule);
}
if (rule === DISPLAY_NAME) {
orRule.conditions = [{ kind: 'contains_display_name' }];
orRule.actions = getTypeActions(type, true);
} else {
orRule.conditions = [
{ kind: 'event_match', key: 'content.body', pattern: '@room' },
{ kind: 'sender_notification_permission', key: 'room' },
];
orRule.actions = getTypeActions(type, true);
}
} else if (rule === USERNAME) {
let usernameRule = ct.find((r) => r?.rule_id === rule);
if (!usernameRule) {
const userId = mx.getUserId();
const username = userId.match(/^@?(\S+):(\S+)$/)?.[1] ?? userId;
usernameRule = {
actions: [],
default: true,
enabled: true,
pattern: username,
rule_id: rule,
};
ct.push(usernameRule);
}
usernameRule.actions = getTypeActions(type, true);
} else {
const keyRules = ct.filter((r) => r.rule_id !== USERNAME);
keyRules.forEach((r) => {
// eslint-disable-next-line no-param-reassign
r.actions = getTypeActions(type, true);
});
}
mx.setAccountData('m.push_rules', evtContent);
};
const addKeyword = (keyword) => {
if (content.find((r) => r.rule_id === keyword)) return;
content.push({
rule_id: keyword,
pattern: keyword,
enabled: true,
default: false,
actions: getTypeActions(rulesToType[KEYWORD] ?? notifType.NOISY, true),
});
mx.setAccountData('m.push_rules', pushRules);
};
const removeKeyword = (rule) => {
pushRules.global.content = content.filter((r) => r.rule_id !== rule.rule_id);
mx.setAccountData('m.push_rules', pushRules);
};
const dsRule = override.find((rule) => rule.rule_id === DISPLAY_NAME);
const roomRule = override.find((rule) => rule.rule_id === ROOM_PING);
const usernameRule = content.find((rule) => rule.rule_id === USERNAME);
const keywordRule = content.find((rule) => rule.rule_id !== USERNAME);
if (dsRule) rulesToType[DISPLAY_NAME] = getActionType(dsRule);
if (roomRule) rulesToType[ROOM_PING] = getActionType(roomRule);
if (usernameRule) rulesToType[USERNAME] = getActionType(usernameRule);
if (keywordRule) rulesToType[KEYWORD] = getActionType(keywordRule);
return {
rulesToType,
pushRules,
setRule,
addKeyword,
removeKeyword,
};
}
function GlobalNotification() {
const {
rulesToType,
pushRules,
setRule,
addKeyword,
removeKeyword,
} = useKeywordNotif();
const keywordRules = pushRules?.global?.content.filter((r) => r.rule_id !== USERNAME) ?? [];
const onSelect = (evt, rule) => {
openReusableContextMenu(
'bottom',
getEventCords(evt, '.btn-surface'),
(requestClose) => (
<NotificationSelector
value={rulesToType[rule]}
onSelect={(value) => {
if (rulesToType[rule] !== value) setRule(rule, value);
requestClose();
}}
/>
),
);
};
const handleSubmit = (evt) => {
evt.preventDefault();
const { keywordInput } = evt.target.elements;
const value = keywordInput.value.trim();
if (value === '') return;
addKeyword(value);
keywordInput.value = '';
};
return (
<div className="keyword-notification">
<MenuHeader>Mentions & keywords</MenuHeader>
<SettingTile
title="Message containing my display name"
options={(
<Button onClick={(evt) => onSelect(evt, DISPLAY_NAME)} iconSrc={ChevronBottomIC}>
{ typeToLabel[rulesToType[DISPLAY_NAME]] }
</Button>
)}
content={<Text variant="b3">Default notification settings for all message containing your display name.</Text>}
/>
<SettingTile
title="Message containing my username"
options={(
<Button onClick={(evt) => onSelect(evt, USERNAME)} iconSrc={ChevronBottomIC}>
{ typeToLabel[rulesToType[USERNAME]] }
</Button>
)}
content={<Text variant="b3">Default notification settings for all message containing your username.</Text>}
/>
<SettingTile
title="Message containing @room"
options={(
<Button onClick={(evt) => onSelect(evt, ROOM_PING)} iconSrc={ChevronBottomIC}>
{typeToLabel[rulesToType[ROOM_PING]]}
</Button>
)}
content={<Text variant="b3">Default notification settings for all messages containing @room.</Text>}
/>
{ rulesToType[KEYWORD] && (
<SettingTile
title="Message containing keywords"
options={(
<Button onClick={(evt) => onSelect(evt, KEYWORD)} iconSrc={ChevronBottomIC}>
{typeToLabel[rulesToType[KEYWORD]]}
</Button>
)}
content={<Text variant="b3">Default notification settings for all message containing keywords.</Text>}
/>
)}
<SettingTile
title="Keywords"
content={(
<div className="keyword-notification__keyword">
<Text variant="b3">Get notification when a message contains keyword.</Text>
<form onSubmit={handleSubmit}>
<Input name="keywordInput" required />
<Button variant="primary" type="submit">Add</Button>
</form>
{keywordRules.length > 0 && (
<div>
{keywordRules.map((rule) => (
<Chip
iconSrc={CrossIC}
key={rule.rule_id}
text={rule.pattern}
iconColor={CrossIC}
onClick={() => removeKeyword(rule)}
/>
))}
</div>
)}
</div>
)}
/>
</div>
);
}
export default GlobalNotification;
@@ -0,0 +1,17 @@
.keyword-notification {
&__keyword {
& form,
& > div:last-child {
display: flex;
flex-wrap: wrap;
gap: var(--sp-tight);
}
& form {
margin: var(--sp-extra-tight) 0 var(--sp-normal);
.input-container {
flex-grow: 1;
}
}
}
}
@@ -0,0 +1,26 @@
import React from 'react';
import PropTypes from 'prop-types';
import { MenuHeader, MenuItem } from '../../atoms/context-menu/ContextMenu';
import CheckIC from '../../../../public/res/ic/outlined/check.svg';
function NotificationSelector({
value, onSelect,
}) {
return (
<div>
<MenuHeader>Notification</MenuHeader>
<MenuItem iconSrc={value === 'off' ? CheckIC : null} variant={value === 'off' ? 'positive' : 'surface'} onClick={() => onSelect('off')}>Off</MenuItem>
<MenuItem iconSrc={value === 'on' ? CheckIC : null} variant={value === 'on' ? 'positive' : 'surface'} onClick={() => onSelect('on')}>On</MenuItem>
<MenuItem iconSrc={value === 'noisy' ? CheckIC : null} variant={value === 'noisy' ? 'positive' : 'surface'} onClick={() => onSelect('noisy')}>Noisy</MenuItem>
</div>
);
}
NotificationSelector.propTypes = {
value: PropTypes.oneOf(['off', 'on', 'noisy']).isRequired,
onSelect: PropTypes.func.isRequired,
};
export default NotificationSelector;
@@ -0,0 +1,47 @@
import React from 'react';
import PropTypes from 'prop-types';
import './ImageLightbox.scss';
import FileSaver from 'file-saver';
import Text from '../../atoms/text/Text';
import RawModal from '../../atoms/modal/RawModal';
import IconButton from '../../atoms/button/IconButton';
import DownloadSVG from '../../../../public/res/ic/outlined/download.svg';
import ExternalSVG from '../../../../public/res/ic/outlined/external.svg';
function ImageLightbox({
url, alt, isOpen, onRequestClose,
}) {
const handleDownload = () => {
FileSaver.saveAs(url, alt);
};
return (
<RawModal
className="image-lightbox__modal"
overlayClassName="image-lightbox__overlay"
isOpen={isOpen}
onRequestClose={onRequestClose}
size="large"
>
<div className="image-lightbox__header">
<Text variant="b2" weight="medium">{alt}</Text>
<IconButton onClick={() => window.open(url)} size="small" src={ExternalSVG} />
<IconButton onClick={handleDownload} size="small" src={DownloadSVG} />
</div>
<div className="image-lightbox__content">
<img src={url} alt={alt} />
</div>
</RawModal>
);
}
ImageLightbox.propTypes = {
url: PropTypes.string.isRequired,
alt: PropTypes.string.isRequired,
isOpen: PropTypes.bool.isRequired,
onRequestClose: PropTypes.func.isRequired,
};
export default ImageLightbox;
@@ -0,0 +1,50 @@
@use '../../partials/flex';
@use '../../partials/text';
.image-lightbox__modal {
box-shadow: none;
width: unset;
gap: var(--sp-normal);
border-radius: 0;
pointer-events: none;
& .text {
color: white;
}
& .ic-raw {
background-color: white;
}
}
.image-lightbox__overlay {
background-color: var(--bg-overlay-low);
}
.image-lightbox__header > *,
.image-lightbox__content > * {
pointer-events: all;
}
.image-lightbox__header {
display: flex;
align-items: center;
& > .text {
@extend .cp-fx__item-one;
@extend .cp-txt__ellipsis;
}
}
.image-lightbox__content {
display: flex;
justify-content: center;
max-height: 80vh;
& img {
background-color: var(--bg-surface-low);
object-fit: contain;
max-width: 100%;
max-height: 100%;
border-radius: var(--bo-radius);
}
}
+469
View File
@@ -0,0 +1,469 @@
import React, {
useState, useMemo, useReducer, useEffect,
} from 'react';
import PropTypes from 'prop-types';
import './ImagePack.scss';
import initMatrix from '../../../client/initMatrix';
import { openReusableDialog } from '../../../client/action/navigation';
import { suffixRename } from '../../../util/common';
import Button from '../../atoms/button/Button';
import Text from '../../atoms/text/Text';
import Input from '../../atoms/input/Input';
import Checkbox from '../../atoms/button/Checkbox';
import { MenuHeader } from '../../atoms/context-menu/ContextMenu';
import { ImagePack as ImagePackBuilder } from '../../organisms/emoji-board/custom-emoji';
import { confirmDialog } from '../confirm-dialog/ConfirmDialog';
import ImagePackProfile from './ImagePackProfile';
import ImagePackItem from './ImagePackItem';
import ImagePackUpload from './ImagePackUpload';
const renameImagePackItem = (shortcode) => new Promise((resolve) => {
let isCompleted = false;
openReusableDialog(
<Text variant="s1" weight="medium">Rename</Text>,
(requestClose) => (
<div style={{ padding: 'var(--sp-normal)' }}>
<form
onSubmit={(e) => {
e.preventDefault();
const sc = e.target.shortcode.value;
if (sc.trim() === '') return;
isCompleted = true;
resolve(sc.trim());
requestClose();
}}
>
<Input
value={shortcode}
name="shortcode"
label="Shortcode"
autoFocus
required
/>
<div style={{ height: 'var(--sp-normal)' }} />
<Button variant="primary" type="submit">Rename</Button>
</form>
</div>
),
() => {
if (!isCompleted) resolve(null);
},
);
});
function getUsage(usage) {
if (usage.includes('emoticon') && usage.includes('sticker')) return 'both';
if (usage.includes('emoticon')) return 'emoticon';
if (usage.includes('sticker')) return 'sticker';
return 'both';
}
function isGlobalPack(roomId, stateKey) {
const mx = initMatrix.matrixClient;
const globalContent = mx.getAccountData('im.ponies.emote_rooms')?.getContent();
if (typeof globalContent !== 'object') return false;
const { rooms } = globalContent;
if (typeof rooms !== 'object') return false;
return rooms[roomId]?.[stateKey] !== undefined;
}
function useRoomImagePack(roomId, stateKey) {
const mx = initMatrix.matrixClient;
const room = mx.getRoom(roomId);
const packEvent = room.currentState.getStateEvents('im.ponies.room_emotes', stateKey);
const pack = useMemo(() => (
ImagePackBuilder.parsePack(packEvent.getId(), packEvent.getContent())
), [room, stateKey]);
const sendPackContent = (content) => {
mx.sendStateEvent(roomId, 'im.ponies.room_emotes', content, stateKey);
};
return {
pack,
sendPackContent,
};
}
function useUserImagePack() {
const mx = initMatrix.matrixClient;
const packEvent = mx.getAccountData('im.ponies.user_emotes');
const pack = useMemo(() => (
ImagePackBuilder.parsePack(mx.getUserId(), packEvent?.getContent() ?? {
pack: { display_name: 'Personal' },
images: {},
})
), []);
const sendPackContent = (content) => {
mx.setAccountData('im.ponies.user_emotes', content);
};
return {
pack,
sendPackContent,
};
}
function useImagePackHandles(pack, sendPackContent) {
const [, forceUpdate] = useReducer((count) => count + 1, 0);
const getNewKey = (key) => {
if (typeof key !== 'string') return undefined;
let newKey = key?.replace(/\s/g, '_');
if (pack.getImages().get(newKey)) {
newKey = suffixRename(
newKey,
(suffixedKey) => pack.getImages().get(suffixedKey),
);
}
return newKey;
};
const handleAvatarChange = (url) => {
pack.setAvatarUrl(url);
sendPackContent(pack.getContent());
forceUpdate();
};
const handleEditProfile = (name, attribution) => {
pack.setDisplayName(name);
pack.setAttribution(attribution);
sendPackContent(pack.getContent());
forceUpdate();
};
const handleUsageChange = (newUsage) => {
const usage = [];
if (newUsage === 'emoticon' || newUsage === 'both') usage.push('emoticon');
if (newUsage === 'sticker' || newUsage === 'both') usage.push('sticker');
pack.setUsage(usage);
pack.getImages().forEach((img) => pack.setImageUsage(img.shortcode, undefined));
sendPackContent(pack.getContent());
forceUpdate();
};
const handleRenameItem = async (key) => {
const newKey = getNewKey(await renameImagePackItem(key));
if (!newKey || newKey === key) return;
pack.updateImageKey(key, newKey);
sendPackContent(pack.getContent());
forceUpdate();
};
const handleDeleteItem = async (key) => {
const isConfirmed = await confirmDialog(
'Delete',
`Are you sure that you want to delete "${key}"?`,
'Delete',
'danger',
);
if (!isConfirmed) return;
pack.removeImage(key);
sendPackContent(pack.getContent());
forceUpdate();
};
const handleUsageItem = (key, newUsage) => {
const usage = [];
if (newUsage === 'emoticon' || newUsage === 'both') usage.push('emoticon');
if (newUsage === 'sticker' || newUsage === 'both') usage.push('sticker');
pack.setImageUsage(key, usage);
sendPackContent(pack.getContent());
forceUpdate();
};
const handleAddItem = (key, url) => {
const newKey = getNewKey(key);
if (!newKey || !url) return;
pack.addImage(newKey, {
url,
});
sendPackContent(pack.getContent());
forceUpdate();
};
return {
handleAvatarChange,
handleEditProfile,
handleUsageChange,
handleRenameItem,
handleDeleteItem,
handleUsageItem,
handleAddItem,
};
}
function addGlobalImagePack(mx, roomId, stateKey) {
const content = mx.getAccountData('im.ponies.emote_rooms')?.getContent() ?? {};
if (!content.rooms) content.rooms = {};
if (!content.rooms[roomId]) content.rooms[roomId] = {};
content.rooms[roomId][stateKey] = {};
return mx.setAccountData('im.ponies.emote_rooms', content);
}
function removeGlobalImagePack(mx, roomId, stateKey) {
const content = mx.getAccountData('im.ponies.emote_rooms')?.getContent() ?? {};
if (!content.rooms) return Promise.resolve();
if (!content.rooms[roomId]) return Promise.resolve();
delete content.rooms[roomId][stateKey];
if (Object.keys(content.rooms[roomId]).length === 0) {
delete content.rooms[roomId];
}
return mx.setAccountData('im.ponies.emote_rooms', content);
}
function ImagePack({ roomId, stateKey, handlePackDelete }) {
const mx = initMatrix.matrixClient;
const room = mx.getRoom(roomId);
const [viewMore, setViewMore] = useState(false);
const [isGlobal, setIsGlobal] = useState(isGlobalPack(roomId, stateKey));
const { pack, sendPackContent } = useRoomImagePack(roomId, stateKey);
const {
handleAvatarChange,
handleEditProfile,
handleUsageChange,
handleRenameItem,
handleDeleteItem,
handleUsageItem,
handleAddItem,
} = useImagePackHandles(pack, sendPackContent);
const handleGlobalChange = (isG) => {
setIsGlobal(isG);
if (isG) addGlobalImagePack(mx, roomId, stateKey);
else removeGlobalImagePack(mx, roomId, stateKey);
};
const myPowerlevel = room.getMember(mx.getUserId())?.powerLevel || 0;
const canChange = room.currentState.hasSufficientPowerLevelFor('state_default', myPowerlevel);
const handleDeletePack = async () => {
const isConfirmed = await confirmDialog(
'Delete Pack',
`Are you sure that you want to delete "${pack.displayName}"?`,
'Delete',
'danger',
);
if (!isConfirmed) return;
handlePackDelete(stateKey);
};
const images = [...pack.images].slice(0, viewMore ? pack.images.size : 2);
return (
<div className="image-pack">
<ImagePackProfile
avatarUrl={pack.avatarUrl ? mx.mxcUrlToHttp(pack.avatarUrl, 42, 42, 'crop') : null}
displayName={pack.displayName ?? 'Unknown'}
attribution={pack.attribution}
usage={getUsage(pack.usage)}
onUsageChange={canChange ? handleUsageChange : null}
onAvatarChange={canChange ? handleAvatarChange : null}
onEditProfile={canChange ? handleEditProfile : null}
/>
{ canChange && (
<ImagePackUpload onUpload={handleAddItem} />
)}
{ images.length === 0 ? null : (
<div>
<div className="image-pack__header">
<Text variant="b3">Image</Text>
<Text variant="b3">Shortcode</Text>
<Text variant="b3">Usage</Text>
</div>
{images.map(([shortcode, image]) => (
<ImagePackItem
key={shortcode}
url={mx.mxcUrlToHttp(image.mxc)}
shortcode={shortcode}
usage={getUsage(image.usage)}
onUsageChange={canChange ? handleUsageItem : undefined}
onDelete={canChange ? handleDeleteItem : undefined}
onRename={canChange ? handleRenameItem : undefined}
/>
))}
</div>
)}
{(pack.images.size > 2 || handlePackDelete) && (
<div className="image-pack__footer">
{pack.images.size > 2 && (
<Button onClick={() => setViewMore(!viewMore)}>
{
viewMore
? 'View less'
: `View ${pack.images.size - 2} more`
}
</Button>
)}
{ handlePackDelete && <Button variant="danger" onClick={handleDeletePack}>Delete Pack</Button>}
</div>
)}
<div className="image-pack__global">
<Checkbox variant="positive" onToggle={handleGlobalChange} isActive={isGlobal} />
<div>
<Text variant="b2">Use globally</Text>
<Text variant="b3">Add this pack to your account to use in all rooms.</Text>
</div>
</div>
</div>
);
}
ImagePack.defaultProps = {
handlePackDelete: null,
};
ImagePack.propTypes = {
roomId: PropTypes.string.isRequired,
stateKey: PropTypes.string.isRequired,
handlePackDelete: PropTypes.func,
};
function ImagePackUser() {
const mx = initMatrix.matrixClient;
const [viewMore, setViewMore] = useState(false);
const { pack, sendPackContent } = useUserImagePack();
const {
handleAvatarChange,
handleEditProfile,
handleUsageChange,
handleRenameItem,
handleDeleteItem,
handleUsageItem,
handleAddItem,
} = useImagePackHandles(pack, sendPackContent);
const images = [...pack.images].slice(0, viewMore ? pack.images.size : 2);
return (
<div className="image-pack">
<ImagePackProfile
avatarUrl={pack.avatarUrl ? mx.mxcUrlToHttp(pack.avatarUrl, 42, 42, 'crop') : null}
displayName={pack.displayName ?? 'Personal'}
attribution={pack.attribution}
usage={getUsage(pack.usage)}
onUsageChange={handleUsageChange}
onAvatarChange={handleAvatarChange}
onEditProfile={handleEditProfile}
/>
<ImagePackUpload onUpload={handleAddItem} />
{ images.length === 0 ? null : (
<div>
<div className="image-pack__header">
<Text variant="b3">Image</Text>
<Text variant="b3">Shortcode</Text>
<Text variant="b3">Usage</Text>
</div>
{images.map(([shortcode, image]) => (
<ImagePackItem
key={shortcode}
url={mx.mxcUrlToHttp(image.mxc)}
shortcode={shortcode}
usage={getUsage(image.usage)}
onUsageChange={handleUsageItem}
onDelete={handleDeleteItem}
onRename={handleRenameItem}
/>
))}
</div>
)}
{(pack.images.size > 2) && (
<div className="image-pack__footer">
<Button onClick={() => setViewMore(!viewMore)}>
{
viewMore
? 'View less'
: `View ${pack.images.size - 2} more`
}
</Button>
</div>
)}
</div>
);
}
function useGlobalImagePack() {
const [, forceUpdate] = useReducer((count) => count + 1, 0);
const mx = initMatrix.matrixClient;
const roomIdToStateKeys = new Map();
const globalContent = mx.getAccountData('im.ponies.emote_rooms')?.getContent() ?? { rooms: {} };
const { rooms } = globalContent;
Object.keys(rooms).forEach((roomId) => {
if (typeof rooms[roomId] !== 'object') return;
const room = mx.getRoom(roomId);
const stateKeys = Object.keys(rooms[roomId]);
if (!room || stateKeys.length === 0) return;
roomIdToStateKeys.set(roomId, stateKeys);
});
useEffect(() => {
const handleEvent = (event) => {
if (event.getType() === 'im.ponies.emote_rooms') forceUpdate();
};
mx.addListener('accountData', handleEvent);
return () => {
mx.removeListener('accountData', handleEvent);
};
}, []);
return roomIdToStateKeys;
}
function ImagePackGlobal() {
const mx = initMatrix.matrixClient;
const roomIdToStateKeys = useGlobalImagePack();
const handleChange = (roomId, stateKey) => {
removeGlobalImagePack(mx, roomId, stateKey);
};
return (
<div className="image-pack-global">
<MenuHeader>Global packs</MenuHeader>
<div>
{
roomIdToStateKeys.size > 0
? [...roomIdToStateKeys].map(([roomId, stateKeys]) => {
const room = mx.getRoom(roomId);
return (
stateKeys.map((stateKey) => {
const data = room.currentState.getStateEvents('im.ponies.room_emotes', stateKey);
const pack = ImagePackBuilder.parsePack(data?.getId(), data?.getContent());
if (!pack) return null;
return (
<div className="image-pack__global" key={pack.id}>
<Checkbox variant="positive" onToggle={() => handleChange(roomId, stateKey)} isActive />
<div>
<Text variant="b2">{pack.displayName ?? 'Unknown'}</Text>
<Text variant="b3">{room.name}</Text>
</div>
</div>
);
})
);
})
: <div className="image-pack-global__empty"><Text>No global packs</Text></div>
}
</div>
</div>
);
}
export default ImagePack;
export { ImagePackUser, ImagePackGlobal };
@@ -0,0 +1,47 @@
@use '../../partials/flex';
.image-pack {
&-item {
border-top: 1px solid var(--bg-surface-border);
}
&__header {
padding: var(--sp-extra-tight) var(--sp-normal);
display: flex;
align-items: center;
gap: var(--sp-normal);
& > *:nth-child(2) {
@extend .cp-fx__item-one;
}
}
&__footer {
padding: var(--sp-normal);
display: flex;
justify-content: space-between;
gap: var(--sp-tight);
}
&__global {
padding: var(--sp-normal);
padding-top: var(--sp-tight);
display: flex;
align-items: center;
gap: var(--sp-normal);
}
}
.image-pack-global {
&__empty {
text-align: center;
padding: var(--sp-extra-loose) var(--sp-normal);
}
& .image-pack__global {
padding: 0 var(--sp-normal);
padding-bottom: var(--sp-normal);
&:first-child {
padding-top: var(--sp-normal);
}
}
}
@@ -0,0 +1,76 @@
import React from 'react';
import PropTypes from 'prop-types';
import './ImagePackItem.scss';
import { openReusableContextMenu } from '../../../client/action/navigation';
import { getEventCords } from '../../../util/common';
import Avatar from '../../atoms/avatar/Avatar';
import Text from '../../atoms/text/Text';
import Button from '../../atoms/button/Button';
import RawIcon from '../../atoms/system-icons/RawIcon';
import IconButton from '../../atoms/button/IconButton';
import ImagePackUsageSelector from './ImagePackUsageSelector';
import ChevronBottomIC from '../../../../public/res/ic/outlined/chevron-bottom.svg';
import PencilIC from '../../../../public/res/ic/outlined/pencil.svg';
import BinIC from '../../../../public/res/ic/outlined/bin.svg';
function ImagePackItem({
url, shortcode, usage, onUsageChange, onDelete, onRename,
}) {
const handleUsageSelect = (event) => {
openReusableContextMenu(
'bottom',
getEventCords(event, '.btn-surface'),
(closeMenu) => (
<ImagePackUsageSelector
usage={usage}
onSelect={(newUsage) => {
onUsageChange(shortcode, newUsage);
closeMenu();
}}
/>
),
);
};
return (
<div className="image-pack-item">
<Avatar imageSrc={url} size="extra-small" text={shortcode} bgColor="black" />
<div className="image-pack-item__content">
<Text>{shortcode}</Text>
</div>
<div className="image-pack-item__usage">
<div className="image-pack-item__btn">
{onRename && <IconButton tooltip="Rename" size="extra-small" src={PencilIC} onClick={() => onRename(shortcode)} />}
{onDelete && <IconButton tooltip="Delete" size="extra-small" src={BinIC} onClick={() => onDelete(shortcode)} />}
</div>
<Button onClick={onUsageChange ? handleUsageSelect : undefined}>
{onUsageChange && <RawIcon src={ChevronBottomIC} size="extra-small" />}
<Text variant="b2">
{usage === 'emoticon' && 'Emoji'}
{usage === 'sticker' && 'Sticker'}
{usage === 'both' && 'Both'}
</Text>
</Button>
</div>
</div>
);
}
ImagePackItem.defaultProps = {
onUsageChange: null,
onDelete: null,
onRename: null,
};
ImagePackItem.propTypes = {
url: PropTypes.string.isRequired,
shortcode: PropTypes.string.isRequired,
usage: PropTypes.oneOf(['emoticon', 'sticker', 'both']).isRequired,
onUsageChange: PropTypes.func,
onDelete: PropTypes.func,
onRename: PropTypes.func,
};
export default ImagePackItem;
@@ -0,0 +1,43 @@
@use '../../partials/flex';
@use '../../partials/dir';
.image-pack-item {
margin: 0 var(--sp-normal);
padding: var(--sp-tight) 0;
display: flex;
align-items: center;
gap: var(--sp-normal);
& .avatar-container img {
object-fit: contain;
border-radius: 0;
}
&__content {
@extend .cp-fx__item-one;
}
&__usage {
display: flex;
gap: var(--sp-ultra-tight);
& button {
padding: 6px;
}
& > button.btn-surface {
padding: 6px var(--sp-tight);
min-width: 0;
@include dir.side(margin, var(--sp-ultra-tight), 0);
}
}
&__btn {
display: none;
}
&:hover,
&:focus-within {
.image-pack-item__btn {
display: flex;
gap: var(--sp-ultra-tight);
}
}
}
@@ -0,0 +1,125 @@
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import './ImagePackProfile.scss';
import { openReusableContextMenu } from '../../../client/action/navigation';
import { getEventCords } from '../../../util/common';
import Text from '../../atoms/text/Text';
import Avatar from '../../atoms/avatar/Avatar';
import Button from '../../atoms/button/Button';
import IconButton from '../../atoms/button/IconButton';
import Input from '../../atoms/input/Input';
import ImageUpload from '../image-upload/ImageUpload';
import ImagePackUsageSelector from './ImagePackUsageSelector';
import ChevronBottomIC from '../../../../public/res/ic/outlined/chevron-bottom.svg';
import PencilIC from '../../../../public/res/ic/outlined/pencil.svg';
function ImagePackProfile({
avatarUrl, displayName, attribution, usage,
onUsageChange, onAvatarChange, onEditProfile,
}) {
const [isEdit, setIsEdit] = useState(false);
const handleSubmit = (e) => {
e.preventDefault();
const { nameInput, attributionInput } = e.target;
const name = nameInput.value.trim() || undefined;
const att = attributionInput.value.trim() || undefined;
onEditProfile(name, att);
setIsEdit(false);
};
const handleUsageSelect = (event) => {
openReusableContextMenu(
'bottom',
getEventCords(event, '.btn-surface'),
(closeMenu) => (
<ImagePackUsageSelector
usage={usage}
onSelect={(newUsage) => {
onUsageChange(newUsage);
closeMenu();
}}
/>
),
);
};
return (
<div className="image-pack-profile">
{
onAvatarChange
? (
<ImageUpload
bgColor="#555"
text={displayName}
imageSrc={avatarUrl}
size="normal"
onUpload={onAvatarChange}
onRequestRemove={() => onAvatarChange(undefined)}
/>
)
: <Avatar bgColor="#555" text={displayName} imageSrc={avatarUrl} size="normal" />
}
<div className="image-pack-profile__content">
{
isEdit
? (
<form onSubmit={handleSubmit}>
<Input name="nameInput" label="Name" value={displayName} required />
<Input name="attributionInput" label="Attribution" value={attribution} resizable />
<div>
<Button variant="primary" type="submit">Save</Button>
<Button onClick={() => setIsEdit(false)}>Cancel</Button>
</div>
</form>
) : (
<>
<div>
<Text>{displayName}</Text>
{onEditProfile && <IconButton size="extra-small" onClick={() => setIsEdit(true)} src={PencilIC} tooltip="Edit" />}
</div>
{attribution && <Text variant="b3">{attribution}</Text>}
</>
)
}
</div>
<div className="image-pack-profile__usage">
<Text variant="b3">Pack usage</Text>
<Button
onClick={onUsageChange ? handleUsageSelect : undefined}
iconSrc={onUsageChange ? ChevronBottomIC : null}
>
<Text>
{usage === 'emoticon' && 'Emoji'}
{usage === 'sticker' && 'Sticker'}
{usage === 'both' && 'Both'}
</Text>
</Button>
</div>
</div>
);
}
ImagePackProfile.defaultProps = {
avatarUrl: null,
attribution: null,
onUsageChange: null,
onAvatarChange: null,
onEditProfile: null,
};
ImagePackProfile.propTypes = {
avatarUrl: PropTypes.string,
displayName: PropTypes.string.isRequired,
attribution: PropTypes.string,
usage: PropTypes.oneOf(['emoticon', 'sticker', 'both']).isRequired,
onUsageChange: PropTypes.func,
onAvatarChange: PropTypes.func,
onEditProfile: PropTypes.func,
};
export default ImagePackProfile;
@@ -0,0 +1,37 @@
@use '../../partials/flex';
.image-pack-profile {
padding: var(--sp-normal);
display: flex;
align-items: flex-start;
gap: var(--sp-tight);
&__content {
@extend .cp-fx__item-one;
& > div:first-child {
display: flex;
align-items: center;
gap: var(--sp-extra-tight);
& .ic-btn {
padding: var(--sp-ultra-tight);
}
}
& > form {
display: flex;
flex-direction: column;
gap: var(--sp-extra-tight);
& > div:last-child {
margin: var(--sp-extra-tight) 0;
display: flex;
gap: var(--sp-tight);
}
}
}
&__usage {
& > *:first-child {
margin-bottom: var(--sp-ultra-tight);
}
}
}
@@ -0,0 +1,73 @@
import React, { useState, useRef } from 'react';
import PropTypes from 'prop-types';
import './ImagePackUpload.scss';
import initMatrix from '../../../client/initMatrix';
import { scaleDownImage } from '../../../util/common';
import Text from '../../atoms/text/Text';
import Button from '../../atoms/button/Button';
import Input from '../../atoms/input/Input';
import IconButton from '../../atoms/button/IconButton';
import CirclePlusIC from '../../../../public/res/ic/outlined/circle-plus.svg';
function ImagePackUpload({ onUpload }) {
const mx = initMatrix.matrixClient;
const inputRef = useRef(null);
const shortcodeRef = useRef(null);
const [imgFile, setImgFile] = useState(null);
const [progress, setProgress] = useState(false);
const handleSubmit = async (evt) => {
evt.preventDefault();
if (!imgFile) return;
const { shortcodeInput } = evt.target;
const shortcode = shortcodeInput.value.trim();
if (shortcode === '') return;
setProgress(true);
const image = await scaleDownImage(imgFile, 512, 512);
const { content_uri: url } = await mx.uploadContent(image);
onUpload(shortcode, url);
setProgress(false);
setImgFile(null);
shortcodeRef.current.value = '';
};
const handleFileChange = (evt) => {
const img = evt.target.files[0];
if (!img) return;
setImgFile(img);
shortcodeRef.current.value = img.name.slice(0, img.name.indexOf('.'));
shortcodeRef.current.focus();
};
const handleRemove = () => {
setImgFile(null);
inputRef.current.value = null;
shortcodeRef.current.value = '';
};
return (
<form onSubmit={handleSubmit} className="image-pack-upload">
<input ref={inputRef} onChange={handleFileChange} style={{ display: 'none' }} type="file" accept=".png, .gif, .webp" required />
{
imgFile
? (
<div className="image-pack-upload__file">
<IconButton onClick={handleRemove} src={CirclePlusIC} tooltip="Remove file" />
<Text>{imgFile.name}</Text>
</div>
)
: <Button onClick={() => inputRef.current.click()}>Import image</Button>
}
<Input forwardRef={shortcodeRef} name="shortcodeInput" placeholder="shortcode" required />
<Button disabled={progress} variant="primary" type="submit">{progress ? 'Uploading...' : 'Upload'}</Button>
</form>
);
}
ImagePackUpload.propTypes = {
onUpload: PropTypes.func.isRequired,
};
export default ImagePackUpload;
@@ -0,0 +1,43 @@
@use '../../partials/dir';
@use '../../partials/text';
.image-pack-upload {
padding: var(--sp-normal);
padding-top: 0;
display: flex;
gap: var(--sp-tight);
& > .input-container {
flex-grow: 1;
input {
padding: 9px var(--sp-normal);
}
}
&__file {
display: inline-flex;
align-items: center;
background: var(--bg-surface-low);
border-radius: var(--bo-radius);
box-shadow: var(--bs-surface-border);
& button {
--parent-height: 40px;
width: var(--parent-height);
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
& .ic-raw {
background-color: var(--bg-caution);
transform: rotate(45deg);
}
& .text {
@extend .cp-txt__ellipsis;
@include dir.side(margin, var(--sp-ultra-tight), var(--sp-normal));
max-width: 86px;
}
}
}
@@ -0,0 +1,41 @@
import React from 'react';
import PropTypes from 'prop-types';
import { MenuHeader, MenuItem } from '../../atoms/context-menu/ContextMenu';
import CheckIC from '../../../../public/res/ic/outlined/check.svg';
function ImagePackUsageSelector({ usage, onSelect }) {
return (
<div>
<MenuHeader>Usage</MenuHeader>
<MenuItem
iconSrc={usage === 'emoticon' ? CheckIC : undefined}
variant={usage === 'emoticon' ? 'positive' : 'surface'}
onClick={() => onSelect('emoticon')}
>
Emoji
</MenuItem>
<MenuItem
iconSrc={usage === 'sticker' ? CheckIC : undefined}
variant={usage === 'sticker' ? 'positive' : 'surface'}
onClick={() => onSelect('sticker')}
>
Sticker
</MenuItem>
<MenuItem
iconSrc={usage === 'both' ? CheckIC : undefined}
variant={usage === 'both' ? 'positive' : 'surface'}
onClick={() => onSelect('both')}
>
Both
</MenuItem>
</div>
);
}
ImagePackUsageSelector.propTypes = {
usage: PropTypes.oneOf(['emoticon', 'sticker', 'both']).isRequired,
onSelect: PropTypes.func.isRequired,
};
export default ImagePackUsageSelector;
+14 -4
View File
@@ -7,9 +7,13 @@ import initMatrix from '../../../client/initMatrix';
import Text from '../../atoms/text/Text';
import Avatar from '../../atoms/avatar/Avatar';
import Spinner from '../../atoms/spinner/Spinner';
import RawIcon from '../../atoms/system-icons/RawIcon';
import PlusIC from '../../../../public/res/ic/outlined/plus.svg';
function ImageUpload({
text, bgColor, imageSrc, onUpload, onRequestRemove,
size,
}) {
const [uploadPromise, setUploadPromise] = useState(null);
const uploadImageRef = useRef(null);
@@ -18,7 +22,7 @@ function ImageUpload({
const file = e.target.files.item(0);
if (file === null) return;
try {
const uPromise = initMatrix.matrixClient.uploadContent(file, { onlyContentUri: false });
const uPromise = initMatrix.matrixClient.uploadContent(file);
setUploadPromise(uPromise);
const res = await uPromise;
@@ -50,10 +54,14 @@ function ImageUpload({
imageSrc={imageSrc}
text={text}
bgColor={bgColor}
size="large"
size={size}
/>
<div className={`img-upload__process ${uploadPromise === null ? ' img-upload__process--stopped' : ''}`}>
{uploadPromise === null && <Text variant="b3" weight="bold">Upload</Text>}
{uploadPromise === null && (
size === 'large'
? <Text variant="b3" weight="bold">Upload</Text>
: <RawIcon src={PlusIC} color="white" />
)}
{uploadPromise !== null && <Spinner size="small" />}
</div>
</button>
@@ -66,7 +74,7 @@ function ImageUpload({
<Text variant="b3">{uploadPromise ? 'Cancel' : 'Remove'}</Text>
</button>
)}
<input onChange={uploadImage} style={{ display: 'none' }} ref={uploadImageRef} type="file" />
<input onChange={uploadImage} style={{ display: 'none' }} ref={uploadImageRef} type="file" accept="image/*" />
</div>
);
}
@@ -75,6 +83,7 @@ ImageUpload.defaultProps = {
text: null,
bgColor: 'transparent',
imageSrc: null,
size: 'large',
};
ImageUpload.propTypes = {
@@ -83,6 +92,7 @@ ImageUpload.propTypes = {
imageSrc: PropTypes.string,
onUpload: PropTypes.func.isRequired,
onRequestRemove: PropTypes.func.isRequired,
size: PropTypes.oneOf(['large', 'normal']),
};
export default ImageUpload;
+141 -84
View File
@@ -4,42 +4,17 @@ import './Media.scss';
import encrypt from 'browser-encrypt-attachment';
import { BlurhashCanvas } from 'react-blurhash';
import Text from '../../atoms/text/Text';
import IconButton from '../../atoms/button/IconButton';
import Spinner from '../../atoms/spinner/Spinner';
import ImageLightbox from '../image-lightbox/ImageLightbox';
import DownloadSVG from '../../../../public/res/ic/outlined/download.svg';
import ExternalSVG from '../../../../public/res/ic/outlined/external.svg';
import PlaySVG from '../../../../public/res/ic/outlined/play.svg';
// https://github.com/matrix-org/matrix-react-sdk/blob/a9e28db33058d1893d964ec96cd247ecc3d92fc3/src/utils/blobs.ts#L73
const ALLOWED_BLOB_MIMETYPES = [
'image/jpeg',
'image/gif',
'image/png',
'video/mp4',
'video/webm',
'video/ogg',
'audio/mp4',
'audio/webm',
'audio/aac',
'audio/mpeg',
'audio/ogg',
'audio/wave',
'audio/wav',
'audio/x-wav',
'audio/x-pn-wav',
'audio/flac',
'audio/x-flac',
];
function getBlobSafeMimeType(mimetype) {
if (!ALLOWED_BLOB_MIMETYPES.includes(mimetype)) {
return 'application/octet-stream';
}
return mimetype;
}
import { getBlobSafeMimeType } from '../../../util/mimetypes';
async function getDecryptedBlob(response, type, decryptData) {
const arrayBuffer = await response.arrayBuffer();
@@ -61,16 +36,12 @@ async function getUrl(link, type, decryptData) {
}
}
function getNativeHeight(width, height) {
const MEDIA_MAX_WIDTH = 296;
const scale = MEDIA_MAX_WIDTH / width;
function getNativeHeight(width, height, maxWidth = 296) {
const scale = maxWidth / width;
return scale * height;
}
function FileHeader({
name, link, external,
file, type,
}) {
function FileHeader({ name, link, external, file, type }) {
const [url, setUrl] = useState(null);
async function getFile() {
@@ -87,19 +58,19 @@ function FileHeader({
}
return (
<div className="file-header">
<Text className="file-name" variant="b3">{name}</Text>
{ link !== null && (
<Text className="file-name" variant="b3">
{name}
</Text>
{link !== null && (
<>
{
external && (
<IconButton
size="extra-small"
tooltip="Open in new tab"
src={ExternalSVG}
onClick={() => window.open(url || link)}
/>
)
}
{external && (
<IconButton
size="extra-small"
tooltip="Open in new tab"
src={ExternalSVG}
onClick={() => window.open(url || link)}
/>
)}
<a href={url || link} download={name} target="_blank" rel="noreferrer">
<IconButton
size="extra-small"
@@ -126,9 +97,7 @@ FileHeader.propTypes = {
type: PropTypes.string.isRequired,
};
function File({
name, link, file, type,
}) {
function File({ name, link, file, type }) {
return (
<div className="file-container">
<FileHeader name={name} link={link} file={file} type={type} />
@@ -146,9 +115,75 @@ File.propTypes = {
file: PropTypes.shape({}),
};
function Image({
name, width, height, link, file, type,
}) {
function Image({ name, width, height, link, file, type, blurhash }) {
const [url, setUrl] = useState(null);
const [blur, setBlur] = useState(true);
const [lightbox, setLightbox] = useState(false);
useEffect(() => {
let unmounted = false;
async function fetchUrl() {
const myUrl = await getUrl(link, type, file);
if (unmounted) return;
setUrl(myUrl);
}
fetchUrl();
return () => {
unmounted = true;
};
}, []);
const toggleLightbox = () => {
if (!url) return;
setLightbox(!lightbox);
};
return (
<>
<div className="file-container">
<div
style={{ height: width !== null ? getNativeHeight(width, height) : 'unset' }}
className="image-container"
role="button"
tabIndex="0"
onClick={toggleLightbox}
onKeyDown={toggleLightbox}
>
{blurhash && blur && <BlurhashCanvas hash={blurhash} punch={1} />}
{url !== null && (
<img
style={{ display: blur ? 'none' : 'unset' }}
onLoad={() => setBlur(false)}
src={url || link}
alt={name}
/>
)}
</div>
</div>
{url && (
<ImageLightbox url={url} alt={name} isOpen={lightbox} onRequestClose={toggleLightbox} />
)}
</>
);
}
Image.defaultProps = {
file: null,
width: null,
height: null,
type: '',
blurhash: '',
};
Image.propTypes = {
name: PropTypes.string.isRequired,
width: PropTypes.number,
height: PropTypes.number,
link: PropTypes.string.isRequired,
file: PropTypes.shape({}),
type: PropTypes.string,
blurhash: PropTypes.string,
};
function Sticker({ name, height, width, link, file, type }) {
const [url, setUrl] = useState(null);
useEffect(() => {
@@ -165,21 +200,21 @@ function Image({
}, []);
return (
<div className="file-container">
<FileHeader name={name} link={url || link} type={type} external />
<div style={{ height: width !== null ? getNativeHeight(width, height) : 'unset' }} className="image-container">
{ url !== null && <img src={url || link} alt={name} />}
</div>
<div
className="sticker-container"
style={{ height: width !== null ? getNativeHeight(width, height, 256) : 'unset' }}
>
{url !== null && <img src={url || link} title={name} alt={name} />}
</div>
);
}
Image.defaultProps = {
Sticker.defaultProps = {
file: null,
type: '',
width: null,
height: null,
type: '',
};
Image.propTypes = {
Sticker.propTypes = {
name: PropTypes.string.isRequired,
width: PropTypes.number,
height: PropTypes.number,
@@ -188,9 +223,7 @@ Image.propTypes = {
type: PropTypes.string,
};
function Audio({
name, link, type, file,
}) {
function Audio({ name, link, type, file }) {
const [isLoading, setIsLoading] = useState(false);
const [url, setUrl] = useState(null);
@@ -208,9 +241,11 @@ function Audio({
<div className="file-container">
<FileHeader name={name} link={file !== null ? url : url || link} type={type} external />
<div className="audio-container">
{ url === null && isLoading && <Spinner size="small" /> }
{ url === null && !isLoading && <IconButton onClick={handlePlayAudio} tooltip="Play audio" src={PlaySVG} />}
{ url !== null && (
{url === null && isLoading && <Spinner size="small" />}
{url === null && !isLoading && (
<IconButton onClick={handlePlayAudio} tooltip="Play audio" src={PlaySVG} />
)}
{url !== null && (
/* eslint-disable-next-line jsx-a11y/media-has-caption */
<audio autoPlay controls>
<source src={url} type={getBlobSafeMimeType(type)} />
@@ -232,12 +267,21 @@ Audio.propTypes = {
};
function Video({
name, link, thumbnail,
width, height, file, type, thumbnailFile, thumbnailType,
name,
link,
thumbnail,
thumbnailFile,
thumbnailType,
width,
height,
file,
type,
blurhash,
}) {
const [isLoading, setIsLoading] = useState(false);
const [url, setUrl] = useState(null);
const [thumbUrl, setThumbUrl] = useState(null);
const [blur, setBlur] = useState(true);
useEffect(() => {
let unmounted = false;
@@ -252,16 +296,16 @@ function Video({
};
}, []);
async function loadVideo() {
const loadVideo = async () => {
const myUrl = await getUrl(link, type, file);
setUrl(myUrl);
setIsLoading(false);
}
};
function handlePlayVideo() {
const handlePlayVideo = () => {
setIsLoading(true);
loadVideo();
}
};
return (
<div className="file-container">
@@ -269,14 +313,27 @@ function Video({
<div
style={{
height: width !== null ? getNativeHeight(width, height) : 'unset',
backgroundImage: thumbUrl === null ? 'none' : `url(${thumbUrl}`,
}}
className="video-container"
>
{ url === null && isLoading && <Spinner size="small" /> }
{ url === null && !isLoading && <IconButton onClick={handlePlayVideo} tooltip="Play video" src={PlaySVG} />}
{ url !== null && (
/* eslint-disable-next-line jsx-a11y/media-has-caption */
{url === null ? (
<>
{blurhash && blur && <BlurhashCanvas hash={blurhash} punch={1} />}
{thumbUrl !== null && (
<img
style={{ display: blur ? 'none' : 'unset' }}
src={thumbUrl}
onLoad={() => setBlur(false)}
alt={name}
/>
)}
{isLoading && <Spinner size="small" />}
{!isLoading && (
<IconButton onClick={handlePlayVideo} tooltip="Play video" src={PlaySVG} />
)}
</>
) : (
/* eslint-disable-next-line jsx-a11y/media-has-caption */
<video autoPlay controls poster={thumbUrl}>
<source src={url} type={getBlobSafeMimeType(type)} />
</video>
@@ -290,22 +347,22 @@ Video.defaultProps = {
height: null,
file: null,
thumbnail: null,
type: '',
thumbnailType: null,
thumbnailFile: null,
type: '',
blurhash: null,
};
Video.propTypes = {
name: PropTypes.string.isRequired,
link: PropTypes.string.isRequired,
thumbnail: PropTypes.string,
thumbnailFile: PropTypes.shape({}),
thumbnailType: PropTypes.string,
width: PropTypes.number,
height: PropTypes.number,
file: PropTypes.shape({}),
type: PropTypes.string,
thumbnailFile: PropTypes.shape({}),
thumbnailType: PropTypes.string,
blurhash: PropTypes.string,
};
export {
File, Image, Audio, Video,
};
export { File, Image, Sticker, Audio, Video };
+29 -5
View File
@@ -27,6 +27,15 @@
white-space: initial;
}
.sticker-container {
display: inline-flex;
max-width: 256px;
width: 100%;
& img {
width: 100% !important;
}
}
.image-container,
.video-container,
.audio-container {
@@ -42,25 +51,40 @@
background-size: cover;
}
.image-container {
& img {
.image-container,
.video-container {
& img,
& canvas {
max-width: unset !important;
width: 100% !important;
height: 100%;
border-radius: 0 !important;
margin: 0 !important;
}
}
.image-container {
max-height: 460px;
img {
cursor: pointer;
object-fit: cover;
}
}
.video-container {
position: relative;
& .ic-btn-surface {
background-color: var(--bg-surface-low);
}
& .ic-btn-surface,
& .donut-spinner {
position: absolute;
}
video {
width: 100%
width: 100%;
}
}
.audio-container {
audio {
width: 100%
width: 100%;
}
}
}
+236 -162
View File
@@ -1,20 +1,28 @@
/* eslint-disable react/prop-types */
import React, {
useState, useEffect, useCallback, useRef,
} from 'react';
import React, { useState, useEffect, useCallback, useRef } from 'react';
import PropTypes from 'prop-types';
import './Message.scss';
import { getShortcodeToCustomEmoji } from '../../organisms/emoji-board/custom-emoji';
import { twemojify } from '../../../util/twemojify';
import initMatrix from '../../../client/initMatrix';
import { getUsername, getUsernameOfRoomMember, parseReply } from '../../../util/matrixUtil';
import {
getUsername,
getUsernameOfRoomMember,
parseReply,
trimHTMLReply,
} from '../../../util/matrixUtil';
import colorMXID from '../../../util/colorMXID';
import { getEventCords } from '../../../util/common';
import { redactEvent, sendReaction } from '../../../client/action/roomTimeline';
import {
openEmojiBoard, openProfileViewer, openReadReceipts, openViewSource, replyTo,
openEmojiBoard,
openProfileViewer,
openReadReceipts,
openTextTranslate,
openViewSource,
replyTo,
} from '../../../client/action/navigation';
import { sanitizeCustomHtml } from '../../../util/sanitize';
@@ -25,7 +33,12 @@ import Tooltip from '../../atoms/tooltip/Tooltip';
import Input from '../../atoms/input/Input';
import Avatar from '../../atoms/avatar/Avatar';
import IconButton from '../../atoms/button/IconButton';
import ContextMenu, { MenuHeader, MenuItem, MenuBorder } from '../../atoms/context-menu/ContextMenu';
import Time from '../../atoms/time/Time';
import ContextMenu, {
MenuHeader,
MenuItem,
MenuBorder,
} from '../../atoms/context-menu/ContextMenu';
import * as Media from '../media/Media';
import ReplyArrowIC from '../../../../public/res/ic/outlined/reply-arrow.svg';
@@ -33,10 +46,14 @@ import EmojiAddIC from '../../../../public/res/ic/outlined/emoji-add.svg';
import VerticalMenuIC from '../../../../public/res/ic/outlined/vertical-menu.svg';
import PencilIC from '../../../../public/res/ic/outlined/pencil.svg';
import TickMarkIC from '../../../../public/res/ic/outlined/tick-mark.svg';
import CmdIC from '../../../../public/res/ic/outlined/cmd.svg';
import BinIC from '../../../../public/res/ic/outlined/bin.svg';
import TransIC from '../../../../public/res/ic/outlined/translate.svg';
import { confirmDialog } from '../confirm-dialog/ConfirmDialog';
import { getBlobSafeMimeType } from '../../../util/mimetypes';
import { html, plain } from '../../../util/markdown';
function PlaceholderMessage() {
return (
@@ -57,9 +74,7 @@ function PlaceholderMessage() {
);
}
const MessageAvatar = React.memo(({
roomId, avatarSrc, userId, username,
}) => (
const MessageAvatar = React.memo(({ roomId, avatarSrc, userId, username }) => (
<div className="message__avatar-container">
<button type="button" onClick={() => openProfileViewer(userId, roomId)}>
<Avatar imageSrc={avatarSrc} text={username} bgColor={colorMXID(userId)} size="small" />
@@ -67,9 +82,7 @@ const MessageAvatar = React.memo(({
</div>
));
const MessageHeader = React.memo(({
userId, username, time,
}) => (
const MessageHeader = React.memo(({ userId, username, timestamp, fullTime }) => (
<div className="message__header">
<Text
style={{ color: colorMXID(userId) }}
@@ -82,14 +95,20 @@ const MessageHeader = React.memo(({
<span>{twemojify(userId)}</span>
</Text>
<div className="message__time">
<Text variant="b3">{time}</Text>
<Text variant="b3">
<Time timestamp={timestamp} fullTime={fullTime} />
</Text>
</div>
</div>
));
MessageHeader.defaultProps = {
fullTime: false,
};
MessageHeader.propTypes = {
userId: PropTypes.string.isRequired,
username: PropTypes.string.isRequired,
time: PropTypes.string.isRequired,
timestamp: PropTypes.number.isRequired,
fullTime: PropTypes.bool,
};
function MessageReply({ name, color, body }) {
@@ -97,9 +116,7 @@ function MessageReply({ name, color, body }) {
<div className="message__reply">
<Text variant="b2">
<RawIcon color={color} size="extra-small" src={ReplyArrowIC} />
<span style={{ color }}>{twemojify(name)}</span>
{' '}
{twemojify(body)}
<span style={{ color }}>{twemojify(name)}</span> {twemojify(body)}
</Text>
</div>
);
@@ -133,7 +150,9 @@ const MessageReplyWrapper = React.memo(({ roomTimeline, eventId }) => {
const username = getUsernameOfRoomMember(mEvent.sender);
if (isMountedRef.current === false) return;
const fallbackBody = mEvent.isRedacted() ? '*** This message has been deleted ***' : '*** Unable to load reply ***';
const fallbackBody = mEvent.isRedacted()
? '*** This message has been deleted ***'
: '*** Unable to load reply ***';
let parsedBody = parseReply(rawBody)?.body ?? rawBody ?? fallbackBody;
if (editedList && parsedBody.startsWith(' * ')) {
parsedBody = parsedBody.slice(3);
@@ -162,8 +181,8 @@ const MessageReplyWrapper = React.memo(({ roomTimeline, eventId }) => {
}, []);
const focusReply = (ev) => {
if (!ev.keyCode || ev.keyCode === 32 || ev.keyCode === 13) {
if (ev.keyCode) ev.preventDefault();
if (!ev.key || ev.key === ' ' || ev.key === 'Enter') {
if (ev.key) ev.preventDefault();
if (reply?.event === null) return;
if (reply?.event.isRedacted()) return;
roomTimeline.loadEventTimeline(eventId);
@@ -187,20 +206,20 @@ MessageReplyWrapper.propTypes = {
eventId: PropTypes.string.isRequired,
};
const MessageBody = React.memo(({
senderName,
body,
isCustomHTML,
isEdited,
msgType,
}) => {
const MessageBody = React.memo(({ senderName, body, isCustomHTML, isEdited, msgType }) => {
// if body is not string it is a React element.
if (typeof body !== 'string') return <div className="message__body">{body}</div>;
let content = null;
if (isCustomHTML) {
try {
content = twemojify(sanitizeCustomHtml(body), undefined, true, false, true);
content = twemojify(
sanitizeCustomHtml(initMatrix.matrixClient, body),
undefined,
true,
false,
true
);
} catch {
console.error('Malformed custom html: ', body);
content = twemojify(body, undefined);
@@ -224,10 +243,14 @@ const MessageBody = React.memo(({
const nEmojis = content.filter((e) => e.type === 'img').length;
// Make sure there's no text besides whitespace and variation selector U+FE0F
if (nEmojis <= 10 && content.every((element) => (
(typeof element === 'object' && element.type === 'img')
|| (typeof element === 'string' && /^[\s\ufe0f]*$/g.test(element))
))) {
if (
nEmojis <= 10 &&
content.every(
(element) =>
(typeof element === 'object' && element.type === 'img') ||
(typeof element === 'string' && /^[\s\ufe0f]*$/g.test(element))
)
) {
emojiOnly = true;
}
}
@@ -235,22 +258,25 @@ const MessageBody = React.memo(({
if (!isCustomHTML) {
// If this is a plaintext message, wrap it in a <p> element (automatically applying
// white-space: pre-wrap) in order to preserve newlines
content = (<p>{content}</p>);
content = <p className="message__body-plain">{content}</p>;
}
return (
<div className="message__body">
<div className={`text ${emojiOnly ? 'text-h1' : 'text-b1'}`}>
{ msgType === 'm.emote' && (
<div dir="auto" className={`text ${emojiOnly ? 'text-h1' : 'text-b1'}`}>
{msgType === 'm.emote' && (
<>
{'* '}
{twemojify(senderName)}
{' '}
{twemojify(senderName)}{' '}
</>
)}
{ content }
{content}
</div>
{ isEdited && <Text className="message__body-edited" variant="b3">(edited)</Text>}
{isEdited && (
<Text className="message__body-edited" variant="b3">
(edited)
</Text>
)}
</div>
);
});
@@ -277,14 +303,25 @@ function MessageEdit({ body, onSave, onCancel }) {
}, []);
const handleKeyDown = (e) => {
if (e.keyCode === 13 && e.shiftKey === false) {
if (e.key === 'Escape') {
e.preventDefault();
onSave(editInputRef.current.value);
onCancel();
}
if (e.key === 'Enter' && e.shiftKey === false) {
e.preventDefault();
onSave(editInputRef.current.value, body);
}
};
return (
<form className="message__edit" onSubmit={(e) => { e.preventDefault(); onSave(editInputRef.current.value); }}>
<form
className="message__edit"
onSubmit={(e) => {
e.preventDefault();
onSave(editInputRef.current.value, body);
}}
>
<Input
forwardRef={editInputRef}
onKeyDown={handleKeyDown}
@@ -295,7 +332,9 @@ function MessageEdit({ body, onSave, onCancel }) {
autoFocus
/>
<div className="message__edit-btns">
<Button type="submit" variant="primary">Save</Button>
<Button type="submit" variant="primary">
Save
</Button>
<Button onClick={onCancel}>Cancel</Button>
</div>
</form>
@@ -322,7 +361,7 @@ function getMyEmojiEvent(emojiKey, eventId, roomTimeline) {
return rEvent;
}
function toggleEmoji(roomId, eventId, emojiKey, roomTimeline) {
function toggleEmoji(roomId, eventId, emojiKey, shortcode, roomTimeline) {
const myAlreadyReactEvent = getMyEmojiEvent(emojiKey, eventId, roomTimeline);
if (myAlreadyReactEvent) {
const rId = myAlreadyReactEvent.getId();
@@ -330,67 +369,77 @@ function toggleEmoji(roomId, eventId, emojiKey, roomTimeline) {
redactEvent(roomId, rId);
return;
}
sendReaction(roomId, eventId, emojiKey);
sendReaction(roomId, eventId, emojiKey, shortcode);
}
function pickEmoji(e, roomId, eventId, roomTimeline) {
openEmojiBoard(getEventCords(e), (emoji) => {
toggleEmoji(roomId, eventId, emoji.unicode, roomTimeline);
toggleEmoji(roomId, eventId, emoji.mxc ?? emoji.unicode, emoji.shortcodes[0], roomTimeline);
e.target.click();
});
}
function genReactionMsg(userIds, reaction) {
function genReactionMsg(userIds, reaction, shortcode) {
return (
<>
{userIds.map((userId, index) => (
<React.Fragment key={userId}>
{twemojify(getUsername(userId))}
{index < userIds.length - 1 && (
<span style={{ opacity: '.6' }}>
{index === userIds.length - 2 ? ' and ' : ', '}
</span>
<span style={{ opacity: '.6' }}>{index === userIds.length - 2 ? ' and ' : ', '}</span>
)}
</React.Fragment>
))}
<span style={{ opacity: '.6' }}>{' reacted with '}</span>
{twemojify(reaction, { className: 'react-emoji' })}
{twemojify(shortcode ? `:${shortcode}:` : reaction, { className: 'react-emoji' })}
</>
);
}
function MessageReaction({
shortcodeToEmoji, reaction, count, users, isActive, onClick,
}) {
const customEmojiMatch = reaction.match(/^:(\S+):$/);
function MessageReaction({ reaction, shortcode, count, users, isActive, onClick }) {
let customEmojiUrl = null;
if (customEmojiMatch) {
const customEmoji = shortcodeToEmoji.get(customEmojiMatch[1]);
customEmojiUrl = initMatrix.matrixClient.mxcUrlToHttp(customEmoji?.mxc);
if (reaction.match(/^mxc:\/\/\S+$/)) {
customEmojiUrl = initMatrix.matrixClient.mxcUrlToHttp(reaction);
}
return (
<Tooltip
className="msg__reaction-tooltip"
content={<Text variant="b2">{users.length > 0 ? genReactionMsg(users, reaction) : 'Unable to load who has reacted'}</Text>}
content={
<Text variant="b2">
{users.length > 0
? genReactionMsg(users, reaction, shortcode)
: 'Unable to load who has reacted'}
</Text>
}
>
<button
onClick={onClick}
type="button"
className={`msg__reaction${isActive ? ' msg__reaction--active' : ''}`}
>
{
customEmojiUrl
? <img className="react-emoji" draggable="false" alt={reaction} src={customEmojiUrl} />
: twemojify(reaction, { className: 'react-emoji' })
}
<Text variant="b3" className="msg__reaction-count">{count}</Text>
{customEmojiUrl ? (
<img
className="react-emoji"
draggable="false"
alt={shortcode ?? reaction}
src={customEmojiUrl}
/>
) : (
twemojify(reaction, { className: 'react-emoji' })
)}
<Text variant="b3" className="msg__reaction-count">
{count}
</Text>
</button>
</Tooltip>
);
}
MessageReaction.defaultProps = {
shortcode: undefined,
};
MessageReaction.propTypes = {
shortcodeToEmoji: PropTypes.shape({}).isRequired,
reaction: PropTypes.node.isRequired,
shortcode: PropTypes.string,
count: PropTypes.number.isRequired,
users: PropTypes.arrayOf(PropTypes.string).isRequired,
isActive: PropTypes.bool.isRequired,
@@ -401,11 +450,10 @@ function MessageReactionGroup({ roomTimeline, mEvent }) {
const { roomId, room, reactionTimeline } = roomTimeline;
const mx = initMatrix.matrixClient;
const reactions = {};
const shortcodeToEmoji = getShortcodeToCustomEmoji(room);
const canSendReaction = room.currentState.maySendEvent('m.reaction', mx.getUserId());
const eventReactions = reactionTimeline.get(mEvent.getId());
const addReaction = (key, count, senderId, isActive) => {
const addReaction = (key, shortcode, count, senderId, isActive) => {
let reaction = reactions[key];
if (reaction === undefined) {
reaction = {
@@ -414,6 +462,7 @@ function MessageReactionGroup({ roomTimeline, mEvent }) {
isActive: false,
};
}
if (shortcode) reaction.shortcode = shortcode;
if (count) {
reaction.count = count;
} else {
@@ -429,9 +478,10 @@ function MessageReactionGroup({ roomTimeline, mEvent }) {
if (rEvent.getRelation() === null) return;
const reaction = rEvent.getRelation();
const senderId = rEvent.getSender();
const { shortcode } = rEvent.getContent();
const isActive = senderId === mx.getUserId();
addReaction(reaction.key, undefined, senderId, isActive);
addReaction(reaction.key, shortcode, undefined, senderId, isActive);
});
} else {
// Use aggregated reactions
@@ -439,27 +489,25 @@ function MessageReactionGroup({ roomTimeline, mEvent }) {
if (!aggregatedReaction) return null;
aggregatedReaction.forEach((reaction) => {
if (reaction.type !== 'm.reaction') return;
addReaction(reaction.key, reaction.count, undefined, false);
addReaction(reaction.key, undefined, reaction.count, undefined, false);
});
}
return (
<div className="message__reactions text text-b3 noselect">
{
Object.keys(reactions).map((key) => (
<MessageReaction
key={key}
shortcodeToEmoji={shortcodeToEmoji}
reaction={key}
count={reactions[key].count}
users={reactions[key].users}
isActive={reactions[key].isActive}
onClick={() => {
toggleEmoji(roomId, mEvent.getId(), key, roomTimeline);
}}
/>
))
}
{Object.keys(reactions).map((key) => (
<MessageReaction
key={key}
reaction={key}
shortcode={reactions[key].shortcode}
count={reactions[key].count}
users={reactions[key].users}
isActive={reactions[key].isActive}
onClick={() => {
toggleEmoji(roomId, mEvent.getId(), key, reactions[key].shortcode, roomTimeline);
}}
/>
))}
{canSendReaction && (
<IconButton
onClick={(e) => {
@@ -480,11 +528,11 @@ MessageReactionGroup.propTypes = {
function isMedia(mE) {
return (
mE.getContent()?.msgtype === 'm.file'
|| mE.getContent()?.msgtype === 'm.image'
|| mE.getContent()?.msgtype === 'm.audio'
|| mE.getContent()?.msgtype === 'm.video'
|| mE.getType() === 'm.sticker'
mE.getContent()?.msgtype === 'm.file' ||
mE.getContent()?.msgtype === 'm.image' ||
mE.getContent()?.msgtype === 'm.audio' ||
mE.getContent()?.msgtype === 'm.video' ||
mE.getType() === 'm.sticker'
);
}
@@ -500,9 +548,11 @@ function handleOpenViewSource(mEvent, roomTimeline) {
openViewSource(editedMEvent !== undefined ? editedMEvent : mEvent);
}
const MessageOptions = React.memo(({
roomTimeline, mEvent, edit, reply,
}) => {
function handleTextTranslate(mEvent) {
openTextTranslate(mEvent);
}
const MessageOptions = React.memo(({ roomTimeline, mEvent, edit, reply }) => {
const { roomId, room } = roomTimeline;
const mx = initMatrix.matrixClient;
const senderId = mEvent.getSender();
@@ -521,19 +571,9 @@ const MessageOptions = React.memo(({
tooltip="Add reaction"
/>
)}
<IconButton
onClick={() => reply()}
src={ReplyArrowIC}
size="extra-small"
tooltip="Reply"
/>
{(senderId === mx.getUserId() && !isMedia(mEvent)) && (
<IconButton
onClick={() => edit(true)}
src={PencilIC}
size="extra-small"
tooltip="Edit"
/>
<IconButton onClick={() => reply()} src={ReplyArrowIC} size="extra-small" tooltip="Reply" />
{senderId === mx.getUserId() && !isMedia(mEvent) && (
<IconButton onClick={() => edit(true)} src={PencilIC} size="extra-small" tooltip="Edit" />
)}
<ContextMenu
content={() => (
@@ -545,12 +585,12 @@ const MessageOptions = React.memo(({
>
Read receipts
</MenuItem>
<MenuItem
iconSrc={CmdIC}
onClick={() => handleOpenViewSource(mEvent, roomTimeline)}
>
<MenuItem iconSrc={CmdIC} onClick={() => handleOpenViewSource(mEvent, roomTimeline)}>
View source
</MenuItem>
<MenuItem iconSrc={TransIC} onClick={() => handleTextTranslate(mEvent)}>
Translate
</MenuItem>
{(canIRedact || senderId === mx.getUserId()) && (
<>
<MenuBorder />
@@ -562,7 +602,7 @@ const MessageOptions = React.memo(({
'Delete message',
'Are you sure that you want to delete this message?',
'Delete',
'danger',
'danger'
);
if (!isConfirmed) return;
redactEvent(roomId, mEvent.getId());
@@ -596,7 +636,8 @@ MessageOptions.propTypes = {
function genMediaContent(mE) {
const mx = initMatrix.matrixClient;
const mContent = mE.getContent();
if (!mContent || !mContent.body) return <span style={{ color: 'var(--bg-danger)' }}>Malformed event</span>;
if (!mContent || !mContent.body)
return <span style={{ color: 'var(--bg-danger)' }}>Malformed event</span>;
let mediaMXC = mContent?.url;
const isEncryptedFile = typeof mediaMXC === 'undefined';
@@ -604,10 +645,18 @@ function genMediaContent(mE) {
let thumbnailMXC = mContent?.info?.thumbnail_url;
if (typeof mediaMXC === 'undefined' || mediaMXC === '') return <span style={{ color: 'var(--bg-danger)' }}>Malformed event</span>;
if (typeof mediaMXC === 'undefined' || mediaMXC === '')
return <span style={{ color: 'var(--bg-danger)' }}>Malformed event</span>;
let msgType = mE.getContent()?.msgtype;
if (mE.getType() === 'm.sticker') msgType = 'm.image';
const safeMimetype = getBlobSafeMimeType(mContent.info?.mimetype);
if (mE.getType() === 'm.sticker') {
msgType = 'm.sticker';
} else if (safeMimetype === 'application/octet-stream') {
msgType = 'm.file';
}
const blurhash = mContent?.info?.['xyz.amorgan.blurhash'];
switch (msgType) {
case 'm.file':
@@ -628,6 +677,18 @@ function genMediaContent(mE) {
link={mx.mxcUrlToHttp(mediaMXC)}
file={isEncryptedFile ? mContent.file : null}
type={mContent.info?.mimetype}
blurhash={blurhash}
/>
);
case 'm.sticker':
return (
<Media.Sticker
name={mContent.body}
width={typeof mContent.info?.w === 'number' ? mContent.info?.w : null}
height={typeof mContent.info?.h === 'number' ? mContent.info?.h : null}
link={mx.mxcUrlToHttp(mediaMXC)}
file={isEncryptedFile ? mContent.file : null}
type={mContent.info?.mimetype}
/>
);
case 'm.audio':
@@ -654,6 +715,7 @@ function genMediaContent(mE) {
height={typeof mContent.info?.h === 'number' ? mContent.info?.h : null}
file={isEncryptedFile ? mContent.file : null}
type={mContent.info?.mimetype}
blurhash={blurhash}
/>
);
default:
@@ -674,13 +736,19 @@ function getEditedBody(editedMEvent) {
}
function Message({
mEvent, isBodyOnly, roomTimeline, focus, time,
mEvent,
isBodyOnly,
roomTimeline,
focus,
fullTime,
isEdit,
setEdit,
cancelEdit,
}) {
const [isEditing, setIsEditing] = useState(false);
const roomId = mEvent.getRoomId();
const { editedTimeline, reactionTimeline } = roomTimeline ?? {};
const className = ['message', (isBodyOnly ? 'message--body-only' : 'message--full')];
const className = ['message', isBodyOnly ? 'message--body-only' : 'message--full'];
if (focus) className.push('message--focus');
const content = mEvent.getContent();
const eventId = mEvent.getId();
@@ -688,62 +756,64 @@ function Message({
const senderId = mEvent.getSender();
let { body } = content;
const username = mEvent.sender ? getUsernameOfRoomMember(mEvent.sender) : getUsername(senderId);
const avatarSrc = mEvent.sender?.getAvatarUrl(initMatrix.matrixClient.baseUrl, 36, 36, 'crop') ?? null;
const avatarSrc =
mEvent.sender?.getAvatarUrl(initMatrix.matrixClient.baseUrl, 36, 36, 'crop') ?? null;
let isCustomHTML = content.format === 'org.matrix.custom.html';
let customHTML = isCustomHTML ? content.formatted_body : null;
const edit = useCallback(() => {
setIsEditing(true);
setEdit(eventId);
}, []);
const reply = useCallback(() => {
replyTo(senderId, mEvent.getId(), body);
}, [body]);
replyTo(senderId, mEvent.getId(), body, customHTML);
}, [body, customHTML]);
if (body === undefined) return null;
if (msgType === 'm.emote') className.push('message--type-emote');
let isCustomHTML = content.format === 'org.matrix.custom.html';
const isEdited = roomTimeline ? editedTimeline.has(eventId) : false;
const haveReactions = roomTimeline
? reactionTimeline.has(eventId) || !!mEvent.getServerAggregatedRelation('m.annotation')
: false;
const isReply = !!mEvent.replyEventId;
let customHTML = isCustomHTML ? content.formatted_body : null;
if (isEdited) {
const editedList = editedTimeline.get(eventId);
const editedMEvent = editedList[editedList.length - 1];
[body, isCustomHTML, customHTML] = getEditedBody(editedMEvent);
if (typeof body !== 'string') return null;
}
if (isReply) {
body = parseReply(body)?.body ?? body;
customHTML = trimHTMLReply(customHTML);
}
if (typeof body !== 'string') body = '';
return (
<div className={className.join(' ')}>
{
isBodyOnly
? <div className="message__avatar-container" />
: (
<MessageAvatar
roomId={roomId}
avatarSrc={avatarSrc}
userId={senderId}
username={username}
/>
)
}
{isBodyOnly ? (
<div className="message__avatar-container" />
) : (
<MessageAvatar
roomId={roomId}
avatarSrc={avatarSrc}
userId={senderId}
username={username}
/>
)}
<div className="message__main-container">
{!isBodyOnly && (
<MessageHeader userId={senderId} username={username} time={time} />
)}
{roomTimeline && isReply && (
<MessageReplyWrapper
roomTimeline={roomTimeline}
eventId={mEvent.replyEventId}
<MessageHeader
userId={senderId}
username={username}
timestamp={mEvent.getTs()}
fullTime={fullTime}
/>
)}
{!isEditing && (
{roomTimeline && isReply && (
<MessageReplyWrapper roomTimeline={roomTimeline} eventId={mEvent.replyEventId} />
)}
{!isEdit && (
<MessageBody
senderName={username}
isCustomHTML={isCustomHTML}
@@ -752,28 +822,25 @@ function Message({
isEdited={isEdited}
/>
)}
{isEditing && (
{isEdit && (
<MessageEdit
body={body}
onSave={(newBody) => {
if (newBody !== body) {
body={
customHTML
? html(customHTML, { kind: 'edit', onlyPlain: true }).plain
: plain(body, { kind: 'edit', onlyPlain: true }).plain
}
onSave={(newBody, oldBody) => {
if (newBody !== oldBody) {
initMatrix.roomsInput.sendEditedMessage(roomId, mEvent, newBody);
}
setIsEditing(false);
cancelEdit();
}}
onCancel={() => setIsEditing(false)}
onCancel={cancelEdit}
/>
)}
{haveReactions && (
<MessageReactionGroup roomTimeline={roomTimeline} mEvent={mEvent} />
)}
{roomTimeline && !isEditing && (
<MessageOptions
roomTimeline={roomTimeline}
mEvent={mEvent}
edit={edit}
reply={reply}
/>
{haveReactions && <MessageReactionGroup roomTimeline={roomTimeline} mEvent={mEvent} />}
{roomTimeline && !isEdit && (
<MessageOptions roomTimeline={roomTimeline} mEvent={mEvent} edit={edit} reply={reply} />
)}
</div>
</div>
@@ -783,13 +850,20 @@ Message.defaultProps = {
isBodyOnly: false,
focus: false,
roomTimeline: null,
fullTime: false,
isEdit: false,
setEdit: null,
cancelEdit: null,
};
Message.propTypes = {
mEvent: PropTypes.shape({}).isRequired,
isBodyOnly: PropTypes.bool,
roomTimeline: PropTypes.shape({}),
focus: PropTypes.bool,
time: PropTypes.string.isRequired,
fullTime: PropTypes.bool,
isEdit: PropTypes.bool,
setEdit: PropTypes.func,
cancelEdit: PropTypes.func,
};
export { Message, MessageReply, PlaceholderMessage };
+35 -18
View File
@@ -15,7 +15,7 @@
display: flex;
}
}
&__avatar-container {
padding-top: 6px;
@include dir.side(margin, 0, var(--sp-tight));
@@ -101,7 +101,6 @@
}
}
.message__header {
display: flex;
align-items: baseline;
@@ -115,10 +114,16 @@
@extend .cp-txt__ellipsis;
color: inherit;
}
& > span:last-child { display: none; }
& > span:last-child {
display: none;
}
&:hover {
& > span:first-child { display: none; }
& > span:last-child { display: block; }
& > span:first-child {
display: none;
}
& > span:last-child {
display: block;
}
}
}
@@ -158,7 +163,7 @@
.message__body {
word-break: break-word;
& > .text > * {
& > .text > .message__body-plain {
white-space: pre-wrap;
}
@@ -168,7 +173,11 @@
& > .text > a {
white-space: initial !important;
}
& > .text > p + p {
margin-top: var(--sp-normal);
}
& span[data-mx-pill] {
background-color: hsla(0, 0%, 64%, 0.15);
padding: 0 2px;
@@ -191,7 +200,7 @@
& span[data-mx-spoiler] {
border-radius: 4px;
background-color: rgba(124, 124, 124, 0.5);
color:transparent;
color: transparent;
cursor: pointer;
-webkit-touch-callout: none;
-webkit-user-select: none;
@@ -220,6 +229,8 @@
padding: var(--sp-extra-tight) 0;
&-btns button {
margin: var(--sp-tight) 0 0 0;
padding: var(--sp-ultra-tight) var(--sp-tight);
min-width: 0;
@include dir.side(margin, 0, var(--sp-tight));
}
}
@@ -250,15 +261,14 @@
cursor: pointer;
& .react-emoji {
width: 16px;
height: 16px;
margin: 2px;
}
&-count {
margin: 0 var(--sp-ultra-tight);
color: var(--tc-surface-normal)
color: var(--tc-surface-normal);
}
&-tooltip .react-emoji {
&-tooltip .react-emoji {
width: 16px;
height: 16px;
margin: 0 var(--sp-ultra-tight);
@@ -271,19 +281,19 @@
}
}
&:active {
background-color: var(--bg-surface-active)
background-color: var(--bg-surface-active);
}
&--active {
background-color: var(--bg-caution-active);
@media (hover: hover) {
&:hover {
background-color: var(--bg-caution-hover);
}
}
&:active {
background-color: var(--bg-caution-active)
background-color: var(--bg-caution-active);
}
}
}
@@ -304,7 +314,12 @@
// markdown formating
.message__body {
& h1, h2, h3, h4, h5, h6 {
& h1,
h2,
h3,
h4,
h5,
h6 {
margin: 0;
margin-bottom: var(--sp-ultra-tight);
font-weight: var(--fw-medium);
@@ -385,6 +400,7 @@
& pre {
width: fit-content;
max-width: 100%;
direction: initial;
@include scrollbar.scroll;
@include scrollbar.scroll__h;
@include scrollbar.scroll--auto-hide;
@@ -425,7 +441,8 @@
@include scrollbar.scroll__h;
@include scrollbar.scroll--auto-hide;
& td, & th {
& td,
& th {
padding: var(--sp-extra-tight);
border: 1px solid var(--bg-surface-border);
border-width: 0 1px 1px 0;
@@ -433,11 +450,11 @@
&:last-child {
border-width: 0;
border-bottom-width: 1px;
[dir=rtl] & {
[dir='rtl'] & {
border-width: 0 1px 1px 0;
}
}
[dir=rtl] &:first-child {
[dir='rtl'] &:first-child {
border-width: 0;
border-bottom-width: 1px;
}
+6 -3
View File
@@ -4,6 +4,7 @@ import './TimelineChange.scss';
import Text from '../../atoms/text/Text';
import RawIcon from '../../atoms/system-icons/RawIcon';
import Time from '../../atoms/time/Time';
import JoinArraowIC from '../../../../public/res/ic/outlined/join-arrow.svg';
import LeaveArraowIC from '../../../../public/res/ic/outlined/leave-arrow.svg';
@@ -12,7 +13,7 @@ import InviteCancelArraowIC from '../../../../public/res/ic/outlined/invite-canc
import UserIC from '../../../../public/res/ic/outlined/user.svg';
function TimelineChange({
variant, content, time, onClick,
variant, content, timestamp, onClick,
}) {
let iconSrc;
@@ -48,7 +49,9 @@ function TimelineChange({
</Text>
</div>
<div className="timeline-change__time">
<Text variant="b3">{time}</Text>
<Text variant="b3">
<Time timestamp={timestamp} />
</Text>
</div>
</button>
);
@@ -68,7 +71,7 @@ TimelineChange.propTypes = {
PropTypes.string,
PropTypes.node,
]).isRequired,
time: PropTypes.string.isRequired,
timestamp: PropTypes.number.isRequired,
onClick: PropTypes.func,
};
@@ -0,0 +1,129 @@
import React, { useReducer, useEffect } from 'react';
import PropTypes from 'prop-types';
import './RoomEmojis.scss';
import initMatrix from '../../../client/initMatrix';
import { suffixRename } from '../../../util/common';
import { MenuHeader } from '../../atoms/context-menu/ContextMenu';
import Text from '../../atoms/text/Text';
import Input from '../../atoms/input/Input';
import Button from '../../atoms/button/Button';
import ImagePack from '../image-pack/ImagePack';
function useRoomPacks(room) {
const mx = initMatrix.matrixClient;
const [, forceUpdate] = useReducer((count) => count + 1, 0);
const packEvents = room.currentState.getStateEvents('im.ponies.room_emotes');
const unUsablePacks = [];
const usablePacks = packEvents.filter((mEvent) => {
if (typeof mEvent.getContent()?.images !== 'object') {
unUsablePacks.push(mEvent);
return false;
}
return true;
});
useEffect(() => {
const handleEvent = (event, state, prevEvent) => {
if (event.getRoomId() !== room.roomId) return;
if (event.getType() !== 'im.ponies.room_emotes') return;
if (!prevEvent?.getContent()?.images || !event.getContent().images) {
forceUpdate();
}
};
mx.on('RoomState.events', handleEvent);
return () => {
mx.removeListener('RoomState.events', handleEvent);
};
}, [room, mx]);
const isStateKeyAvailable = (key) => !room.currentState.getStateEvents('im.ponies.room_emotes', key);
const createPack = async (name) => {
const packContent = {
pack: { display_name: name },
images: {},
};
let stateKey = '';
if (unUsablePacks.length > 0) {
const mEvent = unUsablePacks[0];
stateKey = mEvent.getStateKey();
} else {
stateKey = packContent.pack.display_name.replace(/\s/g, '-');
if (!isStateKeyAvailable(stateKey)) {
stateKey = suffixRename(
stateKey,
isStateKeyAvailable,
);
}
}
await mx.sendStateEvent(room.roomId, 'im.ponies.room_emotes', packContent, stateKey);
};
const deletePack = async (stateKey) => {
await mx.sendStateEvent(room.roomId, 'im.ponies.room_emotes', {}, stateKey);
};
return {
usablePacks,
createPack,
deletePack,
};
}
function RoomEmojis({ roomId }) {
const mx = initMatrix.matrixClient;
const room = mx.getRoom(roomId);
const { usablePacks, createPack, deletePack } = useRoomPacks(room);
const canChange = room.currentState.maySendStateEvent('im.ponies.room_emote', mx.getUserId());
const handlePackCreate = (e) => {
e.preventDefault();
const { nameInput } = e.target;
const name = nameInput.value.trim();
if (name === '') return;
nameInput.value = '';
createPack(name);
};
return (
<div className="room-emojis">
{ canChange && (
<div className="room-emojis__add-pack">
<MenuHeader>Create Pack</MenuHeader>
<form onSubmit={handlePackCreate}>
<Input name="nameInput" placeholder="Pack Name" required />
<Button variant="primary" type="submit">Create pack</Button>
</form>
</div>
)}
{
usablePacks.length > 0
? usablePacks.reverse().map((mEvent) => (
<ImagePack
key={mEvent.getId()}
roomId={roomId}
stateKey={mEvent.getStateKey()}
handlePackDelete={canChange ? deletePack : undefined}
/>
)) : (
<div className="room-emojis__empty">
<Text>No emoji or sticker pack.</Text>
</div>
)
}
</div>
);
}
RoomEmojis.propTypes = {
roomId: PropTypes.string.isRequired,
};
export default RoomEmojis;
@@ -0,0 +1,29 @@
.room-emojis {
.image-pack,
.room-emojis__add-pack,
.room-emojis__empty {
margin: var(--sp-normal) 0;
background-color: var(--bg-surface);
border-radius: var(--bo-radius);
box-shadow: var(--bs-surface-border);
overflow: hidden;
& > .context-menu__header:first-child {
margin-top: 2px;
}
}
&__add-pack {
& form {
margin: var(--sp-normal);
display: flex;
gap: var(--sp-normal);
& .input-container {
flex-grow: 1;
}
}
}
&__empty {
padding: var(--sp-extra-loose) var(--sp-normal);
text-align: center;
}
}
@@ -237,12 +237,12 @@ function RoomPermissions({ roomId }) {
? permissions[permInfo.parent]?.[permKey]
: permissions[permKey];
if (!permValue) permValue = permInfo.default;
if (permValue === undefined) permValue = permInfo.default;
if (typeof permValue === 'number') {
powerLevel = permValue;
} else if (permKey === 'notifications') {
powerLevel = permValue.room || 50;
powerLevel = permValue.room ?? 50;
}
return (
<SettingTile
@@ -132,7 +132,7 @@ function RoomProfile({ roomId }) {
const renderEditNameAndTopic = () => (
<form className="room-profile__edit-form" onSubmit={handleOnSubmit}>
{canChangeName && <Input value={roomName} name="room-name" disabled={status.type === cons.status.IN_FLIGHT} label="Name" required />}
{canChangeName && <Input value={roomName} name="room-name" disabled={status.type === cons.status.IN_FLIGHT} label="Name" />}
{canChangeTopic && <Input value={roomTopic} name="room-topic" disabled={status.type === cons.status.IN_FLIGHT} minHeight={100} resizable label="Topic" />}
{(!canChangeName || !canChangeTopic) && <Text variant="b3">{`You have permission to change ${room.isSpaceRoom() ? 'space' : 'room'} ${canChangeName ? 'name' : 'topic'} only.`}</Text>}
{ status.type === cons.status.IN_FLIGHT && <Text variant="b2">{status.msg}</Text>}
+1 -4
View File
@@ -2,8 +2,6 @@ import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import './RoomSearch.scss';
import dateFormat from 'dateformat';
import initMatrix from '../../../client/initMatrix';
import cons from '../../../client/state/cons';
import { selectRoom } from '../../../client/action/navigation';
@@ -120,14 +118,13 @@ function RoomSearch({ roomId }) {
const renderTimeline = (timeline) => (
<div className="room-search__result-item" key={timeline[0].getId()}>
{ timeline.map((mEvent) => {
const time = dateFormat(mEvent.getDate(), 'dd/mm/yyyy - hh:MM TT');
const id = mEvent.getId();
return (
<React.Fragment key={id}>
<Message
mEvent={mEvent}
isBodyOnly={false}
time={time}
fullTime
/>
<Button onClick={() => selectRoom(roomId, id)}>View</Button>
</React.Fragment>
@@ -0,0 +1,66 @@
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import initMatrix from '../../../client/initMatrix';
import Button from '../../atoms/button/Button';
import Text from '../../atoms/text/Text';
import './RoomTimezone.scss';
function RoomTimezone({ roomId }) {
const mx = initMatrix.matrixClient;
const room = mx.getRoom(roomId);
const userId = mx.getUserId();
const timezoneEventId = room.currentState.getStateEvents('in.cinny.shared_timezone', userId)?.event?.content?.user_timezone_event;
const timezoneEvent = room.findEventById(timezoneEventId);
const timezoneContent = timezoneEvent?.getContent();
const [timezone, setTimezone] = useState(timezoneContent?.user_timezone);
const clearTimezone = () => {
const eventKey = room.currentState.getStateEvents('in.cinny.shared_timezone', userId)?.event?.content?.user_timezone_event;
mx.redactEvent(roomId, eventKey);
mx.sendStateEvent(roomId, 'in.cinny.shared_timezone', { }, userId);
setTimezone(null);
};
const shareTimezone = () => {
const userTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
setTimezone(userTimezone);
const content = {
user_timezone: userTimezone,
msgtype: 'in.cinny.share_timezone',
};
mx.sendEvent(roomId, 'in.cinny.share_timezone', content).then((event) => {
// Append the shared timezone event to the room state
mx.sendStateEvent(roomId, 'in.cinny.shared_timezone', { user_timezone_event: event.event_id }, userId);
});
};
return (
<div className="room-timezone__content">
<Text className="room-timezone__message">Share your timezone</Text>
<Text className="room-timezone__message" variant="b3">
Sharing your timezone will allow other users in this room to see your local time.
Keep in mind that sharing your timezone will share your approximate location.
</Text>
<Text className="room-timezone__message" variant="b2">
{timezone ? `Currently shared timezone: ${timezone}` : 'You are not currently sharing a timezone'}
</Text>
<Button onClick={() => shareTimezone()} variant={timezone ? 'surface' : 'danger'}>
{timezone ? 'Update Timezone' : 'Share Timezone'}
</Button>
<Button onClick={() => clearTimezone()} disabled={!timezone}>
Clear Shared Timezone
</Button>
</div>
);
}
RoomTimezone.propTypes = {
roomId: PropTypes.string.isRequired,
};
export default RoomTimezone;
@@ -0,0 +1,84 @@
@use '../../partials/flex';
@use '../../partials/dir';
@use '../../partials/text';
.room-timezone {
&__message,
& .setting-tile {
margin: var(--sp-tight) var(--sp-normal);
}
& .setting-tile {
margin-bottom: var(--sp-loose);
}
&__alias-item {
padding: var(--sp-extra-tight) var(--sp-normal);
@extend .cp-fx__row--s-c;
&.checkbox {
@include dir.side(margin, 0 , var(--sp-tight));
}
& .text {
@extend .cp-fx__item-one;
@extend .cp-txt__ellipsis;
color: var(--tc-surface-high);
span {
margin: 0 var(--sp-extra-tight);
padding: 0 var(--sp-ultra-tight);
color: var(--bg-surface);
background-color: var(--tc-surface-low);
border-radius: 4px;
}
}
}
&__item-btns {
@include dir.side(margin, 48px, 0);
& button {
padding: var(--sp-ultra-tight) var(--sp-tight);
margin-bottom: var(--sp-tight);
@include dir.side(margin, 0, var(--sp-tight));
}
}
&__content {
margin-bottom: var(--sp-normal);
& .checkbox {
@include dir.side(margin, 0, var(--sp-tight));
min-width: 20px;
}
& > button {
margin: 0 var(--sp-normal);
}
}
&__form {
padding: var(--sp-normal);
padding-top: 0;
display: flex;
&-label {
padding: var(--sp-normal) var(--sp-normal) var(--sp-ultra-tight);
}
}
&__input-wrapper {
display: flex;
@extend .cp-fx__item-one;
@include dir.side(margin, 0, var(--sp-tight));
& .input-container {
@extend .cp-fx__item-one;
}
}
&__input-status {
padding: 0 var(--sp-normal);
}
&__valid {
color: var(--tc-positive-high);
padding-bottom: var(--sp-normal);
}
&__invalid {
color: var(--tc-danger-high);
padding-bottom: var(--sp-normal);
}
}
@@ -5,6 +5,7 @@ import { twemojify } from '../../../util/twemojify';
import initMatrix from '../../../client/initMatrix';
import { openSpaceSettings, openSpaceManage, openInviteUser } from '../../../client/action/navigation';
import { markAsRead } from '../../../client/action/notifications';
import { leave } from '../../../client/action/room';
import {
createSpaceShortcut,
@@ -17,6 +18,7 @@ import { MenuHeader, MenuItem } from '../../atoms/context-menu/ContextMenu';
import CategoryIC from '../../../../public/res/ic/outlined/category.svg';
import CategoryFilledIC from '../../../../public/res/ic/filled/category.svg';
import TickMarkIC from '../../../../public/res/ic/outlined/tick-mark.svg';
import AddUserIC from '../../../../public/res/ic/outlined/add-user.svg';
import SettingsIC from '../../../../public/res/ic/outlined/settings.svg';
import HashSearchIC from '../../../../public/res/ic/outlined/hash-search.svg';
@@ -28,11 +30,21 @@ import { confirmDialog } from '../confirm-dialog/ConfirmDialog';
function SpaceOptions({ roomId, afterOptionSelect }) {
const mx = initMatrix.matrixClient;
const { roomList } = initMatrix;
const room = mx.getRoom(roomId);
const canInvite = room?.canInvite(mx.getUserId());
const isPinned = initMatrix.accountData.spaceShortcut.has(roomId);
const isCategorized = initMatrix.accountData.categorizedSpaces.has(roomId);
const handleMarkAsRead = () => {
const spaceChildren = roomList.getCategorizedSpaces([roomId]);
spaceChildren?.forEach((childIds) => {
childIds?.forEach((childId) => {
markAsRead(childId);
});
});
afterOptionSelect();
};
const handleInviteClick = () => {
openInviteUser(roomId);
afterOptionSelect();
@@ -71,6 +83,7 @@ function SpaceOptions({ roomId, afterOptionSelect }) {
return (
<div style={{ maxWidth: 'calc(var(--navigation-drawer-width) - var(--sp-normal))' }}>
<MenuHeader>{twemojify(`Options for ${initMatrix.matrixClient.getRoom(roomId)?.name}`)}</MenuHeader>
<MenuItem iconSrc={TickMarkIC} onClick={handleMarkAsRead}>Mark as read</MenuItem>
<MenuItem
onClick={handleCategorizeClick}
iconSrc={isCategorized ? CategoryFilledIC : CategoryIC}
+138 -125
View File
@@ -13,6 +13,7 @@ import cons from '../../../client/state/cons';
import navigation from '../../../client/state/navigation';
import AsyncSearch from '../../../util/AsyncSearch';
import { addRecentEmoji, getRecentEmojis } from './recent';
import { TWEMOJI_BASE_URL } from '../../../util/twemojify';
import Text from '../../atoms/text/Text';
import RawIcon from '../../atoms/system-icons/RawIcon';
@@ -46,45 +47,49 @@ const EmojiGroup = React.memo(({ name, groupEmojis }) => {
const emoji = groupEmojis[emojiIndex];
emojiRow.push(
<span key={emojiIndex}>
{
emoji.hexcode
// This is a unicode emoji, and should be rendered with twemoji
? parse(twemoji.parse(
emoji.unicode,
{
attributes: () => ({
unicode: emoji.unicode,
shortcodes: emoji.shortcodes?.toString(),
hexcode: emoji.hexcode,
loading: 'lazy',
}),
},
))
// This is a custom emoji, and should be render as an mxc
: (
<img
className="emoji"
draggable="false"
loading="lazy"
alt={emoji.shortcode}
unicode={`:${emoji.shortcode}:`}
shortcodes={emoji.shortcode}
src={initMatrix.matrixClient.mxcUrlToHttp(emoji.mxc)}
data-mx-emoticon
/>
)
}
</span>,
{emoji.hexcode ? (
// This is a unicode emoji, and should be rendered with twemoji
parse(
twemoji.parse(emoji.unicode, {
attributes: () => ({
unicode: emoji.unicode,
shortcodes: emoji.shortcodes?.toString(),
hexcode: emoji.hexcode,
loading: 'lazy',
}),
base: TWEMOJI_BASE_URL,
})
)
) : (
// This is a custom emoji, and should be render as an mxc
<img
className="emoji"
draggable="false"
loading="lazy"
alt={emoji.shortcode}
unicode={`:${emoji.shortcode}:`}
shortcodes={emoji.shortcode}
src={initMatrix.matrixClient.mxcUrlToHttp(emoji.mxc)}
data-mx-emoticon={emoji.mxc}
/>
)}
</span>
);
}
emojiBoard.push(<div key={r} className="emoji-row">{emojiRow}</div>);
emojiBoard.push(
<div key={r} className="emoji-row">
{emojiRow}
</div>
);
}
return emojiBoard;
}
return (
<div className="emoji-group">
<Text className="emoji-group__header" variant="b2" weight="bold">{name}</Text>
<Text className="emoji-group__header" variant="b2" weight="bold">
{name}
</Text>
{groupEmojis.length !== 0 && <div className="emoji-set noselect">{getEmojiBoard()}</div>}
</div>
);
@@ -92,17 +97,16 @@ const EmojiGroup = React.memo(({ name, groupEmojis }) => {
EmojiGroup.propTypes = {
name: PropTypes.string.isRequired,
groupEmojis: PropTypes.arrayOf(PropTypes.shape({
length: PropTypes.number,
unicode: PropTypes.string,
hexcode: PropTypes.string,
mxc: PropTypes.string,
shortcode: PropTypes.string,
shortcodes: PropTypes.oneOfType([
PropTypes.string,
PropTypes.arrayOf(PropTypes.string),
]),
})).isRequired,
groupEmojis: PropTypes.arrayOf(
PropTypes.shape({
length: PropTypes.number,
unicode: PropTypes.string,
hexcode: PropTypes.string,
mxc: PropTypes.string,
shortcode: PropTypes.string,
shortcodes: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]),
})
).isRequired,
};
const asyncSearch = new AsyncSearch();
@@ -128,7 +132,13 @@ function SearchedEmoji() {
if (searchedEmojis === null) return false;
return <EmojiGroup key="-1" name={searchedEmojis.emojis.length === 0 ? 'No search result found' : 'Search results'} groupEmojis={searchedEmojis.emojis} />;
return (
<EmojiGroup
key="-1"
name={searchedEmojis.emojis.length === 0 ? 'No search result found' : 'Search results'}
groupEmojis={searchedEmojis.emojis}
/>
);
}
function EmojiBoard({ onSelect, searchRef }) {
@@ -141,10 +151,16 @@ function EmojiBoard({ onSelect, searchRef }) {
function getEmojiDataFromTarget(target) {
const unicode = target.getAttribute('unicode');
const hexcode = target.getAttribute('hexcode');
const mxc = target.getAttribute('data-mx-emoticon');
let shortcodes = target.getAttribute('shortcodes');
if (typeof shortcodes === 'undefined') shortcodes = undefined;
else shortcodes = shortcodes.split(',');
return { unicode, hexcode, shortcodes };
return {
unicode,
hexcode,
shortcodes,
mxc,
};
}
function selectEmoji(e) {
@@ -202,21 +218,22 @@ function EmojiBoard({ onSelect, searchRef }) {
setAvailableEmojis([]);
return;
}
// Retrieve the packs for the new room
// Remove packs that aren't marked as emoji packs
// Remove packs without emojis
const packs = getRelevantPacks(
initMatrix.matrixClient.getRoom(selectedRoomId),
)
.filter((pack) => pack.usage.indexOf('emoticon') !== -1)
.filter((pack) => pack.getEmojis().length !== 0);
// Set an index for each pack so that we know where to jump when the user uses the nav
for (let i = 0; i < packs.length; i += 1) {
packs[i].packIndex = i;
const mx = initMatrix.matrixClient;
const room = mx.getRoom(selectedRoomId);
const parentIds = initMatrix.roomList.getAllParentSpaces(room.roomId);
const parentRooms = [...parentIds].map((id) => mx.getRoom(id));
if (room) {
const packs = getRelevantPacks(room.client, [room, ...parentRooms]).filter(
(pack) => pack.getEmojis().length !== 0
);
// Set an index for each pack so that we know where to jump when the user uses the nav
for (let i = 0; i < packs.length; i += 1) {
packs[i].packIndex = i;
}
setAvailableEmojis(packs);
}
setAvailableEmojis(packs);
};
const onOpen = () => {
@@ -247,6 +264,55 @@ function EmojiBoard({ onSelect, searchRef }) {
return (
<div id="emoji-board" className="emoji-board">
<ScrollView invisible>
<div className="emoji-board__nav">
{recentEmojis.length > 0 && (
<IconButton
onClick={() => openGroup(0)}
src={RecentClockIC}
tooltip="Recent"
tooltipPlacement="left"
/>
)}
<div className="emoji-board__nav-custom">
{availableEmojis.map((pack) => {
const src = initMatrix.matrixClient.mxcUrlToHttp(
pack.avatarUrl ?? pack.getEmojis()[0].mxc
);
return (
<IconButton
onClick={() => openGroup(recentOffset + pack.packIndex)}
src={src}
key={pack.packIndex}
tooltip={pack.displayName ?? 'Unknown'}
tooltipPlacement="left"
isImage
/>
);
})}
</div>
<div className="emoji-board__nav-twemoji">
{[
[0, EmojiIC, 'Smilies'],
[1, DogIC, 'Animals'],
[2, CupIC, 'Food'],
[3, BallIC, 'Activities'],
[4, PhotoIC, 'Travel'],
[5, BulbIC, 'Objects'],
[6, PeaceIC, 'Symbols'],
[7, FlagIC, 'Flags'],
].map(([indx, ico, name]) => (
<IconButton
onClick={() => openGroup(recentOffset + availableEmojis.length + indx)}
key={indx}
src={ico}
tooltip={name}
tooltipPlacement="left"
/>
))}
</div>
</div>
</ScrollView>
<div className="emoji-board__content">
<div className="emoji-board__content__search">
<RawIcon size="small" src={SearchIC} />
@@ -256,81 +322,28 @@ function EmojiBoard({ onSelect, searchRef }) {
<ScrollView ref={scrollEmojisRef} autoHide>
<div onMouseMove={hoverEmoji} onClick={selectEmoji}>
<SearchedEmoji />
{recentEmojis.length > 0 && <EmojiGroup name="Recently used" groupEmojis={recentEmojis} />}
{
availableEmojis.map((pack) => (
<EmojiGroup
name={pack.displayName}
key={pack.packIndex}
groupEmojis={pack.getEmojis()}
className="custom-emoji-group"
/>
))
}
{
emojiGroups.map((group) => (
<EmojiGroup key={group.name} name={group.name} groupEmojis={group.emojis} />
))
}
{recentEmojis.length > 0 && (
<EmojiGroup name="Recently used" groupEmojis={recentEmojis} />
)}
{availableEmojis.map((pack) => (
<EmojiGroup
name={pack.displayName ?? 'Unknown'}
key={pack.packIndex}
groupEmojis={pack.getEmojis()}
className="custom-emoji-group"
/>
))}
{emojiGroups.map((group) => (
<EmojiGroup key={group.name} name={group.name} groupEmojis={group.emojis} />
))}
</div>
</ScrollView>
</div>
<div ref={emojiInfo} className="emoji-board__content__info">
<div>{ parse(twemoji.parse('🙂')) }</div>
<div>{parse(twemoji.parse('🙂', { base: TWEMOJI_BASE_URL }))}</div>
<Text>:slight_smile:</Text>
</div>
</div>
<ScrollView invisible>
<div className="emoji-board__nav">
{recentEmojis.length > 0 && (
<IconButton
onClick={() => openGroup(0)}
src={RecentClockIC}
tooltip="Recent"
tooltipPlacement="right"
/>
)}
<div className="emoji-board__nav-custom">
{
availableEmojis.map((pack) => {
const src = initMatrix.matrixClient.mxcUrlToHttp(pack.avatar ?? pack.images[0].mxc);
return (
<IconButton
onClick={() => openGroup(recentOffset + pack.packIndex)}
src={src}
key={pack.packIndex}
tooltip={pack.displayName}
tooltipPlacement="right"
isImage
/>
);
})
}
</div>
<div className="emoji-board__nav-twemoji">
{
[
[0, EmojiIC, 'Smilies'],
[1, DogIC, 'Animals'],
[2, CupIC, 'Food'],
[3, BallIC, 'Activities'],
[4, PhotoIC, 'Travel'],
[5, BulbIC, 'Objects'],
[6, PeaceIC, 'Symbols'],
[7, FlagIC, 'Flags'],
].map(([indx, ico, name]) => (
<IconButton
onClick={() => openGroup(recentOffset + availableEmojis.length + indx)}
key={indx}
src={ico}
tooltip={name}
tooltipPlacement="right"
/>
))
}
</div>
</div>
</ScrollView>
</div>
);
}
@@ -25,8 +25,7 @@
min-height: 100%;
padding: 4px 6px;
background-color: var(--bg-surface-low);
@include dir.side(border, 1px solid var(--bg-surface-border), none);
@include dir.side(border, none, 1px solid var(--bg-surface-border));
position: relative;
@@ -39,7 +38,7 @@
@extend .cp-fx__column;
}
&__nav-twemoji {
background: inherit;
background-color: var(--bg-surface);
position: sticky;
bottom: -70%;
z-index: 999;
@@ -84,6 +83,7 @@
.emoji {
width: 32px;
height: 32px;
object-fit: contain;
}
}
& > p:last-child {
@@ -121,8 +121,12 @@
@include dir.side(margin, var(--left-margin), var(--right-margin));
}
& .emoji {
width: 38px;
height: 38px;
max-width: 38px;
max-height: 38px;
width: 100%;
height: 100%;
overflow: hidden;
object-fit: contain;
padding: var(--emoji-padding);
cursor: pointer;
&:hover {
Loaded 100 of 168 files, more files were not shown because too many files have changed in this diff. Show more