Compare commits

...
Author SHA1 Message Date
ajbura 23de3aa4a3 add navigation atoms 2023-02-05 18:04:20 +05:30
ajbura c7e668eed2 Fix init muted room list atom 2023-02-05 18:04:02 +05:30
ajbura ddc9bdef70 Add bind atoms hook 2023-02-05 18:03:41 +05:30
Ajay Bura b08125f68e WIP 2023-02-05 09:45:58 +05:30
Ajay Bura 837d03a93b Add Sidebar components 2023-02-04 20:32:23 +05:30
Ajay Bura 9bd913e174 Extract set settings hook 2022-12-31 19:10:00 +05:30
Ajay Bura bc1e9abf3e Add settings hook 2022-12-31 19:02:57 +05:30
Ajay Bura 85e5bc887f Add settings atom 2022-12-31 19:02:43 +05:30
Ajay Bura 147a6065d0 Use hook to bind atoms with sdk 2022-12-31 15:54:57 +05:30
Ajay Bura 67cd2fc5c4 Add room to unread atom 2022-12-31 10:18:18 +05:30
Ajay Bura 899a5b934e Add mute list atom 2022-12-31 10:18:10 +05:30
Ajay Bura 4d802d918e Add room id to parents atom 2022-12-27 20:17:04 +05:30
Ajay Bura a9937cb4ba add utils for jotai atoms 2022-12-27 20:16:49 +05:30
Ajay Bura 08070d41c5 add room list atom 2022-12-27 20:16:20 +05:30
Ajay Bura 6b559404b2 Add invite list atom 2022-12-27 20:16:13 +05:30
Ajay Bura 582250c419 Add mDirect list atom 2022-12-27 20:15:52 +05:30
Ajay Bura 56a134c85c Add room utils 2022-12-27 20:15:17 +05:30
Ajay Bura 1c7600c3b8 Add disposable util 2022-12-27 20:14:08 +05:30
Ajay Bura 5b41794947 Add new types 2022-12-27 20:13:49 +05:30
Ajay Bura 3cf603bfc6 Add function to access matrix client 2022-12-27 20:12:49 +05:30
Ajay Bura 0a3fe685d1 change cross-signing alert anim to 30 iteration 2022-12-27 20:11:40 +05:30
Ajay Bura 116bf7d2f0 Enable immer map/set 2022-12-27 20:10:43 +05:30
Ajay Bura cf1a02a7b3 install folds, jotai & immer 2022-12-27 20:09:30 +05:30
Ajay Bura 0714685b9b Enable ts strict mode 2022-12-27 20:09:01 +05:30
Ajay Bura 2ef8fdb1c9 Fix eslint 2022-12-27 20:07:36 +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
169 changed files with 8425 additions and 22782 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
+35 -2
View File
@@ -4,25 +4,58 @@ 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,
"no-shadow": "off",
"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",
"@typescript-eslint/no-shadow": "error"
},
};
+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.4.1
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.1.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.4.1
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
+44 -42
View File
@@ -1,24 +1,39 @@
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.4.1
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/*/}
@@ -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.4.1
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.1.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.23.1-alpine
FROM nginx:1.23.3-alpine
COPY --from=builder /src/dist /app
+1 -1
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
+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>
+1 -1
View File
@@ -1,9 +1,9 @@
{
"defaultHomeserver": 3,
"homeserverList": [
"converser.eu",
"envs.net",
"halogen.city",
"kde.org",
"matrix.org",
"mozilla.org"
],
+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="./public/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.
+1906 -21416
View File
File diff suppressed because it is too large. Load diff
+64 -72
View File
@@ -1,88 +1,80 @@
{
"name": "cinny",
"version": "2.0.4",
"version": "2.2.2",
"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": "^3.0.1",
"katex": "^0.16.0",
"linkify-html": "^4.0.0-beta.5",
"linkifyjs": "^4.0.0-beta.5",
"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.1",
"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",
"@matrix-org/olm": "3.2.14",
"@tippyjs/react": "4.2.6",
"@vanilla-extract/css": "1.9.3",
"@vanilla-extract/recipes": "0.3.0",
"@vanilla-extract/vite-plugin": "3.7.1",
"blurhash": "2.0.4",
"browser-encrypt-attachment": "0.3.0",
"classnames": "2.3.2",
"dateformat": "5.0.3",
"emojibase-data": "7.0.1",
"file-saver": "2.0.5",
"flux": "4.0.3",
"focus-trap-react": "10.0.2",
"folds": "1.0.4",
"formik": "2.2.9",
"html-react-parser": "3.0.4",
"immer": "9.0.16",
"jotai": "1.12.0",
"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-modal": "3.16.1",
"sanitize-html": "2.8.0",
"tippy.js": "6.3.7",
"twemoji": "14.0.2"
},
"devDependencies": {
"@babel/core": "^7.18.10",
"@babel/preset-env": "^7.18.10",
"@babel/preset-react": "^7.18.6",
"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.21.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-jsx-a11y": "^6.6.1",
"eslint-plugin-react": "^7.30.1",
"eslint-plugin-react-hooks": "^4.6.0",
"favicons": "^6.2.2",
"favicons-webpack-plugin": "^5.0.2",
"html-loader": "^4.1.0",
"html-webpack-plugin": "^5.3.1",
"mini-css-extract-plugin": "^2.6.1",
"path-browserify": "^1.0.1",
"sass": "^1.54.1",
"sass-loader": "^13.0.2",
"stream-browserify": "^3.0.0",
"style-loader": "^3.3.1",
"url": "^0.11.0",
"util": "^0.12.4",
"webpack": "^5.74.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.9.3",
"webpack-merge": "^5.7.3"
"@rollup/plugin-wasm": "6.1.1",
"@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",
"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",
"prettier": "2.8.1",
"sass": "1.56.2",
"typescript": "4.9.4",
"vite": "4.0.4",
"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>
+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="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

+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
View File
@@ -1,5 +1,6 @@
import React, { useEffect, useRef } from 'react';
import PropTypes from 'prop-types';
import './Math.scss';
import katex from 'katex';
import 'katex/dist/katex.min.css';
+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;
}
}
+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;
+111
View File
@@ -0,0 +1,111 @@
import { style } from '@vanilla-extract/css';
import { recipe, RecipeVariants } from '@vanilla-extract/recipes';
import { color, config, DefaultReset, toRem } from 'folds';
export const Sidebar = style([
DefaultReset,
{
width: toRem(66),
backgroundColor: color.Background.Container,
borderRight: `${config.borderWidth.B300} solid ${color.Background.ContainerLine}`,
display: 'flex',
flexDirection: 'column',
color: color.Background.OnContainer,
},
]);
export const SidebarStack = style([
DefaultReset,
{
width: '100%',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
gap: config.space.S300,
padding: `${config.space.S300} 0`,
},
]);
const PUSH_X = 2;
export const SidebarAvatarBox = recipe({
base: [
DefaultReset,
{
display: 'flex',
alignItems: 'center',
position: 'relative',
transition: 'transform 200ms cubic-bezier(0, 0.8, 0.67, 0.97)',
selectors: {
'&:hover': {
transform: `translateX(${toRem(PUSH_X)})`,
},
'&::before': {
content: '',
display: 'none',
position: 'absolute',
left: toRem(-11.5 - PUSH_X),
width: toRem(3 + PUSH_X),
height: toRem(16),
borderRadius: `0 ${toRem(4)} ${toRem(4)} 0`,
background: 'CurrentColor',
transition: 'height 200ms linear',
},
'&:hover::before': {
display: 'block',
width: toRem(3),
},
},
},
],
variants: {
active: {
true: {
selectors: {
'&::before': {
display: 'block',
height: toRem(24),
},
'&:hover::before': {
width: toRem(3 + PUSH_X),
},
},
},
},
},
});
export type SidebarAvatarBoxVariants = RecipeVariants<typeof SidebarAvatarBox>;
export const SidebarBadgeBox = recipe({
base: [
DefaultReset,
{
position: 'absolute',
zIndex: 1,
},
],
variants: {
hasCount: {
true: {
top: toRem(-6),
right: toRem(-6),
},
false: {
top: toRem(-2),
right: toRem(-2),
},
},
},
defaultVariants: {
hasCount: false,
},
});
export type SidebarBadgeBoxVariants = RecipeVariants<typeof SidebarBadgeBox>;
export const SidebarBadgeOutline = style({
boxShadow: `0 0 0 ${config.borderWidth.B500} ${color.Background.Container}`,
});
+8
View File
@@ -0,0 +1,8 @@
import classNames from 'classnames';
import { as } from 'folds';
import React from 'react';
import * as css from './Sidebar.css';
export const Sidebar = as<'div'>(({ as: AsSidebar = 'div', className, ...props }, ref) => (
<AsSidebar className={classNames(css.Sidebar, className)} {...props} ref={ref} />
));
@@ -0,0 +1,75 @@
import classNames from 'classnames';
import { as, Avatar, Box, color, config, Text, Tooltip, TooltipProvider } from 'folds';
import React, { forwardRef, MouseEventHandler, ReactNode } from 'react';
import * as css from './Sidebar.css';
const SidebarAvatarBox = as<'div', css.SidebarAvatarBoxVariants>(
({ as: AsSidebarAvatarBox = 'div', className, active, ...props }, ref) => (
<AsSidebarAvatarBox
className={classNames(css.SidebarAvatarBox({ active }), className)}
{...props}
ref={ref}
/>
)
);
export const SidebarAvatar = forwardRef<
HTMLDivElement,
css.SidebarAvatarBoxVariants &
css.SidebarBadgeBoxVariants & {
outlined?: boolean;
avatarChildren: ReactNode;
tooltip: ReactNode | string;
notificationBadge?: (badgeClassName: string) => ReactNode;
onClick?: MouseEventHandler<HTMLButtonElement>;
onContextMenu?: MouseEventHandler<HTMLButtonElement>;
}
>(
(
{
active,
hasCount,
outlined,
avatarChildren,
tooltip,
notificationBadge,
onClick,
onContextMenu,
},
ref
) => (
<SidebarAvatarBox active={active} ref={ref}>
<TooltipProvider
delay={0}
position="right"
tooltip={
<Tooltip>
<Text size="T300">{tooltip}</Text>
</Tooltip>
}
>
{(avRef) => (
<Avatar
ref={avRef}
as="button"
onClick={onClick}
onContextMenu={onContextMenu}
style={{
border: outlined
? `${config.borderWidth.B300} solid ${color.Background.ContainerLine}`
: undefined,
cursor: 'pointer',
}}
>
{avatarChildren}
</Avatar>
)}
</TooltipProvider>
{notificationBadge && (
<Box className={css.SidebarBadgeBox({ hasCount })}>
{notificationBadge(css.SidebarBadgeOutline)}
</Box>
)}
</SidebarAvatarBox>
)
);
@@ -0,0 +1,21 @@
import React, { ReactNode } from 'react';
import { Box, Scroll } from 'folds';
type SidebarContentProps = {
scrollable: ReactNode;
sticky: ReactNode;
};
export function SidebarContent({ scrollable, sticky }: SidebarContentProps) {
return (
<>
<Box direction="Column" grow="Yes">
<Scroll variant="Background" size="0">
{scrollable}
</Scroll>
</Box>
<Box direction="Column" shrink="No">
{sticky}
</Box>
</>
);
}
@@ -0,0 +1,10 @@
import React from 'react';
import classNames from 'classnames';
import { as } from 'folds';
import * as css from './Sidebar.css';
export const SidebarStack = as<'div'>(
({ as: AsSidebarStack = 'div', className, ...props }, ref) => (
<AsSidebarStack className={classNames(css.SidebarStack, className)} {...props} ref={ref} />
)
);
@@ -0,0 +1,13 @@
import React from 'react';
import { Line, toRem } from 'folds';
export function SidebarStackSeparator() {
return (
<Line
role="separator"
style={{ width: toRem(24), margin: '0 auto' }}
variant="Background"
size="300"
/>
);
}
+5
View File
@@ -0,0 +1,5 @@
export * from './Sidebar';
export * from './SidebarAvatar';
export * from './SidebarContent';
export * from './SidebarStack';
export * from './SidebarStackSeparator';
+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;
}
@@ -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;
+13 -3
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>
@@ -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;
+110 -63
View File
@@ -4,50 +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/cd15e08fc285da42134817cce50de8011809cd53/src/utils/blobs.ts#L73
const ALLOWED_BLOB_MIMETYPES = [
'image/jpeg',
'image/gif',
'image/png',
'image/apng',
'image/webp',
'image/avif',
'video/mp4',
'video/webm',
'video/ogg',
'video/quicktime',
'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';
}
// Required for Chromium browsers
if (mimetype === 'video/quicktime') {
return 'video/mp4';
}
return mimetype;
}
import { getBlobSafeMimeType } from '../../../util/mimetypes';
async function getDecryptedBlob(response, type, decryptData) {
const arrayBuffer = await response.arrayBuffer();
@@ -69,9 +36,8 @@ 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;
}
@@ -155,7 +121,82 @@ File.propTypes = {
};
function Image({
name, width, height, link, file, type,
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);
@@ -173,21 +214,18 @@ 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, 128) : '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,
@@ -240,12 +278,13 @@ 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;
@@ -260,16 +299,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">
@@ -277,14 +316,20 @@ 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>
@@ -298,22 +343,24 @@ 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,
File, Image, Sticker, Audio, Video,
};
+29 -5
View File
@@ -27,6 +27,15 @@
white-space: initial;
}
.sticker-container {
display: inline-flex;
max-width: 128px;
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%;
}
}
}
+107 -49
View File
@@ -5,11 +5,12 @@ import 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';
@@ -25,6 +26,7 @@ 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 Time from '../../atoms/time/Time';
import ContextMenu, { MenuHeader, MenuItem, MenuBorder } from '../../atoms/context-menu/ContextMenu';
import * as Media from '../media/Media';
@@ -37,6 +39,8 @@ import CmdIC from '../../../../public/res/ic/outlined/cmd.svg';
import BinIC from '../../../../public/res/ic/outlined/bin.svg';
import { confirmDialog } from '../confirm-dialog/ConfirmDialog';
import { getBlobSafeMimeType } from '../../../util/mimetypes';
import { html, plain } from '../../../util/markdown';
function PlaceholderMessage() {
return (
@@ -68,7 +72,7 @@ const MessageAvatar = React.memo(({
));
const MessageHeader = React.memo(({
userId, username, time,
userId, username, timestamp, fullTime,
}) => (
<div className="message__header">
<Text
@@ -82,14 +86,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 }) {
@@ -200,7 +210,13 @@ const MessageBody = React.memo(({
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);
@@ -235,12 +251,12 @@ 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'}`}>
<div dir="auto" className={`text ${emojiOnly ? 'text-h1' : 'text-b1'}`}>
{ msgType === 'm.emote' && (
<>
{'* '}
@@ -277,14 +293,19 @@ function MessageEdit({ body, onSave, onCancel }) {
}, []);
const handleKeyDown = (e) => {
if (e.key === 'Escape') {
e.preventDefault();
onCancel();
}
if (e.key === 'Enter' && e.shiftKey === false) {
e.preventDefault();
onSave(editInputRef.current.value);
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}
@@ -322,7 +343,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,17 +351,17 @@ 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) => (
@@ -354,24 +375,22 @@ function genReactionMsg(userIds, reaction) {
</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,
reaction, shortcode, count, users, isActive, onClick,
}) {
const customEmojiMatch = reaction.match(/^:(\S+):$/);
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}
@@ -380,7 +399,7 @@ function MessageReaction({
>
{
customEmojiUrl
? <img className="react-emoji" draggable="false" alt={reaction} src={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>
@@ -388,9 +407,12 @@ function MessageReaction({
</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 +423,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 +435,7 @@ function MessageReactionGroup({ roomTimeline, mEvent }) {
isActive: false,
};
}
if (shortcode) reaction.shortcode = shortcode;
if (count) {
reaction.count = count;
} else {
@@ -429,9 +451,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,7 +462,7 @@ 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);
});
}
@@ -449,13 +472,13 @@ function MessageReactionGroup({ roomTimeline, mEvent }) {
Object.keys(reactions).map((key) => (
<MessageReaction
key={key}
shortcodeToEmoji={shortcodeToEmoji}
reaction={key}
shortcode={reactions[key].shortcode}
count={reactions[key].count}
users={reactions[key].users}
isActive={reactions[key].isActive}
onClick={() => {
toggleEmoji(roomId, mEvent.getId(), key, roomTimeline);
toggleEmoji(roomId, mEvent.getId(), key, reactions[key].shortcode, roomTimeline);
}}
/>
))
@@ -607,7 +630,14 @@ function genMediaContent(mE) {
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 +658,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 +696,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,9 +717,9 @@ 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 ?? {};
@@ -689,36 +732,37 @@ function Message({
let { body } = content;
const username = mEvent.sender ? getUsernameOfRoomMember(mEvent.sender) : getUsername(senderId);
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(' ')}>
{
@@ -735,7 +779,12 @@ function Message({
}
<div className="message__main-container">
{!isBodyOnly && (
<MessageHeader userId={senderId} username={username} time={time} />
<MessageHeader
userId={senderId}
username={username}
timestamp={mEvent.getTs()}
fullTime={fullTime}
/>
)}
{roomTimeline && isReply && (
<MessageReplyWrapper
@@ -743,7 +792,7 @@ function Message({
eventId={mEvent.replyEventId}
/>
)}
{!isEditing && (
{!isEdit && (
<MessageBody
senderName={username}
isCustomHTML={isCustomHTML}
@@ -752,22 +801,24 @@ 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 && (
{roomTimeline && !isEdit && (
<MessageOptions
roomTimeline={roomTimeline}
mEvent={mEvent}
@@ -783,13 +834,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 };
+34 -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);
@@ -425,7 +440,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 +449,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,130 @@
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 myPowerlevel = room.getMember(mx.getUserId())?.powerLevel || 0;
const canChange = room.currentState.hasSufficientPowerLevelFor('state_default', myPowerlevel);
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;
}
}
+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>
@@ -38,10 +38,10 @@ function SpaceOptions({ roomId, afterOptionSelect }) {
const handleMarkAsRead = () => {
const spaceChildren = roomList.getCategorizedSpaces([roomId]);
spaceChildren?.forEach((childIds, spaceId) => {
spaceChildren?.forEach((childIds) => {
childIds?.forEach((childId) => {
markAsRead(childId);
})
});
});
afterOptionSelect();
};
+59 -53
View File
@@ -70,7 +70,7 @@ const EmojiGroup = React.memo(({ name, groupEmojis }) => {
unicode={`:${emoji.shortcode}:`}
shortcodes={emoji.shortcode}
src={initMatrix.matrixClient.mxcUrlToHttp(emoji.mxc)}
data-mx-emoticon
data-mx-emoticon={emoji.mxc}
/>
)
}
@@ -141,10 +141,13 @@ 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 +205,23 @@ 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,39 +252,6 @@ function EmojiBoard({ onSelect, searchRef }) {
return (
<div id="emoji-board" className="emoji-board">
<div className="emoji-board__content">
<div className="emoji-board__content__search">
<RawIcon size="small" src={SearchIC} />
<Input onChange={handleSearchChange} forwardRef={searchRef} placeholder="Search" />
</div>
<div className="emoji-board__content__emojis">
<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} />
))
}
</div>
</ScrollView>
</div>
<div ref={emojiInfo} className="emoji-board__content__info">
<div>{ parse(twemoji.parse('🙂')) }</div>
<Text>:slight_smile:</Text>
</div>
</div>
<ScrollView invisible>
<div className="emoji-board__nav">
{recentEmojis.length > 0 && (
@@ -287,20 +259,21 @@ function EmojiBoard({ onSelect, searchRef }) {
onClick={() => openGroup(0)}
src={RecentClockIC}
tooltip="Recent"
tooltipPlacement="right"
tooltipPlacement="left"
/>
)}
<div className="emoji-board__nav-custom">
{
availableEmojis.map((pack) => {
const src = initMatrix.matrixClient.mxcUrlToHttp(pack.avatar ?? pack.images[0].mxc);
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}
tooltipPlacement="right"
tooltip={pack.displayName ?? 'Unknown'}
tooltipPlacement="left"
isImage
/>
);
@@ -324,13 +297,46 @@ function EmojiBoard({ onSelect, searchRef }) {
key={indx}
src={ico}
tooltip={name}
tooltipPlacement="right"
tooltipPlacement="left"
/>
))
}
</div>
</div>
</ScrollView>
<div className="emoji-board__content">
<div className="emoji-board__content__search">
<RawIcon size="small" src={SearchIC} />
<Input onChange={handleSearchChange} forwardRef={searchRef} placeholder="Search" />
</div>
<div className="emoji-board__content__emojis">
<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 ?? '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>
<Text>:slight_smile:</Text>
</div>
</div>
</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 {
+184 -102
View File
@@ -1,135 +1,224 @@
import { emojis } from './emoji';
// Custom emoji are stored in one of three places:
// - User emojis, which are stored in account data
// - Room emojis, which are stored in state events in a room
// - Emoji packs, which are rooms of emojis referenced in the account data or in a room's
// cannonical space
//
// Emojis and packs referenced from within a user's account data should be available
// globally, while emojis and packs in rooms and spaces should only be available within
// those spaces and rooms
// https://github.com/Sorunome/matrix-doc/blob/soru/emotes/proposals/2545-emotes.md
class ImagePack {
// Convert a raw image pack into a more maliable format
//
// Takes an image pack as per MSC 2545 (e.g. as in the Matrix spec), and converts it to a
// format used here, while filling in defaults.
//
// The room argument is the room the pack exists in, which is used as a fallback for
// missing properties
//
// Returns `null` if the rawPack is not a properly formatted image pack, although there
// is still a fair amount of tolerance for malformed packs.
static parsePack(rawPack, room) {
if (typeof rawPack.images === 'undefined') {
static parsePack(eventId, packContent) {
if (!eventId || typeof packContent?.images !== 'object') {
return null;
}
const pack = rawPack.pack ?? {};
return new ImagePack(eventId, packContent);
}
const displayName = pack.display_name ?? (room ? room.name : undefined);
const avatar = pack.avatar_url ?? (room ? room.getMxcAvatarUrl() : undefined);
const usage = pack.usage ?? ['emoticon', 'sticker'];
const { attribution } = pack;
const images = Object.entries(rawPack.images).flatMap((e) => {
const data = e[1];
const shortcode = e[0];
constructor(eventId, content) {
this.id = eventId;
this.content = JSON.parse(JSON.stringify(content));
this.applyPack(content);
this.applyImages(content);
}
applyPack(content) {
const pack = content.pack ?? {};
this.displayName = pack.display_name;
this.avatarUrl = pack.avatar_url;
this.usage = pack.usage ?? ['emoticon', 'sticker'];
this.attribution = pack.attribution;
}
applyImages(content) {
this.images = new Map();
this.emoticons = [];
this.stickers = [];
Object.entries(content.images).forEach(([shortcode, data]) => {
const mxc = data.url;
const body = data.body ?? shortcode;
const usage = data.usage ?? this.usage;
const { info } = data;
const usage_ = data.usage ?? usage;
if (mxc) {
return [{
shortcode, mxc, body, info, usage: usage_,
}];
if (!mxc) return;
const image = {
shortcode, mxc, body, usage, info,
};
this.images.set(shortcode, image);
if (usage.includes('emoticon')) {
this.emoticons.push(image);
}
if (usage.includes('sticker')) {
this.stickers.push(image);
}
return [];
});
return new ImagePack(displayName, avatar, usage, attribution, images);
}
constructor(displayName, avatar, usage, attribution, images) {
this.displayName = displayName;
this.avatar = avatar;
this.usage = usage;
this.attribution = attribution;
this.images = images;
getImages() {
return this.images;
}
// Produce a list of emoji in this image pack
getEmojis() {
return this.images.filter((i) => i.usage.indexOf('emoticon') !== -1);
return this.emoticons;
}
// Produce a list of stickers in this image pack
getStickers() {
return this.images.filter((i) => i.usage.indexOf('sticker') !== -1);
return this.stickers;
}
getContent() {
return this.content;
}
_updatePackProperty(property, value) {
if (this.content.pack === undefined) {
this.content.pack = {};
}
this.content.pack[property] = value;
this.applyPack(this.content);
}
setAvatarUrl(avatarUrl) {
this._updatePackProperty('avatar_url', avatarUrl);
}
setDisplayName(displayName) {
this._updatePackProperty('display_name', displayName);
}
setAttribution(attribution) {
this._updatePackProperty('attribution', attribution);
}
setUsage(usage) {
this._updatePackProperty('usage', usage);
}
addImage(key, imgContent) {
this.content.images = {
[key]: imgContent,
...this.content.images,
};
this.applyImages(this.content);
}
removeImage(key) {
if (this.content.images[key] === undefined) return;
delete this.content.images[key];
this.applyImages(this.content);
}
updateImageKey(key, newKey) {
if (this.content.images[key] === undefined) return;
const copyImages = {};
Object.keys(this.content.images).forEach((imgKey) => {
copyImages[imgKey === key ? newKey : imgKey] = this.content.images[imgKey];
});
this.content.images = copyImages;
this.applyImages(this.content);
}
_updateImageProperty(key, property, value) {
if (this.content.images[key] === undefined) return;
this.content.images[key][property] = value;
this.applyImages(this.content);
}
setImageUrl(key, url) {
this._updateImageProperty(key, 'url', url);
}
setImageBody(key, body) {
this._updateImageProperty(key, 'body', body);
}
setImageInfo(key, info) {
this._updateImageProperty(key, 'info', info);
}
setImageUsage(key, usage) {
this._updateImageProperty(key, 'usage', usage);
}
}
// Retrieve a list of user emojis
//
// Result is an ImagePack, or null if the user hasn't set up or has deleted their personal
// image pack.
//
// Accepts a reference to a matrix client as the only argument
function getGlobalImagePacks(mx) {
const globalContent = mx.getAccountData('im.ponies.emote_rooms')?.getContent();
if (typeof globalContent !== 'object') return [];
const { rooms } = globalContent;
if (typeof rooms !== 'object') return [];
const roomIds = Object.keys(rooms);
const packs = roomIds.flatMap((roomId) => {
if (typeof rooms[roomId] !== 'object') return [];
const room = mx.getRoom(roomId);
if (!room) return [];
const stateKeys = Object.keys(rooms[roomId]);
return stateKeys.map((stateKey) => {
const data = room.currentState.getStateEvents('im.ponies.room_emotes', stateKey);
const pack = ImagePack.parsePack(data?.getId(), data?.getContent());
if (pack) {
pack.displayName ??= room.name;
pack.avatarUrl ??= room.getMxcAvatarUrl();
}
return pack;
}).filter((pack) => pack !== null);
});
return packs;
}
function getUserImagePack(mx) {
const accountDataEmoji = mx.getAccountData('im.ponies.user_emotes');
if (!accountDataEmoji) {
return null;
}
const userImagePack = ImagePack.parsePack(accountDataEmoji.event.content);
if (userImagePack) userImagePack.displayName ??= 'Your Emoji';
const userImagePack = ImagePack.parsePack(mx.getUserId(), accountDataEmoji.event.content);
if (userImagePack) userImagePack.displayName ??= 'Personal Emoji';
return userImagePack;
}
// Produces a list of all of the emoji packs in a room
//
// Returns a list of `ImagePack`s. This does not include packs in spaces that contain
// this room.
function getPacksInRoom(room) {
const packs = room.currentState.getStateEvents('im.ponies.room_emotes');
function getRoomImagePacks(room) {
const dataEvents = room.currentState.getStateEvents('im.ponies.room_emotes');
return packs
.map((p) => ImagePack.parsePack(p.event.content, room))
.filter((p) => p !== null);
return dataEvents
.map((data) => {
const pack = ImagePack.parsePack(data?.getId(), data?.getContent());
if (pack) {
pack.displayName ??= room.name;
pack.avatarUrl ??= room.getMxcAvatarUrl();
}
return pack;
})
.filter((pack) => pack !== null);
}
// Produce a list of all image packs which should be shown for a given room
//
// This includes packs in that room, the user's personal images, and will eventually
// include the user's enabled global image packs and space-level packs.
//
// This differs from getPacksInRoom, as the former only returns packs that are directly in
// a room, whereas this function returns all packs which should be shown to the user while
// they are in this room.
//
// Packs will be returned in the order that shortcode conflicts should be resolved, with
// higher priority packs coming first.
function getRelevantPacks(room) {
/**
* @param {MatrixClient} mx Provide if you want to include user personal/global pack
* @param {Room[]} rooms Provide rooms if you want to include rooms pack
* @returns {ImagePack[]} packs
*/
function getRelevantPacks(mx, rooms) {
const userPack = mx ? getUserImagePack(mx) : [];
const globalPacks = mx ? getGlobalImagePacks(mx) : [];
const globalPackIds = new Set(globalPacks.map((pack) => pack.id));
const roomsPack = rooms?.flatMap(getRoomImagePacks) ?? [];
return [].concat(
getUserImagePack(room.client) ?? [],
getPacksInRoom(room),
userPack ?? [],
globalPacks,
roomsPack.filter((pack) => !globalPackIds.has(pack.id)),
);
}
// Returns all user+room emojis and all standard unicode emojis
//
// Accepts a reference to a matrix client as the only argument
//
// Result is a map from shortcode to the corresponding emoji. If two emoji share a
// shortcode, only one will be presented, with priority given to custom emoji.
//
// Will eventually be expanded to include all emojis revelant to a room and the user
function getShortcodeToEmoji(room) {
function getShortcodeToEmoji(mx, rooms) {
const allEmoji = new Map();
emojis.forEach((emoji) => {
if (emoji.shortcodes.constructor.name === 'Array') {
if (Array.isArray(emoji.shortcodes)) {
emoji.shortcodes.forEach((shortcode) => {
allEmoji.set(shortcode, emoji);
});
@@ -138,7 +227,7 @@ function getShortcodeToEmoji(room) {
}
});
getRelevantPacks(room).reverse()
getRelevantPacks(mx, rooms)
.flatMap((pack) => pack.getEmojis())
.forEach((emoji) => {
allEmoji.set(emoji.shortcode, emoji);
@@ -150,7 +239,7 @@ function getShortcodeToEmoji(room) {
function getShortcodeToCustomEmoji(room) {
const allEmoji = new Map();
getRelevantPacks(room).reverse()
getRelevantPacks(room.client, [room])
.flatMap((pack) => pack.getEmojis())
.forEach((emoji) => {
allEmoji.set(emoji.shortcode, emoji);
@@ -159,27 +248,20 @@ function getShortcodeToCustomEmoji(room) {
return allEmoji;
}
// Produces a special list of emoji specifically for auto-completion
//
// This list contains each emoji once, with all emoji being deduplicated by shortcode.
// However, the order of the standard emoji will have been preserved, and alternate
// shortcodes for the standard emoji will not be considered.
//
// Standard emoji are guaranteed to be earlier in the list than custom emoji
function getEmojiForCompletion(room) {
function getEmojiForCompletion(mx, rooms) {
const allEmoji = new Map();
getRelevantPacks(room).reverse()
getRelevantPacks(mx, rooms)
.flatMap((pack) => pack.getEmojis())
.forEach((emoji) => {
allEmoji.set(emoji.shortcode, emoji);
});
return emojis.filter((e) => !allEmoji.has(e.shortcode))
.concat(Array.from(allEmoji.values()));
return Array.from(allEmoji.values()).concat(emojis.filter((e) => !allEmoji.has(e.shortcode)));
}
export {
getUserImagePack,
ImagePack,
getUserImagePack, getGlobalImagePacks, getRoomImagePacks,
getShortcodeToEmoji, getShortcodeToCustomEmoji,
getRelevantPacks, getEmojiForCompletion,
};
+2 -2
View File
@@ -6,7 +6,7 @@ import initMatrix from '../../../client/initMatrix';
import cons from '../../../client/state/cons';
import navigation from '../../../client/state/navigation';
import { join } from '../../../client/action/room';
import { selectRoom, selectSpace } from '../../../client/action/navigation';
import { selectRoom, selectTab } from '../../../client/action/navigation';
import Text from '../../atoms/text/Text';
import IconButton from '../../atoms/button/IconButton';
@@ -32,7 +32,7 @@ function JoinAliasContent({ term, requestClose }) {
const openRoom = (roomId) => {
const room = mx.getRoom(roomId);
if (!room) return;
if (room.isSpaceRoom()) selectSpace(roomId);
if (room.isSpaceRoom()) selectTab(roomId);
else selectRoom(roomId);
requestClose();
};
+3 -1
View File
@@ -56,7 +56,9 @@ function Drawer() {
useEffect(() => {
requestAnimationFrame(() => {
scrollRef.current.scrollTop = 0;
if (scrollRef.current) {
scrollRef.current.scrollTop = 0;
}
});
}, [selectedTab]);
@@ -6,7 +6,7 @@ import { twemojify } from '../../../util/twemojify';
import initMatrix from '../../../client/initMatrix';
import cons from '../../../client/state/cons';
import { selectSpace } from '../../../client/action/navigation';
import { selectTab, selectSpace } from '../../../client/action/navigation';
import navigation from '../../../client/state/navigation';
import { abbreviateNumber } from '../../../util/common';
@@ -21,7 +21,7 @@ import ChevronRightIC from '../../../../public/res/ic/outlined/chevron-right.svg
function DrawerBreadcrumb({ spaceId }) {
const [, forceUpdate] = useState({});
const scrollRef = useRef(null);
const { roomList, notifications } = initMatrix;
const { roomList, notifications, accountData } = initMatrix;
const mx = initMatrix.matrixClient;
const spacePath = navigation.selectedSpacePath;
@@ -49,9 +49,9 @@ function DrawerBreadcrumb({ spaceId }) {
}, [spaceId]);
function getHomeNotiExcept(childId) {
const orphans = roomList.getOrphans();
const childIndex = orphans.indexOf(childId);
if (childId !== -1) orphans.splice(childIndex, 1);
const orphans = roomList.getOrphans()
.filter((id) => (id !== childId))
.filter((id) => !accountData.spaceShortcut.has(id));
let noti = null;
@@ -107,7 +107,10 @@ function DrawerBreadcrumb({ spaceId }) {
{ index !== 0 && <RawIcon size="extra-small" src={ChevronRightIC} />}
<Button
className={index === spacePath.length - 1 ? 'drawer-breadcrumb__btn--selected' : ''}
onClick={() => selectSpace(id)}
onClick={() => {
if (id === cons.tabs.HOME) selectTab(id);
else selectSpace(id);
}}
>
<Text variant="b2">{id === cons.tabs.HOME ? 'Home' : twemojify(mx.getRoom(id).name)}</Text>
{ noti !== null && (
@@ -57,7 +57,7 @@ export function HomeSpaceOptions({ spaceId, afterOptionSelect }) {
iconSrc={HashGlobeIC}
onClick={() => { afterOptionSelect(); openPublicRooms(); }}
>
Join public room
Explore public rooms
</MenuItem>
)}
{ !spaceId && (
Loaded 100 of 169 files, more files were not shown because too many files have changed in this diff. Show more