Merge branch 'dev' into dev
This commit is contained in:
commit
192c1bdb63
24 changed files with 364 additions and 270 deletions
2
.github/workflows/docker-pr.yml
vendored
2
.github/workflows/docker-pr.yml
vendored
|
@ -15,7 +15,7 @@ jobs:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v3.0.2
|
uses: actions/checkout@v3.0.2
|
||||||
- name: Build Docker image
|
- name: Build Docker image
|
||||||
uses: docker/build-push-action@v3.1.0
|
uses: docker/build-push-action@v3.1.1
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
push: false
|
push: false
|
||||||
|
|
2
.github/workflows/prod-deploy.yml
vendored
2
.github/workflows/prod-deploy.yml
vendored
|
@ -86,7 +86,7 @@ jobs:
|
||||||
with:
|
with:
|
||||||
images: ajbura/cinny
|
images: ajbura/cinny
|
||||||
- name: Build and push Docker image
|
- name: Build and push Docker image
|
||||||
uses: docker/build-push-action@v3.1.0
|
uses: docker/build-push-action@v3.1.1
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
|
|
BIN
olm.wasm
Normal file → Executable file
BIN
olm.wasm
Normal file → Executable file
Binary file not shown.
133
package-lock.json
generated
133
package-lock.json
generated
|
@ -1,18 +1,18 @@
|
||||||
{
|
{
|
||||||
"name": "cinny",
|
"name": "cinny",
|
||||||
"version": "2.0.4",
|
"version": "2.1.2",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "cinny",
|
"name": "cinny",
|
||||||
"version": "2.0.4",
|
"version": "2.1.2",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@alienfast/i18next-loader": "^1.1.4",
|
"@alienfast/i18next-loader": "^1.1.4",
|
||||||
"@fontsource/inter": "^4.5.11",
|
"@fontsource/inter": "^4.5.12",
|
||||||
"@fontsource/roboto": "^4.5.7",
|
"@fontsource/roboto": "^4.5.8",
|
||||||
"@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.8.tgz",
|
"@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.12.tgz",
|
||||||
"@tippyjs/react": "^4.2.6",
|
"@tippyjs/react": "^4.2.6",
|
||||||
"babel-polyfill": "^6.26.0",
|
"babel-polyfill": "^6.26.0",
|
||||||
"blurhash": "^1.1.5",
|
"blurhash": "^1.1.5",
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
"katex": "^0.16.0",
|
"katex": "^0.16.0",
|
||||||
"linkify-html": "^4.0.0-beta.5",
|
"linkify-html": "^4.0.0-beta.5",
|
||||||
"linkifyjs": "^4.0.0-beta.5",
|
"linkifyjs": "^4.0.0-beta.5",
|
||||||
"matrix-js-sdk": "^18.1.0",
|
"matrix-js-sdk": "^19.2.0",
|
||||||
"micromark": "^3.0.10",
|
"micromark": "^3.0.10",
|
||||||
"micromark-extension-gfm": "^2.0.1",
|
"micromark-extension-gfm": "^2.0.1",
|
||||||
"micromark-extension-math": "^2.0.2",
|
"micromark-extension-math": "^2.0.2",
|
||||||
|
@ -75,7 +75,7 @@
|
||||||
"html-webpack-plugin": "^5.3.1",
|
"html-webpack-plugin": "^5.3.1",
|
||||||
"mini-css-extract-plugin": "^2.6.1",
|
"mini-css-extract-plugin": "^2.6.1",
|
||||||
"path-browserify": "^1.0.1",
|
"path-browserify": "^1.0.1",
|
||||||
"sass": "^1.54.1",
|
"sass": "^1.54.3",
|
||||||
"sass-loader": "^13.0.2",
|
"sass-loader": "^13.0.2",
|
||||||
"stream-browserify": "^3.0.0",
|
"stream-browserify": "^3.0.0",
|
||||||
"style-loader": "^3.3.1",
|
"style-loader": "^3.3.1",
|
||||||
|
@ -1897,14 +1897,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@fontsource/inter": {
|
"node_modules/@fontsource/inter": {
|
||||||
"version": "4.5.11",
|
"version": "4.5.12",
|
||||||
"resolved": "https://registry.npmjs.org/@fontsource/inter/-/inter-4.5.11.tgz",
|
"resolved": "https://registry.npmjs.org/@fontsource/inter/-/inter-4.5.12.tgz",
|
||||||
"integrity": "sha512-toizzQkfXL8YJcG/f8j3EYXYGQe4OxiDEItThSigvHU+cYNDw8HPp3wLYQX745hddsnHqOGCM4exitFSBOU8+w=="
|
"integrity": "sha512-bGKk4/8tube/nCk8hav0ZDBVbzJzc7m0Vt4xF5p15IN4YImwGdtKG38Oq5bU8xHNS+VfvbFFCepgQNj7Pr/Lvg=="
|
||||||
},
|
},
|
||||||
"node_modules/@fontsource/roboto": {
|
"node_modules/@fontsource/roboto": {
|
||||||
"version": "4.5.7",
|
"version": "4.5.8",
|
||||||
"resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-4.5.7.tgz",
|
"resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-4.5.8.tgz",
|
||||||
"integrity": "sha512-m57UMER23Mk6Drg9OjtHW1Y+0KPGyZfE5XJoPTOsLARLar6013kJj4X2HICt+iFLJqIgTahA/QAvSn9lwF1EEw=="
|
"integrity": "sha512-CnD7zLItIzt86q4Sj3kZUiLcBk1dSk81qcqgMGaZe7SQ1P8hFNxhMl5AZthK1zrDM5m74VVhaOpuMGIL4gagaA=="
|
||||||
},
|
},
|
||||||
"node_modules/@humanwhocodes/config-array": {
|
"node_modules/@humanwhocodes/config-array": {
|
||||||
"version": "0.10.4",
|
"version": "0.10.4",
|
||||||
|
@ -2485,9 +2485,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@matrix-org/olm": {
|
"node_modules/@matrix-org/olm": {
|
||||||
"version": "3.2.8",
|
"version": "3.2.12",
|
||||||
"resolved": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.8.tgz",
|
"resolved": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.12.tgz",
|
||||||
"integrity": "sha512-yCJzEYY2aG1z+7nxKYZC4DFYwQO/5iG019qgotJhauYJRhEG9gLrKTvXO6lRHS8TjnZzsZFZyO/hQUlI4Dryig==",
|
"integrity": "sha512-muHkYUAXyRDg88YVFlmFY35vgLPovK2YPkuEtBfgnmBcxJvLpV9UMcMMxNkf8opjMV1k/NJ4niFQMzwd4UQOiA==",
|
||||||
"license": "Apache-2.0"
|
"license": "Apache-2.0"
|
||||||
},
|
},
|
||||||
"node_modules/@nodelib/fs.scandir": {
|
"node_modules/@nodelib/fs.scandir": {
|
||||||
|
@ -3076,8 +3076,6 @@
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.9.0.tgz",
|
||||||
"integrity": "sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ==",
|
"integrity": "sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fast-deep-equal": "^3.1.1",
|
"fast-deep-equal": "^3.1.1",
|
||||||
"json-schema-traverse": "^1.0.0",
|
"json-schema-traverse": "^1.0.0",
|
||||||
|
@ -3093,9 +3091,7 @@
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true,
|
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/ajv-keywords": {
|
"node_modules/ajv-keywords": {
|
||||||
"version": "3.5.2",
|
"version": "3.5.2",
|
||||||
|
@ -3527,12 +3523,9 @@
|
||||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||||
},
|
},
|
||||||
"node_modules/base-x": {
|
"node_modules/base-x": {
|
||||||
"version": "3.0.9",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz",
|
"resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.0.tgz",
|
||||||
"integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==",
|
"integrity": "sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw=="
|
||||||
"dependencies": {
|
|
||||||
"safe-buffer": "^5.0.1"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"node_modules/base64-js": {
|
"node_modules/base64-js": {
|
||||||
"version": "1.5.1",
|
"version": "1.5.1",
|
||||||
|
@ -3877,11 +3870,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/bs58": {
|
"node_modules/bs58": {
|
||||||
"version": "4.0.1",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/bs58/-/bs58-5.0.0.tgz",
|
||||||
"integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=",
|
"integrity": "sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"base-x": "^3.0.2"
|
"base-x": "^4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/buffer": {
|
"node_modules/buffer": {
|
||||||
|
@ -9291,18 +9284,18 @@
|
||||||
"integrity": "sha512-9jl4wtWanUFSy2sr2lCjErN/oC8KTAtaeaozJtrgot1JiQcEI4Rda9OLgQ7nLKaqb4Z/QUx/fR3XpDzm5Jy1JA=="
|
"integrity": "sha512-9jl4wtWanUFSy2sr2lCjErN/oC8KTAtaeaozJtrgot1JiQcEI4Rda9OLgQ7nLKaqb4Z/QUx/fR3XpDzm5Jy1JA=="
|
||||||
},
|
},
|
||||||
"node_modules/matrix-js-sdk": {
|
"node_modules/matrix-js-sdk": {
|
||||||
"version": "18.1.0",
|
"version": "19.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/matrix-js-sdk/-/matrix-js-sdk-18.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/matrix-js-sdk/-/matrix-js-sdk-19.2.0.tgz",
|
||||||
"integrity": "sha512-O5D36paIsY7a2M2mOo7KKU7v1Mb3PVkmYKupXYcXd9gB/Ki1K4mds+vSDEhgkKyKwk6MK1AV/vgvp0xJCsttvg==",
|
"integrity": "sha512-alvTasCTCo/XXSIkKEj8xKe1NMsyiVDDVIQdU9ZHI1aePq+DrAcx8CqB7L/dgjk842v+63Eke1f/jZuFWvjn4w==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.12.5",
|
"@babel/runtime": "^7.12.5",
|
||||||
"another-json": "^0.2.0",
|
"another-json": "^0.2.0",
|
||||||
"browser-request": "^0.3.3",
|
"browser-request": "^0.3.3",
|
||||||
"bs58": "^4.0.1",
|
"bs58": "^5.0.0",
|
||||||
"content-type": "^1.0.4",
|
"content-type": "^1.0.4",
|
||||||
"loglevel": "^1.7.1",
|
"loglevel": "^1.7.1",
|
||||||
"matrix-events-sdk": "^0.0.1-beta.7",
|
"matrix-events-sdk": "^0.0.1-beta.7",
|
||||||
"p-retry": "^4.5.0",
|
"p-retry": "4",
|
||||||
"qs": "^6.9.6",
|
"qs": "^6.9.6",
|
||||||
"request": "^2.88.2",
|
"request": "^2.88.2",
|
||||||
"unhomoglyph": "^1.0.6"
|
"unhomoglyph": "^1.0.6"
|
||||||
|
@ -12388,9 +12381,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/sass": {
|
"node_modules/sass": {
|
||||||
"version": "1.54.1",
|
"version": "1.54.3",
|
||||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.54.1.tgz",
|
"resolved": "https://registry.npmjs.org/sass/-/sass-1.54.3.tgz",
|
||||||
"integrity": "sha512-GHJJr31Me32RjjUBagyzx8tzjKBUcDwo5239XANIRBq0adDu5iIG0aFO0i/TBb/4I9oyxkEv44nq/kL1DxdDhA==",
|
"integrity": "sha512-fLodey5Qd41Pxp/Tk7Al97sViYwF/TazRc5t6E65O7JOk4XF8pzwIW7CvCxYVOfJFFI/1x5+elDyBIixrp+zrw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chokidar": ">=3.0.0 <4.0.0",
|
"chokidar": ">=3.0.0 <4.0.0",
|
||||||
|
@ -15985,14 +15978,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@fontsource/inter": {
|
"@fontsource/inter": {
|
||||||
"version": "4.5.11",
|
"version": "4.5.12",
|
||||||
"resolved": "https://registry.npmjs.org/@fontsource/inter/-/inter-4.5.11.tgz",
|
"resolved": "https://registry.npmjs.org/@fontsource/inter/-/inter-4.5.12.tgz",
|
||||||
"integrity": "sha512-toizzQkfXL8YJcG/f8j3EYXYGQe4OxiDEItThSigvHU+cYNDw8HPp3wLYQX745hddsnHqOGCM4exitFSBOU8+w=="
|
"integrity": "sha512-bGKk4/8tube/nCk8hav0ZDBVbzJzc7m0Vt4xF5p15IN4YImwGdtKG38Oq5bU8xHNS+VfvbFFCepgQNj7Pr/Lvg=="
|
||||||
},
|
},
|
||||||
"@fontsource/roboto": {
|
"@fontsource/roboto": {
|
||||||
"version": "4.5.7",
|
"version": "4.5.8",
|
||||||
"resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-4.5.7.tgz",
|
"resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-4.5.8.tgz",
|
||||||
"integrity": "sha512-m57UMER23Mk6Drg9OjtHW1Y+0KPGyZfE5XJoPTOsLARLar6013kJj4X2HICt+iFLJqIgTahA/QAvSn9lwF1EEw=="
|
"integrity": "sha512-CnD7zLItIzt86q4Sj3kZUiLcBk1dSk81qcqgMGaZe7SQ1P8hFNxhMl5AZthK1zrDM5m74VVhaOpuMGIL4gagaA=="
|
||||||
},
|
},
|
||||||
"@humanwhocodes/config-array": {
|
"@humanwhocodes/config-array": {
|
||||||
"version": "0.10.4",
|
"version": "0.10.4",
|
||||||
|
@ -16444,8 +16437,8 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@matrix-org/olm": {
|
"@matrix-org/olm": {
|
||||||
"version": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.8.tgz",
|
"version": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.12.tgz",
|
||||||
"integrity": "sha512-yCJzEYY2aG1z+7nxKYZC4DFYwQO/5iG019qgotJhauYJRhEG9gLrKTvXO6lRHS8TjnZzsZFZyO/hQUlI4Dryig=="
|
"integrity": "sha512-muHkYUAXyRDg88YVFlmFY35vgLPovK2YPkuEtBfgnmBcxJvLpV9UMcMMxNkf8opjMV1k/NJ4niFQMzwd4UQOiA=="
|
||||||
},
|
},
|
||||||
"@nodelib/fs.scandir": {
|
"@nodelib/fs.scandir": {
|
||||||
"version": "2.1.5",
|
"version": "2.1.5",
|
||||||
|
@ -16967,14 +16960,15 @@
|
||||||
"resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
|
||||||
"integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
|
"integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {},
|
"requires": {
|
||||||
|
"ajv": "^8.0.0"
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ajv": {
|
"ajv": {
|
||||||
"version": "https://registry.npmjs.org/ajv/-/ajv-8.9.0.tgz",
|
"version": "8.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.9.0.tgz",
|
||||||
"integrity": "sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ==",
|
"integrity": "sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
|
||||||
"peer": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"fast-deep-equal": "^3.1.1",
|
"fast-deep-equal": "^3.1.1",
|
||||||
"json-schema-traverse": "^1.0.0",
|
"json-schema-traverse": "^1.0.0",
|
||||||
|
@ -16986,9 +16980,7 @@
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true,
|
|
||||||
"peer": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -17347,12 +17339,9 @@
|
||||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||||
},
|
},
|
||||||
"base-x": {
|
"base-x": {
|
||||||
"version": "3.0.9",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz",
|
"resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.0.tgz",
|
||||||
"integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==",
|
"integrity": "sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw=="
|
||||||
"requires": {
|
|
||||||
"safe-buffer": "^5.0.1"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"base64-js": {
|
"base64-js": {
|
||||||
"version": "1.5.1",
|
"version": "1.5.1",
|
||||||
|
@ -17632,11 +17621,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"bs58": {
|
"bs58": {
|
||||||
"version": "4.0.1",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/bs58/-/bs58-5.0.0.tgz",
|
||||||
"integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=",
|
"integrity": "sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"base-x": "^3.0.2"
|
"base-x": "^4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"buffer": {
|
"buffer": {
|
||||||
|
@ -21794,18 +21783,18 @@
|
||||||
"integrity": "sha512-9jl4wtWanUFSy2sr2lCjErN/oC8KTAtaeaozJtrgot1JiQcEI4Rda9OLgQ7nLKaqb4Z/QUx/fR3XpDzm5Jy1JA=="
|
"integrity": "sha512-9jl4wtWanUFSy2sr2lCjErN/oC8KTAtaeaozJtrgot1JiQcEI4Rda9OLgQ7nLKaqb4Z/QUx/fR3XpDzm5Jy1JA=="
|
||||||
},
|
},
|
||||||
"matrix-js-sdk": {
|
"matrix-js-sdk": {
|
||||||
"version": "18.1.0",
|
"version": "19.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/matrix-js-sdk/-/matrix-js-sdk-18.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/matrix-js-sdk/-/matrix-js-sdk-19.2.0.tgz",
|
||||||
"integrity": "sha512-O5D36paIsY7a2M2mOo7KKU7v1Mb3PVkmYKupXYcXd9gB/Ki1K4mds+vSDEhgkKyKwk6MK1AV/vgvp0xJCsttvg==",
|
"integrity": "sha512-alvTasCTCo/XXSIkKEj8xKe1NMsyiVDDVIQdU9ZHI1aePq+DrAcx8CqB7L/dgjk842v+63Eke1f/jZuFWvjn4w==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/runtime": "^7.12.5",
|
"@babel/runtime": "^7.12.5",
|
||||||
"another-json": "^0.2.0",
|
"another-json": "^0.2.0",
|
||||||
"browser-request": "^0.3.3",
|
"browser-request": "^0.3.3",
|
||||||
"bs58": "^4.0.1",
|
"bs58": "^5.0.0",
|
||||||
"content-type": "^1.0.4",
|
"content-type": "^1.0.4",
|
||||||
"loglevel": "^1.7.1",
|
"loglevel": "^1.7.1",
|
||||||
"matrix-events-sdk": "^0.0.1-beta.7",
|
"matrix-events-sdk": "^0.0.1-beta.7",
|
||||||
"p-retry": "^4.5.0",
|
"p-retry": "4",
|
||||||
"qs": "^6.9.6",
|
"qs": "^6.9.6",
|
||||||
"request": "^2.88.2",
|
"request": "^2.88.2",
|
||||||
"unhomoglyph": "^1.0.6"
|
"unhomoglyph": "^1.0.6"
|
||||||
|
@ -23996,9 +23985,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sass": {
|
"sass": {
|
||||||
"version": "1.54.1",
|
"version": "1.54.3",
|
||||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.54.1.tgz",
|
"resolved": "https://registry.npmjs.org/sass/-/sass-1.54.3.tgz",
|
||||||
"integrity": "sha512-GHJJr31Me32RjjUBagyzx8tzjKBUcDwo5239XANIRBq0adDu5iIG0aFO0i/TBb/4I9oyxkEv44nq/kL1DxdDhA==",
|
"integrity": "sha512-fLodey5Qd41Pxp/Tk7Al97sViYwF/TazRc5t6E65O7JOk4XF8pzwIW7CvCxYVOfJFFI/1x5+elDyBIixrp+zrw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"chokidar": ">=3.0.0 <4.0.0",
|
"chokidar": ">=3.0.0 <4.0.0",
|
||||||
|
|
12
package.json
12
package.json
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "cinny",
|
"name": "cinny",
|
||||||
"version": "2.0.4",
|
"version": "2.1.2",
|
||||||
"description": "Yet another matrix client",
|
"description": "Yet another matrix client",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -16,9 +16,9 @@
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@alienfast/i18next-loader": "^1.1.4",
|
"@alienfast/i18next-loader": "^1.1.4",
|
||||||
"@fontsource/inter": "^4.5.11",
|
"@fontsource/inter": "^4.5.12",
|
||||||
"@fontsource/roboto": "^4.5.7",
|
"@fontsource/roboto": "^4.5.8",
|
||||||
"@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.8.tgz",
|
"@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.12.tgz",
|
||||||
"@tippyjs/react": "^4.2.6",
|
"@tippyjs/react": "^4.2.6",
|
||||||
"babel-polyfill": "^6.26.0",
|
"babel-polyfill": "^6.26.0",
|
||||||
"blurhash": "^1.1.5",
|
"blurhash": "^1.1.5",
|
||||||
|
@ -35,7 +35,7 @@
|
||||||
"katex": "^0.16.0",
|
"katex": "^0.16.0",
|
||||||
"linkify-html": "^4.0.0-beta.5",
|
"linkify-html": "^4.0.0-beta.5",
|
||||||
"linkifyjs": "^4.0.0-beta.5",
|
"linkifyjs": "^4.0.0-beta.5",
|
||||||
"matrix-js-sdk": "^18.1.0",
|
"matrix-js-sdk": "^19.2.0",
|
||||||
"micromark": "^3.0.10",
|
"micromark": "^3.0.10",
|
||||||
"micromark-extension-gfm": "^2.0.1",
|
"micromark-extension-gfm": "^2.0.1",
|
||||||
"micromark-extension-math": "^2.0.2",
|
"micromark-extension-math": "^2.0.2",
|
||||||
|
@ -81,7 +81,7 @@
|
||||||
"html-webpack-plugin": "^5.3.1",
|
"html-webpack-plugin": "^5.3.1",
|
||||||
"mini-css-extract-plugin": "^2.6.1",
|
"mini-css-extract-plugin": "^2.6.1",
|
||||||
"path-browserify": "^1.0.1",
|
"path-browserify": "^1.0.1",
|
||||||
"sass": "^1.54.1",
|
"sass": "^1.54.3",
|
||||||
"sass-loader": "^13.0.2",
|
"sass-loader": "^13.0.2",
|
||||||
"stream-browserify": "^3.0.0",
|
"stream-browserify": "^3.0.0",
|
||||||
"style-loader": "^3.3.1",
|
"style-loader": "^3.3.1",
|
||||||
|
|
|
@ -16,6 +16,7 @@ function Input({
|
||||||
{ resizable
|
{ resizable
|
||||||
? (
|
? (
|
||||||
<TextareaAutosize
|
<TextareaAutosize
|
||||||
|
dir="auto"
|
||||||
style={{ minHeight: `${minHeight}px` }}
|
style={{ minHeight: `${minHeight}px` }}
|
||||||
name={name}
|
name={name}
|
||||||
id={id}
|
id={id}
|
||||||
|
@ -34,6 +35,7 @@ function Input({
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<input
|
<input
|
||||||
|
dir="auto"
|
||||||
ref={forwardRef}
|
ref={forwardRef}
|
||||||
id={id}
|
id={id}
|
||||||
name={name}
|
name={name}
|
||||||
|
|
|
@ -123,7 +123,7 @@ function useImagePackHandles(pack, sendPackContent) {
|
||||||
|
|
||||||
const getNewKey = (key) => {
|
const getNewKey = (key) => {
|
||||||
if (typeof key !== 'string') return undefined;
|
if (typeof key !== 'string') return undefined;
|
||||||
let newKey = key?.replace(/\s/g, '-');
|
let newKey = key?.replace(/\s/g, '_');
|
||||||
if (pack.getImages().get(newKey)) {
|
if (pack.getImages().get(newKey)) {
|
||||||
newKey = suffixRename(
|
newKey = suffixRename(
|
||||||
newKey,
|
newKey,
|
||||||
|
|
|
@ -44,11 +44,13 @@ function ImagePackUpload({ onUpload }) {
|
||||||
const img = evt.target.files[0];
|
const img = evt.target.files[0];
|
||||||
if (!img) return;
|
if (!img) return;
|
||||||
setImgFile(img);
|
setImgFile(img);
|
||||||
|
shortcodeRef.current.value = img.name.slice(0, img.name.indexOf('.'));
|
||||||
shortcodeRef.current.focus();
|
shortcodeRef.current.focus();
|
||||||
};
|
};
|
||||||
const handleRemove = () => {
|
const handleRemove = () => {
|
||||||
setImgFile(null);
|
setImgFile(null);
|
||||||
inputRef.current.value = null;
|
inputRef.current.value = null;
|
||||||
|
shortcodeRef.current.value = '';
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -15,43 +15,7 @@ import ExternalSVG from '../../../../public/res/ic/outlined/external.svg';
|
||||||
import PlaySVG from '../../../../public/res/ic/outlined/play.svg';
|
import PlaySVG from '../../../../public/res/ic/outlined/play.svg';
|
||||||
|
|
||||||
import '../../i18n';
|
import '../../i18n';
|
||||||
|
import { getBlobSafeMimeType } from '../../../util/mimetypes';
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getDecryptedBlob(response, type, decryptData) {
|
async function getDecryptedBlob(response, type, decryptData) {
|
||||||
const arrayBuffer = await response.arrayBuffer();
|
const arrayBuffer = await response.arrayBuffer();
|
||||||
|
@ -163,6 +127,7 @@ function Image({
|
||||||
name, width, height, link, file, type, blurhash,
|
name, width, height, link, file, type, blurhash,
|
||||||
}) {
|
}) {
|
||||||
const [url, setUrl] = useState(null);
|
const [url, setUrl] = useState(null);
|
||||||
|
const [blur, setBlur] = useState(true);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let unmounted = false;
|
let unmounted = false;
|
||||||
|
@ -181,8 +146,8 @@ function Image({
|
||||||
<div className="file-container">
|
<div className="file-container">
|
||||||
<FileHeader name={name} link={url || link} type={type} external />
|
<FileHeader name={name} link={url || link} type={type} external />
|
||||||
<div style={{ height: width !== null ? getNativeHeight(width, height) : 'unset' }} className="image-container">
|
<div style={{ height: width !== null ? getNativeHeight(width, height) : 'unset' }} className="image-container">
|
||||||
{ blurhash && <BlurhashCanvas hash={blurhash} punch={1} />}
|
{ blurhash && blur && <BlurhashCanvas hash={blurhash} punch={1} />}
|
||||||
{ url !== null && <img src={url || link} alt={name} />}
|
{ url !== null && <img style={{ display: blur ? 'none' : 'unset' }} onLoad={() => setBlur(false)} src={url || link} alt={name} />}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -231,11 +196,11 @@ function Sticker({
|
||||||
Sticker.defaultProps = {
|
Sticker.defaultProps = {
|
||||||
file: null,
|
file: null,
|
||||||
type: '',
|
type: '',
|
||||||
|
width: null,
|
||||||
|
height: null,
|
||||||
};
|
};
|
||||||
Sticker.propTypes = {
|
Sticker.propTypes = {
|
||||||
name: PropTypes.string.isRequired,
|
name: PropTypes.string.isRequired,
|
||||||
width: null,
|
|
||||||
height: null,
|
|
||||||
width: PropTypes.number,
|
width: PropTypes.number,
|
||||||
height: PropTypes.number,
|
height: PropTypes.number,
|
||||||
link: PropTypes.string.isRequired,
|
link: PropTypes.string.isRequired,
|
||||||
|
@ -295,6 +260,7 @@ function Video({
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [url, setUrl] = useState(null);
|
const [url, setUrl] = useState(null);
|
||||||
const [thumbUrl, setThumbUrl] = useState(null);
|
const [thumbUrl, setThumbUrl] = useState(null);
|
||||||
|
const [blur, setBlur] = useState(true);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let unmounted = false;
|
let unmounted = false;
|
||||||
|
@ -309,16 +275,16 @@ function Video({
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
async function loadVideo() {
|
const loadVideo = async () => {
|
||||||
const myUrl = await getUrl(link, type, file);
|
const myUrl = await getUrl(link, type, file);
|
||||||
setUrl(myUrl);
|
setUrl(myUrl);
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
};
|
||||||
|
|
||||||
function handlePlayVideo() {
|
const handlePlayVideo = () => {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
loadVideo();
|
loadVideo();
|
||||||
}
|
};
|
||||||
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
@ -331,14 +297,16 @@ function Video({
|
||||||
}}
|
}}
|
||||||
className="video-container"
|
className="video-container"
|
||||||
>
|
>
|
||||||
{ url === null && blurhash && <BlurhashCanvas hash={blurhash} punch={1} />}
|
{ url === null ? (
|
||||||
{ url === null && thumbUrl !== null && (
|
<>
|
||||||
/* eslint-disable-next-line jsx-a11y/alt-text */
|
{ blurhash && blur && <BlurhashCanvas hash={blurhash} punch={1} />}
|
||||||
<img src={thumbUrl} />
|
{ thumbUrl !== null && (
|
||||||
|
<img style={{ display: blur ? 'none' : 'unset' }} src={thumbUrl} onLoad={() => setBlur(false)} alt={name} />
|
||||||
)}
|
)}
|
||||||
{ url === null && isLoading && <Spinner size="small" /> }
|
{isLoading && <Spinner size="small" />}
|
||||||
{ url === null && !isLoading && <IconButton onClick={handlePlayVideo} tooltip={t('Molecules.Media.play_video')} src={PlaySVG} />}
|
{!isLoading && <IconButton onClick={handlePlayVideo} tooltip={t('Molecules.Media.play_video')} src={PlaySVG} />}
|
||||||
{ url !== null && (
|
</>
|
||||||
|
) : (
|
||||||
/* eslint-disable-next-line jsx-a11y/media-has-caption */
|
/* eslint-disable-next-line jsx-a11y/media-has-caption */
|
||||||
<video autoPlay controls poster={thumbUrl}>
|
<video autoPlay controls poster={thumbUrl}>
|
||||||
<source src={url} type={getBlobSafeMimeType(type)} />
|
<source src={url} type={getBlobSafeMimeType(type)} />
|
||||||
|
|
|
@ -27,14 +27,21 @@
|
||||||
white-space: initial;
|
white-space: initial;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sticker-container {
|
||||||
|
display: inline-flex;
|
||||||
|
max-width: 128px;
|
||||||
|
width: 100%;
|
||||||
|
& img {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.image-container,
|
.image-container,
|
||||||
.video-container,
|
.video-container,
|
||||||
.audio-container {
|
.audio-container {
|
||||||
font-size: 0;
|
font-size: 0;
|
||||||
line-height: 0;
|
line-height: 0;
|
||||||
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -48,7 +55,6 @@
|
||||||
.video-container {
|
.video-container {
|
||||||
& img,
|
& img,
|
||||||
& canvas {
|
& canvas {
|
||||||
position: absolute;
|
|
||||||
max-width: unset !important;
|
max-width: unset !important;
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
@ -57,18 +63,13 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.sticker-container {
|
|
||||||
display: inline-flex;
|
|
||||||
max-width: 128px;
|
|
||||||
width: 100%;
|
|
||||||
& img {
|
|
||||||
width: 100% !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-container {
|
.video-container {
|
||||||
|
position: relative;
|
||||||
& .ic-btn-surface {
|
& .ic-btn-surface {
|
||||||
background-color: var(--bg-surface-low);
|
background-color: var(--bg-surface-low);
|
||||||
|
}
|
||||||
|
& .ic-btn-surface,
|
||||||
|
& .donut-spinner {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
video {
|
video {
|
||||||
|
|
|
@ -38,6 +38,7 @@ import CmdIC from '../../../../public/res/ic/outlined/cmd.svg';
|
||||||
import BinIC from '../../../../public/res/ic/outlined/bin.svg';
|
import BinIC from '../../../../public/res/ic/outlined/bin.svg';
|
||||||
|
|
||||||
import { confirmDialog } from '../confirm-dialog/ConfirmDialog';
|
import { confirmDialog } from '../confirm-dialog/ConfirmDialog';
|
||||||
|
import { getBlobSafeMimeType } from '../../../util/mimetypes';
|
||||||
|
|
||||||
import '../../i18n';
|
import '../../i18n';
|
||||||
|
|
||||||
|
@ -210,7 +211,13 @@ const MessageBody = React.memo(({
|
||||||
let content = null;
|
let content = null;
|
||||||
if (isCustomHTML) {
|
if (isCustomHTML) {
|
||||||
try {
|
try {
|
||||||
content = twemojify(sanitizeCustomHtml(body), undefined, true, false, true);
|
content = twemojify(
|
||||||
|
sanitizeCustomHtml(initMatrix.matrixClient, body),
|
||||||
|
undefined,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
);
|
||||||
} catch {
|
} catch {
|
||||||
console.error('Malformed custom html: ', body);
|
console.error('Malformed custom html: ', body);
|
||||||
content = twemojify(body, undefined);
|
content = twemojify(body, undefined);
|
||||||
|
@ -626,7 +633,12 @@ function genMediaContent(mE) {
|
||||||
if (typeof mediaMXC === 'undefined' || mediaMXC === '') return <span style={{ color: 'var(--bg-danger)' }}>Malformed event</span>;
|
if (typeof mediaMXC === 'undefined' || mediaMXC === '') return <span style={{ color: 'var(--bg-danger)' }}>Malformed event</span>;
|
||||||
|
|
||||||
let msgType = mE.getContent()?.msgtype;
|
let msgType = mE.getContent()?.msgtype;
|
||||||
if (mE.getType() === 'm.sticker') msgType = 'm.sticker';
|
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'];
|
const blurhash = mContent?.info?.['xyz.amorgan.blurhash'];
|
||||||
|
|
||||||
|
|
|
@ -252,6 +252,58 @@ function EmojiBoard({ onSelect, searchRef }) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="emoji-board" className="emoji-board">
|
<div id="emoji-board" className="emoji-board">
|
||||||
|
<ScrollView invisible>
|
||||||
|
<div className="emoji-board__nav">
|
||||||
|
{recentEmojis.length > 0 && (
|
||||||
|
<IconButton
|
||||||
|
onClick={() => openGroup(0)}
|
||||||
|
src={RecentClockIC}
|
||||||
|
tooltip="Recent"
|
||||||
|
tooltipPlacement="left"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<div className="emoji-board__nav-custom">
|
||||||
|
{
|
||||||
|
availableEmojis.map((pack) => {
|
||||||
|
const src = initMatrix.matrixClient
|
||||||
|
.mxcUrlToHttp(pack.avatarUrl ?? pack.getEmojis()[0].mxc);
|
||||||
|
return (
|
||||||
|
<IconButton
|
||||||
|
onClick={() => openGroup(recentOffset + pack.packIndex)}
|
||||||
|
src={src}
|
||||||
|
key={pack.packIndex}
|
||||||
|
tooltip={pack.displayName ?? 'Unknown'}
|
||||||
|
tooltipPlacement="left"
|
||||||
|
isImage
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div className="emoji-board__nav-twemoji">
|
||||||
|
{
|
||||||
|
[
|
||||||
|
[0, EmojiIC, 'Smilies'],
|
||||||
|
[1, DogIC, 'Animals'],
|
||||||
|
[2, CupIC, 'Food'],
|
||||||
|
[3, BallIC, 'Activities'],
|
||||||
|
[4, PhotoIC, 'Travel'],
|
||||||
|
[5, BulbIC, 'Objects'],
|
||||||
|
[6, PeaceIC, 'Symbols'],
|
||||||
|
[7, FlagIC, 'Flags'],
|
||||||
|
].map(([indx, ico, name]) => (
|
||||||
|
<IconButton
|
||||||
|
onClick={() => openGroup(recentOffset + availableEmojis.length + indx)}
|
||||||
|
key={indx}
|
||||||
|
src={ico}
|
||||||
|
tooltip={name}
|
||||||
|
tooltipPlacement="left"
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ScrollView>
|
||||||
<div className="emoji-board__content">
|
<div className="emoji-board__content">
|
||||||
<div className="emoji-board__content__search">
|
<div className="emoji-board__content__search">
|
||||||
<RawIcon size="small" src={SearchIC} />
|
<RawIcon size="small" src={SearchIC} />
|
||||||
|
@ -285,58 +337,6 @@ function EmojiBoard({ onSelect, searchRef }) {
|
||||||
<Text>:slight_smile:</Text>
|
<Text>:slight_smile:</Text>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ScrollView invisible>
|
|
||||||
<div className="emoji-board__nav">
|
|
||||||
{recentEmojis.length > 0 && (
|
|
||||||
<IconButton
|
|
||||||
onClick={() => openGroup(0)}
|
|
||||||
src={RecentClockIC}
|
|
||||||
tooltip="Recent"
|
|
||||||
tooltipPlacement="right"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<div className="emoji-board__nav-custom">
|
|
||||||
{
|
|
||||||
availableEmojis.map((pack) => {
|
|
||||||
const src = initMatrix.matrixClient
|
|
||||||
.mxcUrlToHttp(pack.avatarUrl ?? pack.getEmojis()[0].mxc);
|
|
||||||
return (
|
|
||||||
<IconButton
|
|
||||||
onClick={() => openGroup(recentOffset + pack.packIndex)}
|
|
||||||
src={src}
|
|
||||||
key={pack.packIndex}
|
|
||||||
tooltip={pack.displayName ?? 'Unknown'}
|
|
||||||
tooltipPlacement="right"
|
|
||||||
isImage
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<div className="emoji-board__nav-twemoji">
|
|
||||||
{
|
|
||||||
[
|
|
||||||
[0, EmojiIC, 'Smilies'],
|
|
||||||
[1, DogIC, 'Animals'],
|
|
||||||
[2, CupIC, 'Food'],
|
|
||||||
[3, BallIC, 'Activities'],
|
|
||||||
[4, PhotoIC, 'Travel'],
|
|
||||||
[5, BulbIC, 'Objects'],
|
|
||||||
[6, PeaceIC, 'Symbols'],
|
|
||||||
[7, FlagIC, 'Flags'],
|
|
||||||
].map(([indx, ico, name]) => (
|
|
||||||
<IconButton
|
|
||||||
onClick={() => openGroup(recentOffset + availableEmojis.length + indx)}
|
|
||||||
key={indx}
|
|
||||||
src={ico}
|
|
||||||
tooltip={name}
|
|
||||||
tooltipPlacement="right"
|
|
||||||
/>
|
|
||||||
))
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</ScrollView>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,8 +25,7 @@
|
||||||
|
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
padding: 4px 6px;
|
padding: 4px 6px;
|
||||||
background-color: var(--bg-surface-low);
|
@include dir.side(border, none, 1px solid var(--bg-surface-border));
|
||||||
@include dir.side(border, 1px solid var(--bg-surface-border), none);
|
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
@ -122,8 +121,11 @@
|
||||||
@include dir.side(margin, var(--left-margin), var(--right-margin));
|
@include dir.side(margin, var(--left-margin), var(--right-margin));
|
||||||
}
|
}
|
||||||
& .emoji {
|
& .emoji {
|
||||||
width: 38px;
|
max-width: 38px;
|
||||||
height: 38px;
|
max-height: 38px;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
padding: var(--emoji-padding);
|
padding: var(--emoji-padding);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
|
@ -342,6 +342,7 @@ function RoomViewInput({
|
||||||
<ScrollView autoHide>
|
<ScrollView autoHide>
|
||||||
<Text className="room-input__textarea-wrapper">
|
<Text className="room-input__textarea-wrapper">
|
||||||
<TextareaAutosize
|
<TextareaAutosize
|
||||||
|
dir="auto"
|
||||||
id="message-textarea"
|
id="message-textarea"
|
||||||
ref={textAreaRef}
|
ref={textAreaRef}
|
||||||
onChange={handleMsgTyping}
|
onChange={handleMsgTyping}
|
||||||
|
|
|
@ -206,7 +206,7 @@ function getUsersActionJsx(roomId, userIds, actionStr) {
|
||||||
|
|
||||||
const othersCount = userIds.length - MAX_VISIBLE_COUNT;
|
const othersCount = userIds.length - MAX_VISIBLE_COUNT;
|
||||||
// eslint-disable-next-line react/jsx-one-expression-per-line
|
// eslint-disable-next-line react/jsx-one-expression-per-line
|
||||||
return <>{u1Jsx}, {u2Jsx}, {u3Jsx} and {othersCount} other are {actionStr}</>;
|
return <>{u1Jsx}, {u2Jsx}, {u3Jsx} and {othersCount} others are {actionStr}</>;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseTimelineChange(mEvent) {
|
function parseTimelineChange(mEvent) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* eslint-disable jsx-a11y/click-events-have-key-events */
|
/* eslint-disable jsx-a11y/click-events-have-key-events */
|
||||||
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
||||||
import React from 'react';
|
import React, { useRef } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import './StickerBoard.scss';
|
import './StickerBoard.scss';
|
||||||
|
|
||||||
|
@ -9,10 +9,12 @@ import { getRelevantPacks } from '../emoji-board/custom-emoji';
|
||||||
|
|
||||||
import Text from '../../atoms/text/Text';
|
import Text from '../../atoms/text/Text';
|
||||||
import ScrollView from '../../atoms/scroll/ScrollView';
|
import ScrollView from '../../atoms/scroll/ScrollView';
|
||||||
|
import IconButton from '../../atoms/button/IconButton';
|
||||||
|
|
||||||
function StickerBoard({ roomId, onSelect }) {
|
function StickerBoard({ roomId, onSelect }) {
|
||||||
const mx = initMatrix.matrixClient;
|
const mx = initMatrix.matrixClient;
|
||||||
const room = mx.getRoom(roomId);
|
const room = mx.getRoom(roomId);
|
||||||
|
const scrollRef = useRef(null);
|
||||||
|
|
||||||
const parentIds = initMatrix.roomList.getAllParentSpaces(room.roomId);
|
const parentIds = initMatrix.roomList.getAllParentSpaces(room.roomId);
|
||||||
const parentRooms = [...parentIds].map((id) => mx.getRoom(id));
|
const parentRooms = [...parentIds].map((id) => mx.getRoom(id));
|
||||||
|
@ -38,6 +40,11 @@ function StickerBoard({ roomId, onSelect }) {
|
||||||
onSelect(stickerData);
|
onSelect(stickerData);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const openGroup = (groupIndex) => {
|
||||||
|
const scrollContent = scrollRef.current.firstElementChild;
|
||||||
|
scrollContent.children[groupIndex].scrollIntoView();
|
||||||
|
};
|
||||||
|
|
||||||
const renderPack = (pack) => (
|
const renderPack = (pack) => (
|
||||||
<div className="sticker-board__pack" key={pack.id}>
|
<div className="sticker-board__pack" key={pack.id}>
|
||||||
<Text className="sticker-board__pack-header" variant="b2" weight="bold">{pack.displayName ?? 'Unknown'}</Text>
|
<Text className="sticker-board__pack-header" variant="b2" weight="bold">{pack.displayName ?? 'Unknown'}</Text>
|
||||||
|
@ -50,6 +57,7 @@ function StickerBoard({ roomId, onSelect }) {
|
||||||
alt={sticker.shortcode}
|
alt={sticker.shortcode}
|
||||||
title={sticker.body ?? sticker.shortcode}
|
title={sticker.body ?? sticker.shortcode}
|
||||||
data-mx-sticker={sticker.mxc}
|
data-mx-sticker={sticker.mxc}
|
||||||
|
loading="lazy"
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
@ -58,8 +66,27 @@ function StickerBoard({ roomId, onSelect }) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="sticker-board">
|
<div className="sticker-board">
|
||||||
|
{packs.length > 0 && (
|
||||||
|
<ScrollView invisible>
|
||||||
|
<div className="sticker-board__sidebar">
|
||||||
|
{packs.map((pack, index) => {
|
||||||
|
const src = mx.mxcUrlToHttp(pack.avatarUrl ?? pack.getStickers()[0].mxc);
|
||||||
|
return (
|
||||||
|
<IconButton
|
||||||
|
key={pack.id}
|
||||||
|
onClick={() => openGroup(index)}
|
||||||
|
src={src}
|
||||||
|
tooltip={pack.displayName || 'Unknown'}
|
||||||
|
tooltipPlacement="left"
|
||||||
|
isImage
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</ScrollView>
|
||||||
|
)}
|
||||||
<div className="sticker-board__container">
|
<div className="sticker-board__container">
|
||||||
<ScrollView autoHide>
|
<ScrollView autoHide ref={scrollRef}>
|
||||||
<div
|
<div
|
||||||
onClick={handleOnSelect}
|
onClick={handleOnSelect}
|
||||||
className="sticker-board__content"
|
className="sticker-board__content"
|
||||||
|
|
|
@ -5,6 +5,20 @@
|
||||||
--sticker-board-width: 286px;
|
--sticker-board-width: 286px;
|
||||||
display: flex;
|
display: flex;
|
||||||
height: var(--sticker-board-height);
|
height: var(--sticker-board-height);
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
& > .scrollbar {
|
||||||
|
width: initial;
|
||||||
|
height: var(--sticker-board-height);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__sidebar {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-height: 100%;
|
||||||
|
padding: 4px 6px;
|
||||||
|
@include dir.side(border, none, 1px solid var(--bg-surface-border));
|
||||||
|
}
|
||||||
|
|
||||||
&__container {
|
&__container {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
import initMatrix from '../initMatrix';
|
import initMatrix from '../initMatrix';
|
||||||
|
|
||||||
function logout() {
|
async function logout() {
|
||||||
const mx = initMatrix.matrixClient;
|
const mx = initMatrix.matrixClient;
|
||||||
mx.stopClient();
|
mx.stopClient();
|
||||||
mx.logout().then(() => {
|
try {
|
||||||
|
await mx.logout();
|
||||||
|
} catch {
|
||||||
|
// ignore if failed to logout
|
||||||
|
}
|
||||||
mx.clearStores();
|
mx.clearStores();
|
||||||
window.localStorage.clear();
|
window.localStorage.clear();
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default logout;
|
export default logout;
|
||||||
|
|
|
@ -33,7 +33,6 @@ class InitMatrix extends EventEmitter {
|
||||||
accessToken: secret.accessToken,
|
accessToken: secret.accessToken,
|
||||||
userId: secret.userId,
|
userId: secret.userId,
|
||||||
store: indexedDBStore,
|
store: indexedDBStore,
|
||||||
sessionStore: new sdk.WebStorageSessionStore(global.localStorage),
|
|
||||||
cryptoStore: new sdk.IndexedDBCryptoStore(global.indexedDB, 'crypto-store'),
|
cryptoStore: new sdk.IndexedDBCryptoStore(global.indexedDB, 'crypto-store'),
|
||||||
deviceId: secret.deviceId,
|
deviceId: secret.deviceId,
|
||||||
timelineSupport: true,
|
timelineSupport: true,
|
||||||
|
|
|
@ -6,10 +6,14 @@ import { math } from 'micromark-extension-math';
|
||||||
import { encode } from 'blurhash';
|
import { encode } from 'blurhash';
|
||||||
import { getShortcodeToEmoji } from '../../app/organisms/emoji-board/custom-emoji';
|
import { getShortcodeToEmoji } from '../../app/organisms/emoji-board/custom-emoji';
|
||||||
import { mathExtensionHtml, spoilerExtension, spoilerExtensionHtml } from '../../util/markdown';
|
import { mathExtensionHtml, spoilerExtension, spoilerExtensionHtml } from '../../util/markdown';
|
||||||
|
import { getBlobSafeMimeType } from '../../util/mimetypes';
|
||||||
|
import { sanitizeText } from '../../util/sanitize';
|
||||||
import cons from './cons';
|
import cons from './cons';
|
||||||
import settings from './settings';
|
import settings from './settings';
|
||||||
|
|
||||||
const blurhashField = 'xyz.amorgan.blurhash';
|
const blurhashField = 'xyz.amorgan.blurhash';
|
||||||
|
const MXID_REGEX = /\B@\S+:\S+\.\S+[^.,:;?!\s]/g;
|
||||||
|
const SHORTCODE_REGEX = /\B:([\w-]+):\B/g;
|
||||||
|
|
||||||
function encodeBlurhash(img) {
|
function encodeBlurhash(img) {
|
||||||
const canvas = document.createElement('canvas');
|
const canvas = document.createElement('canvas');
|
||||||
|
@ -130,38 +134,45 @@ function bindReplyToContent(roomId, reply, content) {
|
||||||
return newContent;
|
return newContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatAndEmojifyText(mx, roomList, roomId, text) {
|
function findAndReplace(text, regex, filter, replace) {
|
||||||
const room = mx.getRoom(roomId);
|
let copyText = text;
|
||||||
|
Array.from(copyText.matchAll(regex))
|
||||||
|
.filter(filter)
|
||||||
|
.reverse() /* to replace backward to forward */
|
||||||
|
.forEach((match) => {
|
||||||
|
const matchText = match[0];
|
||||||
|
const tag = replace(match);
|
||||||
|
|
||||||
|
copyText = copyText.substr(0, match.index)
|
||||||
|
+ tag
|
||||||
|
+ copyText.substr(match.index + matchText.length);
|
||||||
|
});
|
||||||
|
return copyText;
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatUserPill(room, text) {
|
||||||
const { userIdsToDisplayNames } = room.currentState;
|
const { userIdsToDisplayNames } = room.currentState;
|
||||||
const parentIds = roomList.getAllParentSpaces(roomId);
|
return findAndReplace(
|
||||||
|
text,
|
||||||
|
MXID_REGEX,
|
||||||
|
(match) => userIdsToDisplayNames[match[0]],
|
||||||
|
(match) => (
|
||||||
|
`<a href="https://matrix.to/#/${match[0]}">@${userIdsToDisplayNames[match[0]]}</a>`
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatEmoji(mx, room, roomList, text) {
|
||||||
|
const parentIds = roomList.getAllParentSpaces(room.roomId);
|
||||||
const parentRooms = [...parentIds].map((id) => mx.getRoom(id));
|
const parentRooms = [...parentIds].map((id) => mx.getRoom(id));
|
||||||
const allEmoji = getShortcodeToEmoji(mx, [room, ...parentRooms]);
|
const allEmoji = getShortcodeToEmoji(mx, [room, ...parentRooms]);
|
||||||
|
|
||||||
let formattedText;
|
return findAndReplace(
|
||||||
if (settings.isMarkdown) {
|
text,
|
||||||
formattedText = getFormattedBody(text);
|
SHORTCODE_REGEX,
|
||||||
} else {
|
(match) => allEmoji.has(match[1]),
|
||||||
formattedText = text;
|
(match) => {
|
||||||
}
|
const emoji = allEmoji.get(match[1]);
|
||||||
|
|
||||||
const MXID_REGEX = /\B@\S+:\S+\.\S+[^.,:;?!\s]/g;
|
|
||||||
Array.from(formattedText.matchAll(MXID_REGEX))
|
|
||||||
.filter((mxidMatch) => userIdsToDisplayNames[mxidMatch[0]])
|
|
||||||
.reverse()
|
|
||||||
.forEach((mxidMatch) => {
|
|
||||||
const tag = `<a href="https://matrix.to/#/${mxidMatch[0]}">${userIdsToDisplayNames[mxidMatch[0]]}</a>`;
|
|
||||||
|
|
||||||
formattedText = formattedText.substr(0, mxidMatch.index)
|
|
||||||
+ tag
|
|
||||||
+ formattedText.substr(mxidMatch.index + mxidMatch[0].length);
|
|
||||||
});
|
|
||||||
|
|
||||||
const SHORTCODE_REGEX = /\B:([\w-]+):\B/g;
|
|
||||||
Array.from(formattedText.matchAll(SHORTCODE_REGEX))
|
|
||||||
.filter((shortcodeMatch) => allEmoji.has(shortcodeMatch[1]))
|
|
||||||
.reverse() /* Reversing the array ensures that indices are preserved as we start replacing */
|
|
||||||
.forEach((shortcodeMatch) => {
|
|
||||||
const emoji = allEmoji.get(shortcodeMatch[1]);
|
|
||||||
|
|
||||||
let tag;
|
let tag;
|
||||||
if (emoji.mxc) {
|
if (emoji.mxc) {
|
||||||
|
@ -175,13 +186,9 @@ function formatAndEmojifyText(mx, roomList, roomId, text) {
|
||||||
} else {
|
} else {
|
||||||
tag = emoji.unicode;
|
tag = emoji.unicode;
|
||||||
}
|
}
|
||||||
|
return tag;
|
||||||
formattedText = formattedText.substr(0, shortcodeMatch.index)
|
},
|
||||||
+ tag
|
);
|
||||||
+ formattedText.substr(shortcodeMatch.index + shortcodeMatch[0].length);
|
|
||||||
});
|
|
||||||
|
|
||||||
return formattedText;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class RoomsInput extends EventEmitter {
|
class RoomsInput extends EventEmitter {
|
||||||
|
@ -274,6 +281,7 @@ class RoomsInput extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
async sendInput(roomId) {
|
async sendInput(roomId) {
|
||||||
|
const room = this.matrixClient.getRoom(roomId);
|
||||||
const input = this.getInput(roomId);
|
const input = this.getInput(roomId);
|
||||||
input.isSending = true;
|
input.isSending = true;
|
||||||
this.roomIdToInput.set(roomId, input);
|
this.roomIdToInput.set(roomId, input);
|
||||||
|
@ -283,19 +291,27 @@ class RoomsInput extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.getMessage(roomId).trim() !== '') {
|
if (this.getMessage(roomId).trim() !== '') {
|
||||||
|
const rawMessage = input.message;
|
||||||
let content = {
|
let content = {
|
||||||
body: input.message,
|
body: rawMessage,
|
||||||
msgtype: 'm.text',
|
msgtype: 'm.text',
|
||||||
};
|
};
|
||||||
|
|
||||||
// Apply formatting if relevant
|
// Apply formatting if relevant
|
||||||
const formattedBody = formatAndEmojifyText(
|
let formattedBody = settings.isMarkdown
|
||||||
this.matrixClient,
|
? getFormattedBody(rawMessage)
|
||||||
this.roomList,
|
: sanitizeText(rawMessage);
|
||||||
roomId,
|
|
||||||
input.message,
|
formattedBody = formatUserPill(room, formattedBody);
|
||||||
|
formattedBody = formatEmoji(this.matrixClient, room, this.roomList, formattedBody);
|
||||||
|
|
||||||
|
content.body = findAndReplace(
|
||||||
|
content.body,
|
||||||
|
MXID_REGEX,
|
||||||
|
(match) => room.currentState.userIdsToDisplayNames[match[0]],
|
||||||
|
(match) => `@${room.currentState.userIdsToDisplayNames[match[0]]}`,
|
||||||
);
|
);
|
||||||
if (formattedBody !== input.message) {
|
if (formattedBody !== sanitizeText(rawMessage)) {
|
||||||
// Formatting was applied, and we need to switch to custom HTML
|
// Formatting was applied, and we need to switch to custom HTML
|
||||||
content.format = 'org.matrix.custom.html';
|
content.format = 'org.matrix.custom.html';
|
||||||
content.formatted_body = formattedBody;
|
content.formatted_body = formattedBody;
|
||||||
|
@ -340,7 +356,7 @@ class RoomsInput extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
async sendFile(roomId, file) {
|
async sendFile(roomId, file) {
|
||||||
const fileType = file.type.slice(0, file.type.indexOf('/'));
|
const fileType = getBlobSafeMimeType(file.type).slice(0, file.type.indexOf('/'));
|
||||||
const info = {
|
const info = {
|
||||||
mimetype: file.type,
|
mimetype: file.type,
|
||||||
size: file.size,
|
size: file.size,
|
||||||
|
@ -446,6 +462,7 @@ class RoomsInput extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
async sendEditedMessage(roomId, mEvent, editedBody) {
|
async sendEditedMessage(roomId, mEvent, editedBody) {
|
||||||
|
const room = this.matrixClient.getRoom(roomId);
|
||||||
const isReply = typeof mEvent.getWireContent()['m.relates_to']?.['m.in_reply_to'] !== 'undefined';
|
const isReply = typeof mEvent.getWireContent()['m.relates_to']?.['m.in_reply_to'] !== 'undefined';
|
||||||
|
|
||||||
const content = {
|
const content = {
|
||||||
|
@ -462,13 +479,19 @@ class RoomsInput extends EventEmitter {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Apply formatting if relevant
|
// Apply formatting if relevant
|
||||||
const formattedBody = formatAndEmojifyText(
|
let formattedBody = settings.isMarkdown
|
||||||
this.matrixClient,
|
? getFormattedBody(editedBody)
|
||||||
this.roomList,
|
: sanitizeText(editedBody);
|
||||||
roomId,
|
formattedBody = formatUserPill(room, formattedBody);
|
||||||
editedBody,
|
formattedBody = formatEmoji(this.matrixClient, room, this.roomList, formattedBody);
|
||||||
|
|
||||||
|
content.body = findAndReplace(
|
||||||
|
content.body,
|
||||||
|
MXID_REGEX,
|
||||||
|
(match) => room.currentState.userIdsToDisplayNames[match[0]],
|
||||||
|
(match) => `@${room.currentState.userIdsToDisplayNames[match[0]]}`,
|
||||||
);
|
);
|
||||||
if (formattedBody !== editedBody) {
|
if (formattedBody !== sanitizeText(editedBody)) {
|
||||||
content.formatted_body = ` * ${formattedBody}`;
|
content.formatted_body = ` * ${formattedBody}`;
|
||||||
content.format = 'org.matrix.custom.html';
|
content.format = 'org.matrix.custom.html';
|
||||||
content['m.new_content'].formatted_body = formattedBody;
|
content['m.new_content'].formatted_body = formattedBody;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const cons = {
|
const cons = {
|
||||||
version: '2.0.4',
|
version: '2.1.2',
|
||||||
secretKey: {
|
secretKey: {
|
||||||
ACCESS_TOKEN: 'cinny_access_token',
|
ACCESS_TOKEN: 'cinny_access_token',
|
||||||
DEVICE_ID: 'cinny_device_id',
|
DEVICE_ID: 'cinny_device_id',
|
||||||
|
|
|
@ -166,6 +166,9 @@ export function scaleDownImage(imageFile, width, height) {
|
||||||
img.onload = () => {
|
img.onload = () => {
|
||||||
let newWidth = img.width;
|
let newWidth = img.width;
|
||||||
let newHeight = img.height;
|
let newHeight = img.height;
|
||||||
|
if (newHeight <= height && newWidth <= width) {
|
||||||
|
resolve(imageFile);
|
||||||
|
}
|
||||||
|
|
||||||
if (newHeight > height) {
|
if (newHeight > height) {
|
||||||
newWidth = Math.floor(newWidth * (height / newHeight));
|
newWidth = Math.floor(newWidth * (height / newHeight));
|
||||||
|
|
37
src/util/mimetypes.js
Normal file
37
src/util/mimetypes.js
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
// https://github.com/matrix-org/matrix-react-sdk/blob/cd15e08fc285da42134817cce50de8011809cd53/src/utils/blobs.ts
|
||||||
|
export 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',
|
||||||
|
];
|
||||||
|
|
||||||
|
export 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;
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
import sanitizeHtml from 'sanitize-html';
|
import sanitizeHtml from 'sanitize-html';
|
||||||
import initMatrix from '../client/initMatrix';
|
|
||||||
|
|
||||||
const MAX_TAG_NESTING = 100;
|
const MAX_TAG_NESTING = 100;
|
||||||
|
let mx = null;
|
||||||
|
|
||||||
const permittedHtmlTags = [
|
const permittedHtmlTags = [
|
||||||
'font', 'del', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
|
'font', 'del', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
|
||||||
|
@ -54,7 +54,7 @@ function transformATag(tagName, attribs) {
|
||||||
'data-mx-pill': userId,
|
'data-mx-pill': userId,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
if (userId === initMatrix.matrixClient.getUserId()) {
|
if (userId === mx?.getUserId()) {
|
||||||
pill.attribs['data-mx-ping'] = undefined;
|
pill.attribs['data-mx-ping'] = undefined;
|
||||||
}
|
}
|
||||||
return pill;
|
return pill;
|
||||||
|
@ -76,17 +76,28 @@ function transformATag(tagName, attribs) {
|
||||||
|
|
||||||
function transformImgTag(tagName, attribs) {
|
function transformImgTag(tagName, attribs) {
|
||||||
const { src } = attribs;
|
const { src } = attribs;
|
||||||
const mx = initMatrix.matrixClient;
|
if (src.startsWith('mxc://') === false) {
|
||||||
|
return {
|
||||||
|
tagName: 'a',
|
||||||
|
attribs: {
|
||||||
|
href: src,
|
||||||
|
rel: 'noopener',
|
||||||
|
target: '_blank',
|
||||||
|
},
|
||||||
|
text: attribs.alt || src,
|
||||||
|
};
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
tagName,
|
tagName,
|
||||||
attribs: {
|
attribs: {
|
||||||
...attribs,
|
...attribs,
|
||||||
src: src.startsWith('mxc://') ? mx.mxcUrlToHttp(src) : src,
|
src: mx?.mxcUrlToHttp(src),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function sanitizeCustomHtml(body) {
|
export function sanitizeCustomHtml(matrixClient, body) {
|
||||||
|
mx = matrixClient;
|
||||||
return sanitizeHtml(body, {
|
return sanitizeHtml(body, {
|
||||||
allowedTags: permittedHtmlTags,
|
allowedTags: permittedHtmlTags,
|
||||||
allowedAttributes: permittedTagToAttributes,
|
allowedAttributes: permittedTagToAttributes,
|
||||||
|
|
Loading…
Reference in a new issue