Merge branch 'develop' into jaywink/hosting-provider-iframe
This commit is contained in:
commit
6843737a33
21 changed files with 602 additions and 108 deletions
108
CHANGELOG.md
108
CHANGELOG.md
|
@ -1,3 +1,111 @@
|
||||||
|
Changes in [3.11.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.11.1) (2020-12-21)
|
||||||
|
=====================================================================================================
|
||||||
|
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v3.11.0...v3.11.1)
|
||||||
|
|
||||||
|
* Upgrade JS SDK to 9.4.1
|
||||||
|
|
||||||
|
Changes in [3.11.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.11.0) (2020-12-21)
|
||||||
|
=====================================================================================================
|
||||||
|
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v3.11.0-rc.2...v3.11.0)
|
||||||
|
|
||||||
|
* Upgrade JS SDK to 9.4.0
|
||||||
|
* [Release] Look for emoji in the body that will be displayed
|
||||||
|
[\#5519](https://github.com/matrix-org/matrix-react-sdk/pull/5519)
|
||||||
|
* [Release] Recognise `*.element.io` links as Element permalinks
|
||||||
|
[\#5516](https://github.com/matrix-org/matrix-react-sdk/pull/5516)
|
||||||
|
* [Release] Fixes for call UI
|
||||||
|
[\#5513](https://github.com/matrix-org/matrix-react-sdk/pull/5513)
|
||||||
|
* [RELEASE] Add a snowfall chat effect (with /snowfall command)
|
||||||
|
[\#5512](https://github.com/matrix-org/matrix-react-sdk/pull/5512)
|
||||||
|
* [Release] Fix padding in confirmation email registration prompt
|
||||||
|
[\#5502](https://github.com/matrix-org/matrix-react-sdk/pull/5502)
|
||||||
|
|
||||||
|
Changes in [3.11.0-rc.2](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.11.0-rc.2) (2020-12-16)
|
||||||
|
===============================================================================================================
|
||||||
|
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v3.11.0-rc.1...v3.11.0-rc.2)
|
||||||
|
|
||||||
|
* Upgrade JS SDK to 9.4.0-rc.2
|
||||||
|
|
||||||
|
Changes in [3.11.0-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.11.0-rc.1) (2020-12-16)
|
||||||
|
===============================================================================================================
|
||||||
|
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v3.10.0...v3.11.0-rc.1)
|
||||||
|
|
||||||
|
* Upgrade JS SDK to 9.4.0-rc.1
|
||||||
|
* Translations update from Weblate
|
||||||
|
[\#5497](https://github.com/matrix-org/matrix-react-sdk/pull/5497)
|
||||||
|
* Unregister from the dispatcher in CallHandler
|
||||||
|
[\#5495](https://github.com/matrix-org/matrix-react-sdk/pull/5495)
|
||||||
|
* Better adhere to MSC process
|
||||||
|
[\#5496](https://github.com/matrix-org/matrix-react-sdk/pull/5496)
|
||||||
|
* Use random pickle key on all platforms
|
||||||
|
[\#5483](https://github.com/matrix-org/matrix-react-sdk/pull/5483)
|
||||||
|
* Fix mx_MemberList icons
|
||||||
|
[\#5492](https://github.com/matrix-org/matrix-react-sdk/pull/5492)
|
||||||
|
* Convert InviteDialog to TypeScript
|
||||||
|
[\#5491](https://github.com/matrix-org/matrix-react-sdk/pull/5491)
|
||||||
|
* Add keyboard shortcut for emoji reactions
|
||||||
|
[\#5425](https://github.com/matrix-org/matrix-react-sdk/pull/5425)
|
||||||
|
* Run chat effects on events sent by widgets too
|
||||||
|
[\#5488](https://github.com/matrix-org/matrix-react-sdk/pull/5488)
|
||||||
|
* Fix being unable to pin widgets
|
||||||
|
[\#5487](https://github.com/matrix-org/matrix-react-sdk/pull/5487)
|
||||||
|
* Line 1 / 2 Support
|
||||||
|
[\#5468](https://github.com/matrix-org/matrix-react-sdk/pull/5468)
|
||||||
|
* Remove impossible labs feature: sending hidden read receipts
|
||||||
|
[\#5484](https://github.com/matrix-org/matrix-react-sdk/pull/5484)
|
||||||
|
* Fix height of Remote Video in call
|
||||||
|
[\#5456](https://github.com/matrix-org/matrix-react-sdk/pull/5456)
|
||||||
|
* Add UI for hold functionality
|
||||||
|
[\#5446](https://github.com/matrix-org/matrix-react-sdk/pull/5446)
|
||||||
|
* Allow SearchBox to expand to fill width
|
||||||
|
[\#5411](https://github.com/matrix-org/matrix-react-sdk/pull/5411)
|
||||||
|
* Use room alias in generated permalink for rooms
|
||||||
|
[\#5451](https://github.com/matrix-org/matrix-react-sdk/pull/5451)
|
||||||
|
* Only show confetti if the current room is receiving an appropriate event
|
||||||
|
[\#5482](https://github.com/matrix-org/matrix-react-sdk/pull/5482)
|
||||||
|
* Throttle RoomState.members handler to improve performance
|
||||||
|
[\#5481](https://github.com/matrix-org/matrix-react-sdk/pull/5481)
|
||||||
|
* Handle manual hs urls better for the server picker
|
||||||
|
[\#5477](https://github.com/matrix-org/matrix-react-sdk/pull/5477)
|
||||||
|
* Add Olm as a dev dependency for types
|
||||||
|
[\#5479](https://github.com/matrix-org/matrix-react-sdk/pull/5479)
|
||||||
|
* Hide Invite to this room CTA if no permission
|
||||||
|
[\#5476](https://github.com/matrix-org/matrix-react-sdk/pull/5476)
|
||||||
|
* Fix width of underline in server picker dialog
|
||||||
|
[\#5478](https://github.com/matrix-org/matrix-react-sdk/pull/5478)
|
||||||
|
* Fix confetti room unread state check
|
||||||
|
[\#5475](https://github.com/matrix-org/matrix-react-sdk/pull/5475)
|
||||||
|
* Show confetti in a chat room on command or emoji
|
||||||
|
[\#5140](https://github.com/matrix-org/matrix-react-sdk/pull/5140)
|
||||||
|
* Fix inverted settings default value
|
||||||
|
[\#5391](https://github.com/matrix-org/matrix-react-sdk/pull/5391)
|
||||||
|
* Improve usability of the Server Picker Dialog
|
||||||
|
[\#5474](https://github.com/matrix-org/matrix-react-sdk/pull/5474)
|
||||||
|
* Fix typos in some strings
|
||||||
|
[\#5473](https://github.com/matrix-org/matrix-react-sdk/pull/5473)
|
||||||
|
* Bump highlight.js from 10.1.2 to 10.4.1
|
||||||
|
[\#5472](https://github.com/matrix-org/matrix-react-sdk/pull/5472)
|
||||||
|
* Remove old app test script path
|
||||||
|
[\#5471](https://github.com/matrix-org/matrix-react-sdk/pull/5471)
|
||||||
|
* add support for giving reason when redacting
|
||||||
|
[\#5260](https://github.com/matrix-org/matrix-react-sdk/pull/5260)
|
||||||
|
* Add support for Netlify to fetchdep script
|
||||||
|
[\#5469](https://github.com/matrix-org/matrix-react-sdk/pull/5469)
|
||||||
|
* Nest other layers inside on automation
|
||||||
|
[\#5467](https://github.com/matrix-org/matrix-react-sdk/pull/5467)
|
||||||
|
* Rebrand various CI scripts and modules
|
||||||
|
[\#5466](https://github.com/matrix-org/matrix-react-sdk/pull/5466)
|
||||||
|
* Add more widget sanity checking
|
||||||
|
[\#5462](https://github.com/matrix-org/matrix-react-sdk/pull/5462)
|
||||||
|
* Fix React complaining about unknown DOM props
|
||||||
|
[\#5465](https://github.com/matrix-org/matrix-react-sdk/pull/5465)
|
||||||
|
* Jump to home page when leaving a room
|
||||||
|
[\#5464](https://github.com/matrix-org/matrix-react-sdk/pull/5464)
|
||||||
|
* Fix SSO buttons for Social Logins
|
||||||
|
[\#5463](https://github.com/matrix-org/matrix-react-sdk/pull/5463)
|
||||||
|
* Social Login and login delight tweaks
|
||||||
|
[\#5426](https://github.com/matrix-org/matrix-react-sdk/pull/5426)
|
||||||
|
|
||||||
Changes in [3.10.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.10.0) (2020-12-07)
|
Changes in [3.10.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.10.0) (2020-12-07)
|
||||||
=====================================================================================================
|
=====================================================================================================
|
||||||
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v3.10.0-rc.1...v3.10.0)
|
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v3.10.0-rc.1...v3.10.0)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "matrix-react-sdk",
|
"name": "matrix-react-sdk",
|
||||||
"version": "3.10.0",
|
"version": "3.11.1",
|
||||||
"description": "SDK for matrix.org using React",
|
"description": "SDK for matrix.org using React",
|
||||||
"author": "matrix.org",
|
"author": "matrix.org",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -27,11 +27,12 @@
|
||||||
"matrix-gen-i18n": "scripts/gen-i18n.js",
|
"matrix-gen-i18n": "scripts/gen-i18n.js",
|
||||||
"matrix-prune-i18n": "scripts/prune-i18n.js"
|
"matrix-prune-i18n": "scripts/prune-i18n.js"
|
||||||
},
|
},
|
||||||
"main": "./lib/index.js",
|
"main": "./src/index.js",
|
||||||
"typings": "./lib/index.d.ts",
|
|
||||||
"matrix_src_main": "./src/index.js",
|
"matrix_src_main": "./src/index.js",
|
||||||
|
"matrix_lib_main": "./lib/index.js",
|
||||||
|
"matrix_lib_typings": "./lib/index.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"prepare": "yarn build",
|
"prepublishOnly": "yarn build",
|
||||||
"i18n": "matrix-gen-i18n",
|
"i18n": "matrix-gen-i18n",
|
||||||
"prunei18n": "matrix-prune-i18n",
|
"prunei18n": "matrix-prune-i18n",
|
||||||
"diff-i18n": "cp src/i18n/strings/en_EN.json src/i18n/strings/en_EN_orig.json && ./scripts/gen-i18n.js && node scripts/compare-file.js src/i18n/strings/en_EN_orig.json src/i18n/strings/en_EN.json",
|
"diff-i18n": "cp src/i18n/strings/en_EN.json src/i18n/strings/en_EN_orig.json && ./scripts/gen-i18n.js && node scripts/compare-file.js src/i18n/strings/en_EN_orig.json src/i18n/strings/en_EN.json",
|
||||||
|
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.mx_InteractiveAuthEntryComponents_emailWrapper {
|
.mx_InteractiveAuthEntryComponents_emailWrapper {
|
||||||
padding-right: 60px;
|
padding-right: 100px;
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-top: 32px;
|
margin-top: 32px;
|
||||||
margin-bottom: 32px;
|
margin-bottom: 32px;
|
||||||
|
|
|
@ -41,6 +41,8 @@ limitations under the License.
|
||||||
padding: 0 0 0 24px;
|
padding: 0 0 0 24px;
|
||||||
font-size: inherit;
|
font-size: inherit;
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
|
display: block;
|
||||||
|
text-align: start;
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
content: '';
|
content: '';
|
||||||
|
|
|
@ -18,10 +18,7 @@ limitations under the License.
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 20px;
|
right: 20px;
|
||||||
bottom: 72px;
|
bottom: 72px;
|
||||||
border-radius: 8px;
|
|
||||||
overflow: hidden;
|
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
box-shadow: 0px 14px 24px rgba(0, 0, 0, 0.08);
|
|
||||||
|
|
||||||
// Disable pointer events for Jitsi widgets to function. Direct
|
// Disable pointer events for Jitsi widgets to function. Direct
|
||||||
// calls have their own cursor and behaviour, but we need to make
|
// calls have their own cursor and behaviour, but we need to make
|
||||||
|
@ -49,8 +46,10 @@ limitations under the License.
|
||||||
|
|
||||||
.mx_IncomingCallBox {
|
.mx_IncomingCallBox {
|
||||||
min-width: 250px;
|
min-width: 250px;
|
||||||
background-color: $primary-bg-color;
|
background-color: $secondary-accent-color;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
|
box-shadow: 0px 14px 24px rgba(0, 0, 0, 0.08);
|
||||||
|
border-radius: 8px;
|
||||||
|
|
||||||
pointer-events: initial; // restore pointer events so the user can accept/decline
|
pointer-events: initial; // restore pointer events so the user can accept/decline
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
|
@ -35,6 +35,10 @@ limitations under the License.
|
||||||
|
|
||||||
.mx_CallView_pip {
|
.mx_CallView_pip {
|
||||||
width: 320px;
|
width: 320px;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
margin-top: 10px;
|
||||||
|
box-shadow: 0px 14px 24px rgba(0, 0, 0, 0.08);
|
||||||
|
border-radius: 8px;
|
||||||
|
|
||||||
.mx_CallView_voice {
|
.mx_CallView_voice {
|
||||||
height: 180px;
|
height: 180px;
|
||||||
|
@ -84,50 +88,6 @@ limitations under the License.
|
||||||
border-radius: 2000px;
|
border-radius: 2000px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
&::after {
|
|
||||||
position: absolute;
|
|
||||||
content: '';
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
background-color: rgba(0, 0, 0, 0.6);
|
|
||||||
background-image: url('$(res)/img/voip/paused.svg');
|
|
||||||
background-position: center;
|
|
||||||
background-size: 40px;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
|
||||||
.mx_CallView_pip &::after {
|
|
||||||
background-size: 30px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.mx_BaseAvatar {
|
|
||||||
filter: blur(20px);
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_CallView_voice_secondaryAvatarContainer {
|
|
||||||
border-radius: 2000px;
|
|
||||||
overflow: hidden;
|
|
||||||
position: relative;
|
|
||||||
&::after {
|
|
||||||
position: absolute;
|
|
||||||
content: '';
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
background-color: rgba(0, 0, 0, 0.6);
|
|
||||||
background-image: url('$(res)/img/voip/paused.svg');
|
|
||||||
background-position: center;
|
|
||||||
background-size: 40px;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
|
||||||
.mx_CallView_pip &::after {
|
|
||||||
background-size: 24px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ scripts/fetchdep.sh matrix-org matrix-js-sdk
|
||||||
pushd matrix-js-sdk
|
pushd matrix-js-sdk
|
||||||
yarn link
|
yarn link
|
||||||
yarn install $@
|
yarn install $@
|
||||||
yarn build
|
|
||||||
popd
|
popd
|
||||||
|
|
||||||
yarn link matrix-js-sdk
|
yarn link matrix-js-sdk
|
||||||
|
|
|
@ -20,6 +20,7 @@ popd
|
||||||
yarn link matrix-js-sdk
|
yarn link matrix-js-sdk
|
||||||
yarn link
|
yarn link
|
||||||
yarn install
|
yarn install
|
||||||
|
yarn reskindex
|
||||||
|
|
||||||
# Finally, set up element-web
|
# Finally, set up element-web
|
||||||
scripts/fetchdep.sh vector-im element-web
|
scripts/fetchdep.sh vector-im element-web
|
||||||
|
|
|
@ -341,7 +341,8 @@ export default class CallHandler {
|
||||||
title: _t("Answered Elsewhere"),
|
title: _t("Answered Elsewhere"),
|
||||||
description: _t("The call was answered on another device."),
|
description: _t("The call was answered on another device."),
|
||||||
});
|
});
|
||||||
} else {
|
} else if (oldState !== CallState.Fledgling) {
|
||||||
|
// don't play the end-call sound for calls that never got off the ground
|
||||||
this.play(AudioID.CallEnd);
|
this.play(AudioID.CallEnd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -616,6 +617,18 @@ export default class CallHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns true if we are currently in any call where we haven't put the remote party on hold
|
||||||
|
*/
|
||||||
|
hasAnyUnheldCall() {
|
||||||
|
for (const call of this.calls.values()) {
|
||||||
|
if (call.state === CallState.Ended) continue;
|
||||||
|
if (!call.isRemoteOnHold()) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private async startCallApp(roomId: string, type: string) {
|
private async startCallApp(roomId: string, type: string) {
|
||||||
dis.dispatch({
|
dis.dispatch({
|
||||||
action: 'appsDrawer',
|
action: 'appsDrawer',
|
||||||
|
|
|
@ -163,7 +163,7 @@ const transformTags: IExtendedSanitizeOptions["transformTags"] = { // custom to
|
||||||
attribs.target = '_blank'; // by default
|
attribs.target = '_blank'; // by default
|
||||||
|
|
||||||
const transformed = tryTransformPermalinkToLocalHref(attribs.href);
|
const transformed = tryTransformPermalinkToLocalHref(attribs.href);
|
||||||
if (transformed !== attribs.href || attribs.href.match(linkifyMatrix.VECTOR_URL_PATTERN)) {
|
if (transformed !== attribs.href || attribs.href.match(linkifyMatrix.ELEMENT_URL_PATTERN)) {
|
||||||
attribs.href = transformed;
|
attribs.href = transformed;
|
||||||
delete attribs.target;
|
delete attribs.target;
|
||||||
}
|
}
|
||||||
|
@ -438,13 +438,14 @@ export function bodyToHtml(content: IContent, highlights: string[], opts: IOpts
|
||||||
delete sanitizeParams.textFilter;
|
delete sanitizeParams.textFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const contentBody = isDisplayedWithHtml ? safeBody : strippedBody;
|
||||||
if (opts.returnString) {
|
if (opts.returnString) {
|
||||||
return isDisplayedWithHtml ? safeBody : strippedBody;
|
return contentBody;
|
||||||
}
|
}
|
||||||
|
|
||||||
let emojiBody = false;
|
let emojiBody = false;
|
||||||
if (!opts.disableBigEmoji && bodyHasEmoji) {
|
if (!opts.disableBigEmoji && bodyHasEmoji) {
|
||||||
let contentBodyTrimmed = strippedBody !== undefined ? strippedBody.trim() : '';
|
let contentBodyTrimmed = contentBody !== undefined ? contentBody.trim() : '';
|
||||||
|
|
||||||
// Ignore spaces in body text. Emojis with spaces in between should
|
// Ignore spaces in body text. Emojis with spaces in between should
|
||||||
// still be counted as purely emoji messages.
|
// still be counted as purely emoji messages.
|
||||||
|
|
|
@ -166,6 +166,32 @@ export const Commands = [
|
||||||
},
|
},
|
||||||
category: CommandCategories.messages,
|
category: CommandCategories.messages,
|
||||||
}),
|
}),
|
||||||
|
new Command({
|
||||||
|
command: 'tableflip',
|
||||||
|
args: '<message>',
|
||||||
|
description: _td('Prepends (╯°□°)╯︵ ┻━┻ to a plain-text message'),
|
||||||
|
runFn: function(roomId, args) {
|
||||||
|
let message = '(╯°□°)╯︵ ┻━┻';
|
||||||
|
if (args) {
|
||||||
|
message = message + ' ' + args;
|
||||||
|
}
|
||||||
|
return success(MatrixClientPeg.get().sendTextMessage(roomId, message));
|
||||||
|
},
|
||||||
|
category: CommandCategories.messages,
|
||||||
|
}),
|
||||||
|
new Command({
|
||||||
|
command: 'unflip',
|
||||||
|
args: '<message>',
|
||||||
|
description: _td('Prepends ┬──┬ ノ( ゜-゜ノ) to a plain-text message'),
|
||||||
|
runFn: function(roomId, args) {
|
||||||
|
let message = '┬──┬ ノ( ゜-゜ノ)';
|
||||||
|
if (args) {
|
||||||
|
message = message + ' ' + args;
|
||||||
|
}
|
||||||
|
return success(MatrixClientPeg.get().sendTextMessage(roomId, message));
|
||||||
|
},
|
||||||
|
category: CommandCategories.messages,
|
||||||
|
}),
|
||||||
new Command({
|
new Command({
|
||||||
command: 'lenny',
|
command: 'lenny',
|
||||||
args: '<message>',
|
args: '<message>',
|
||||||
|
|
|
@ -45,8 +45,13 @@ const SSOButton: React.FC<ISSOButtonProps> = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
let icon;
|
let icon;
|
||||||
if (idp && idp.icon && idp.icon.startsWith("https://")) {
|
if (typeof idp?.icon === "string" && (idp.icon.startsWith("mxc://") || idp.icon.startsWith("https://"))) {
|
||||||
icon = <img src={idp.icon} height="24" width="24" alt={label} />;
|
icon = <img
|
||||||
|
src={matrixClient.mxcUrlToHttp(idp.icon, 24, 24, "crop", true)}
|
||||||
|
height="24"
|
||||||
|
width="24"
|
||||||
|
alt={label}
|
||||||
|
/>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const classes = classNames("mx_SSOButton", {
|
const classes = classNames("mx_SSOButton", {
|
||||||
|
|
|
@ -19,7 +19,7 @@ import React, { createRef, CSSProperties, ReactNode } from 'react';
|
||||||
import dis from '../../../dispatcher/dispatcher';
|
import dis from '../../../dispatcher/dispatcher';
|
||||||
import CallHandler from '../../../CallHandler';
|
import CallHandler from '../../../CallHandler';
|
||||||
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t, _td } from '../../../languageHandler';
|
||||||
import VideoFeed, { VideoFeedType } from "./VideoFeed";
|
import VideoFeed, { VideoFeedType } from "./VideoFeed";
|
||||||
import RoomAvatar from "../avatars/RoomAvatar";
|
import RoomAvatar from "../avatars/RoomAvatar";
|
||||||
import { CallState, CallType, MatrixCall } from 'matrix-js-sdk/src/webrtc/call';
|
import { CallState, CallType, MatrixCall } from 'matrix-js-sdk/src/webrtc/call';
|
||||||
|
@ -423,7 +423,9 @@ export default class CallView extends React.Component<IProps, IState> {
|
||||||
const isOnHold = this.state.isLocalOnHold || this.state.isRemoteOnHold;
|
const isOnHold = this.state.isLocalOnHold || this.state.isRemoteOnHold;
|
||||||
let onHoldText = null;
|
let onHoldText = null;
|
||||||
if (this.state.isRemoteOnHold) {
|
if (this.state.isRemoteOnHold) {
|
||||||
onHoldText = _t("You held the call <a>Resume</a>", {}, {
|
const holdString = CallHandler.sharedInstance().hasAnyUnheldCall() ?
|
||||||
|
_td("You held the call <a>Switch</a>") : _td("You held the call <a>Resume</a>");
|
||||||
|
onHoldText = _t(holdString, {}, {
|
||||||
a: sub => <AccessibleButton kind="link" onClick={this.onCallResumeClick}>
|
a: sub => <AccessibleButton kind="link" onClick={this.onCallResumeClick}>
|
||||||
{sub}
|
{sub}
|
||||||
</AccessibleButton>,
|
</AccessibleButton>,
|
||||||
|
@ -478,20 +480,6 @@ export default class CallView extends React.Component<IProps, IState> {
|
||||||
mx_CallView_voice: true,
|
mx_CallView_voice: true,
|
||||||
mx_CallView_voice_hold: isOnHold,
|
mx_CallView_voice_hold: isOnHold,
|
||||||
});
|
});
|
||||||
let secondaryCallAvatar: ReactNode;
|
|
||||||
|
|
||||||
if (this.props.secondaryCall) {
|
|
||||||
const secAvatarSize = this.props.pipMode ? 40 : 100;
|
|
||||||
secondaryCallAvatar = <div className="mx_CallView_voice_secondaryAvatarContainer"
|
|
||||||
style={{width: secAvatarSize, height: secAvatarSize}}
|
|
||||||
>
|
|
||||||
<RoomAvatar
|
|
||||||
room={secCallRoom}
|
|
||||||
height={secAvatarSize}
|
|
||||||
width={secAvatarSize}
|
|
||||||
/>
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
contentView = <div className={classes} onMouseMove={this.onMouseMove}>
|
contentView = <div className={classes} onMouseMove={this.onMouseMove}>
|
||||||
<div className="mx_CallView_voice_avatarsContainer">
|
<div className="mx_CallView_voice_avatarsContainer">
|
||||||
|
@ -502,7 +490,6 @@ export default class CallView extends React.Component<IProps, IState> {
|
||||||
width={avatarSize}
|
width={avatarSize}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{secondaryCallAvatar}
|
|
||||||
</div>
|
</div>
|
||||||
<div className="mx_CallView_voice_holdText">{onHoldText}</div>
|
<div className="mx_CallView_voice_holdText">{onHoldText}</div>
|
||||||
{callControls}
|
{callControls}
|
||||||
|
@ -546,7 +533,7 @@ export default class CallView extends React.Component<IProps, IState> {
|
||||||
<AccessibleButton element='span' onClick={this.onSecondaryRoomAvatarClick}>
|
<AccessibleButton element='span' onClick={this.onSecondaryRoomAvatarClick}>
|
||||||
<RoomAvatar room={secCallRoom} height={16} width={16} />
|
<RoomAvatar room={secCallRoom} height={16} width={16} />
|
||||||
<span className="mx_CallView_secondaryCall_roomName">
|
<span className="mx_CallView_secondaryCall_roomName">
|
||||||
{_t("%(name)s paused", { name: secCallRoom.name })}
|
{_t("%(name)s on hold", { name: secCallRoom.name })}
|
||||||
</span>
|
</span>
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
</span>;
|
</span>;
|
||||||
|
|
|
@ -24,7 +24,7 @@ import { ActionPayload } from '../../../dispatcher/payloads';
|
||||||
import CallHandler from '../../../CallHandler';
|
import CallHandler from '../../../CallHandler';
|
||||||
import RoomAvatar from '../avatars/RoomAvatar';
|
import RoomAvatar from '../avatars/RoomAvatar';
|
||||||
import FormButton from '../elements/FormButton';
|
import FormButton from '../elements/FormButton';
|
||||||
import { CallState } from 'matrix-js-sdk/lib/webrtc/call';
|
import { CallState } from 'matrix-js-sdk/src/webrtc/call';
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
}
|
}
|
||||||
|
|
174
src/effects/fireworks/index.ts
Normal file
174
src/effects/fireworks/index.ts
Normal file
|
@ -0,0 +1,174 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 Nurjin Jafar
|
||||||
|
Copyright 2020 Nordeck IT + Consulting GmbH.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import ICanvasEffect from '../ICanvasEffect';
|
||||||
|
|
||||||
|
export type FireworksOptions = {
|
||||||
|
/**
|
||||||
|
* max fireworks count
|
||||||
|
*/
|
||||||
|
maxCount: number;
|
||||||
|
/**
|
||||||
|
* gravity value that firework adds to shift from it's start position
|
||||||
|
*/
|
||||||
|
gravity: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
type FireworksParticle = {
|
||||||
|
/**
|
||||||
|
* color
|
||||||
|
*/
|
||||||
|
color: string;
|
||||||
|
/**
|
||||||
|
* x,y are the point where the particle starts to position on canvas
|
||||||
|
*/
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
/**
|
||||||
|
* vx,vy shift values from x and y
|
||||||
|
*/
|
||||||
|
vx: number;
|
||||||
|
vy: number;
|
||||||
|
/**
|
||||||
|
* the alpha opacity of the firework particle (between 0 and 1, where 1 is opaque and 0 is invisible)
|
||||||
|
*/
|
||||||
|
alpha: number;
|
||||||
|
/**
|
||||||
|
* w,h width and height
|
||||||
|
*/
|
||||||
|
w: number;
|
||||||
|
h: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DefaultOptions: FireworksOptions = {
|
||||||
|
maxCount: 500,
|
||||||
|
gravity: 0.05,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class Fireworks implements ICanvasEffect {
|
||||||
|
private readonly options: FireworksOptions;
|
||||||
|
|
||||||
|
constructor(options: { [key: string]: any }) {
|
||||||
|
this.options = {...DefaultOptions, ...options};
|
||||||
|
}
|
||||||
|
|
||||||
|
private context: CanvasRenderingContext2D | null = null;
|
||||||
|
private supportsAnimationFrame = window.requestAnimationFrame;
|
||||||
|
private particles: Array<FireworksParticle> = [];
|
||||||
|
public isRunning: boolean;
|
||||||
|
|
||||||
|
public start = async (canvas: HTMLCanvasElement, timeout = 3000) => {
|
||||||
|
if (!canvas) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.isRunning = true;
|
||||||
|
this.context = canvas.getContext('2d');
|
||||||
|
this.supportsAnimationFrame.call(window, this.updateWorld);
|
||||||
|
if (timeout) {
|
||||||
|
window.setTimeout(this.stop, timeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateWorld = () => {
|
||||||
|
if (!this.isRunning && this.particles.length === 0) return;
|
||||||
|
this.update();
|
||||||
|
this.paint();
|
||||||
|
this.supportsAnimationFrame.call(window, this.updateWorld);
|
||||||
|
}
|
||||||
|
|
||||||
|
private update = () => {
|
||||||
|
if (this.particles.length < this.options.maxCount && this.isRunning) {
|
||||||
|
this.createFirework();
|
||||||
|
}
|
||||||
|
const alive = [];
|
||||||
|
for (let i=0; i<this.particles.length; i++) {
|
||||||
|
if (this.move(this.particles[i])) {
|
||||||
|
alive.push(this.particles[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.particles = alive;
|
||||||
|
}
|
||||||
|
|
||||||
|
private paint = () => {
|
||||||
|
if (!this.context || !this.context.canvas) return;
|
||||||
|
this.context.globalCompositeOperation = 'destination-out';
|
||||||
|
this.context.fillStyle = "rgba(0,0,0,0.5)";
|
||||||
|
this.context.fillRect(0, 0, this.context.canvas.width, this.context.canvas.height);
|
||||||
|
this.context.globalCompositeOperation = 'lighter';
|
||||||
|
for (let i=0; i<this.particles.length; i++) {
|
||||||
|
this.drawParticle(this.particles[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private createFirework = () => {
|
||||||
|
if (!this.context || !this.context.canvas) return;
|
||||||
|
const width = this.context.canvas.width;
|
||||||
|
const height = this.context.canvas.height;
|
||||||
|
const xPoint = Math.random() * (width - 200) + 100;
|
||||||
|
const yPoint = Math.random() * (height - 200) + 100;
|
||||||
|
const nFire = Math.random() * 50 + 100;
|
||||||
|
const color = "rgb("+(~~(Math.random()*200+55))+","
|
||||||
|
+(~~(Math.random()*200+55))+","+(~~(Math.random()*200+55))+")";
|
||||||
|
for (let i=0; i<nFire; i++) {
|
||||||
|
const particle = <FireworksParticle>{};
|
||||||
|
particle.color = color;
|
||||||
|
particle.w = particle.h = Math.random() * 4 + 1;
|
||||||
|
particle.x = xPoint - particle.w / 2;
|
||||||
|
particle.y = yPoint - particle.h / 2;
|
||||||
|
particle.vx = (Math.random()-0.5)*10;
|
||||||
|
particle.vy = (Math.random()-0.5)*10;
|
||||||
|
particle.alpha = Math.random()*.5+.5;
|
||||||
|
const vy = Math.sqrt(25 - particle.vx * particle.vx);
|
||||||
|
if (Math.abs(particle.vy) > vy) {
|
||||||
|
particle.vy = particle.vy > 0 ? vy: -vy;
|
||||||
|
}
|
||||||
|
this.particles.push(particle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public stop = async () => {
|
||||||
|
this.isRunning = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private drawParticle = (particle: FireworksParticle): void => {
|
||||||
|
if (!this.context || !this.context.canvas) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.context.save();
|
||||||
|
this.context.beginPath();
|
||||||
|
|
||||||
|
this.context.translate(particle.x + particle.w / 2, particle.y + particle.h / 2);
|
||||||
|
this.context.arc(0, 0, particle.w, 0, Math.PI * 2);
|
||||||
|
this.context.fillStyle = particle.color;
|
||||||
|
this.context.globalAlpha = particle.alpha;
|
||||||
|
|
||||||
|
this.context.closePath();
|
||||||
|
this.context.fill();
|
||||||
|
this.context.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private move = (particle: FireworksParticle) => {
|
||||||
|
particle.x += particle.vx;
|
||||||
|
particle.vy += this.options.gravity;
|
||||||
|
particle.y += particle.vy;
|
||||||
|
particle.alpha -= 0.01;
|
||||||
|
return !(particle.x <= -particle.w || particle.x >= screen.width ||
|
||||||
|
particle.y >= screen.height ||
|
||||||
|
particle.alpha <= 0);
|
||||||
|
}
|
||||||
|
}
|
|
@ -47,23 +47,47 @@ type ConfettiOptions = {
|
||||||
/**
|
/**
|
||||||
* max confetti count
|
* max confetti count
|
||||||
*/
|
*/
|
||||||
maxCount: number,
|
maxCount: number;
|
||||||
/**
|
/**
|
||||||
* particle animation speed
|
* particle animation speed
|
||||||
*/
|
*/
|
||||||
speed: number,
|
speed: number;
|
||||||
/**
|
/**
|
||||||
* the confetti animation frame interval in milliseconds
|
* the confetti animation frame interval in milliseconds
|
||||||
*/
|
*/
|
||||||
frameInterval: number,
|
frameInterval: number;
|
||||||
/**
|
/**
|
||||||
* the alpha opacity of the confetti (between 0 and 1, where 1 is opaque and 0 is invisible)
|
* the alpha opacity of the confetti (between 0 and 1, where 1 is opaque and 0 is invisible)
|
||||||
*/
|
*/
|
||||||
alpha: number,
|
alpha: number;
|
||||||
/**
|
/**
|
||||||
* use gradient instead of solid particle color
|
* use gradient instead of solid particle color
|
||||||
*/
|
*/
|
||||||
gradient: boolean,
|
gradient: boolean;
|
||||||
|
};
|
||||||
|
type FireworksOptions = {
|
||||||
|
/**
|
||||||
|
* max fireworks count
|
||||||
|
*/
|
||||||
|
maxCount: number;
|
||||||
|
/**
|
||||||
|
* gravity value that firework adds to shift from it's start position
|
||||||
|
*/
|
||||||
|
gravity: number;
|
||||||
|
}
|
||||||
|
type SnowfallOptions = {
|
||||||
|
/**
|
||||||
|
* The maximum number of snowflakes to render at a given time
|
||||||
|
*/
|
||||||
|
maxCount: number;
|
||||||
|
/**
|
||||||
|
* The amount of gravity to apply to the snowflakes
|
||||||
|
*/
|
||||||
|
gravity: number;
|
||||||
|
/**
|
||||||
|
* The amount of drift (horizontal sway) to apply to the snowflakes. Each snowflake varies.
|
||||||
|
*/
|
||||||
|
maxDrift: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -84,6 +108,29 @@ export const CHAT_EFFECTS: Array<Effect<{ [key: string]: any }>> = [
|
||||||
gradient: false,
|
gradient: false,
|
||||||
},
|
},
|
||||||
} as Effect<ConfettiOptions>,
|
} as Effect<ConfettiOptions>,
|
||||||
|
{
|
||||||
|
emojis: ['🎆'],
|
||||||
|
msgType: 'nic.custom.fireworks',
|
||||||
|
command: 'fireworks',
|
||||||
|
description: () => _td("Sends the given message with fireworks"),
|
||||||
|
fallbackMessage: () => _t("sends fireworks") + " 🎆",
|
||||||
|
options: {
|
||||||
|
maxCount: 500,
|
||||||
|
gravity: 0.05,
|
||||||
|
},
|
||||||
|
} as Effect<FireworksOptions>,
|
||||||
|
{
|
||||||
|
emojis: ['❄', '🌨'],
|
||||||
|
msgType: 'io.element.effect.snowfall',
|
||||||
|
command: 'snowfall',
|
||||||
|
description: () => _td("Sends the given message with snowfall"),
|
||||||
|
fallbackMessage: () => _t("sends snowfall") + " ❄",
|
||||||
|
options: {
|
||||||
|
maxCount: 200,
|
||||||
|
gravity: 0.05,
|
||||||
|
maxDrift: 5,
|
||||||
|
},
|
||||||
|
} as Effect<SnowfallOptions>,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
|
148
src/effects/snowfall/index.ts
Normal file
148
src/effects/snowfall/index.ts
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
import ICanvasEffect from '../ICanvasEffect';
|
||||||
|
import { arrayFastClone } from "../../utils/arrays";
|
||||||
|
|
||||||
|
export type SnowfallOptions = {
|
||||||
|
/**
|
||||||
|
* The maximum number of snowflakes to render at a given time
|
||||||
|
*/
|
||||||
|
maxCount: number;
|
||||||
|
/**
|
||||||
|
* The amount of gravity to apply to the snowflakes
|
||||||
|
*/
|
||||||
|
gravity: number;
|
||||||
|
/**
|
||||||
|
* The amount of drift (horizontal sway) to apply to the snowflakes. Each snowflake varies.
|
||||||
|
*/
|
||||||
|
maxDrift: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
type Snowflake = {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
xCol: number;
|
||||||
|
diameter: number;
|
||||||
|
maximumDrift: number;
|
||||||
|
gravity: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DefaultOptions: SnowfallOptions = {
|
||||||
|
maxCount: 200,
|
||||||
|
gravity: 0.05,
|
||||||
|
maxDrift: 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
const KEY_FRAME_INTERVAL = 15; // 15ms, roughly
|
||||||
|
|
||||||
|
export default class Snowfall implements ICanvasEffect {
|
||||||
|
private readonly options: SnowfallOptions;
|
||||||
|
|
||||||
|
constructor(options: { [key: string]: any }) {
|
||||||
|
this.options = {...DefaultOptions, ...options};
|
||||||
|
}
|
||||||
|
|
||||||
|
private context: CanvasRenderingContext2D | null = null;
|
||||||
|
private particles: Array<Snowflake> = [];
|
||||||
|
private lastAnimationTime: number;
|
||||||
|
|
||||||
|
public isRunning: boolean;
|
||||||
|
|
||||||
|
public start = async (canvas: HTMLCanvasElement, timeout = 3000) => {
|
||||||
|
if (!canvas) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.context = canvas.getContext('2d');
|
||||||
|
this.particles = [];
|
||||||
|
const count = this.options.maxCount;
|
||||||
|
while (this.particles.length < count) {
|
||||||
|
this.particles.push(this.resetParticle({} as Snowflake, canvas.width, canvas.height));
|
||||||
|
}
|
||||||
|
this.isRunning = true;
|
||||||
|
requestAnimationFrame(this.renderLoop);
|
||||||
|
if (timeout) {
|
||||||
|
window.setTimeout(this.stop, timeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public stop = async () => {
|
||||||
|
this.isRunning = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private resetParticle = (particle: Snowflake, width: number, height: number): Snowflake => {
|
||||||
|
particle.x = Math.random() * width;
|
||||||
|
particle.y = Math.random() * -height;
|
||||||
|
particle.xCol = particle.x;
|
||||||
|
particle.diameter = (Math.random() * 7) + 4;
|
||||||
|
particle.maximumDrift = (Math.random() * this.options.maxDrift) + 3.5;
|
||||||
|
particle.gravity = this.options.gravity + (Math.random() * 6) + 4;
|
||||||
|
return particle;
|
||||||
|
}
|
||||||
|
|
||||||
|
private renderLoop = (): void => {
|
||||||
|
if (!this.context || !this.context.canvas) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.particles.length === 0) {
|
||||||
|
this.context.clearRect(0, 0, this.context.canvas.width, this.context.canvas.height);
|
||||||
|
} else {
|
||||||
|
const timeDelta = Date.now() - this.lastAnimationTime;
|
||||||
|
if (timeDelta >= KEY_FRAME_INTERVAL || !this.lastAnimationTime) {
|
||||||
|
// Clear the screen first
|
||||||
|
this.context.clearRect(0, 0, this.context.canvas.width, this.context.canvas.height);
|
||||||
|
|
||||||
|
this.lastAnimationTime = Date.now();
|
||||||
|
this.animateAndRenderSnowflakes();
|
||||||
|
}
|
||||||
|
requestAnimationFrame(this.renderLoop);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private animateAndRenderSnowflakes() {
|
||||||
|
if (!this.context || !this.context.canvas) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const height = this.context.canvas.height;
|
||||||
|
for (const particle of arrayFastClone(this.particles)) {
|
||||||
|
particle.y += particle.gravity;
|
||||||
|
|
||||||
|
// We treat the drift as a sine function to have a more fluid-like movement instead
|
||||||
|
// of a pong-like movement off walls of the X column. This means that for
|
||||||
|
// $x=A\sin(\frac{2\pi}{P}y)$ we use the `maximumDrift` as the amplitude (A) and a
|
||||||
|
// large multiplier to create a very long waveform through P.
|
||||||
|
const peakDistance = 75 * particle.maximumDrift;
|
||||||
|
const PI2 = Math.PI * 2;
|
||||||
|
particle.x = particle.maximumDrift * Math.sin((PI2 / peakDistance) * particle.y);
|
||||||
|
particle.x += particle.xCol; // bring the particle to the right place
|
||||||
|
|
||||||
|
const radius = particle.diameter / 2;
|
||||||
|
this.context.save();
|
||||||
|
this.context.beginPath();
|
||||||
|
this.context.ellipse(particle.x, particle.y, radius, radius, 0, 0, 360);
|
||||||
|
this.context.fillStyle = '#eaeaea'; // grey so it shows up on the light theme
|
||||||
|
this.context.fill();
|
||||||
|
this.context.closePath();
|
||||||
|
this.context.restore();
|
||||||
|
|
||||||
|
// Remove any dead snowflakes
|
||||||
|
const maxBounds = radius * 4; // make sure it's *really* off screen
|
||||||
|
if (particle.y > (height + maxBounds)) {
|
||||||
|
const idx = this.particles.indexOf(particle);
|
||||||
|
this.particles.splice(idx, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -411,6 +411,8 @@
|
||||||
"Command error": "Command error",
|
"Command error": "Command error",
|
||||||
"Usage": "Usage",
|
"Usage": "Usage",
|
||||||
"Prepends ¯\\_(ツ)_/¯ to a plain-text message": "Prepends ¯\\_(ツ)_/¯ to a plain-text message",
|
"Prepends ¯\\_(ツ)_/¯ to a plain-text message": "Prepends ¯\\_(ツ)_/¯ to a plain-text message",
|
||||||
|
"Prepends (╯°□°)╯︵ ┻━┻ to a plain-text message": "Prepends (╯°□°)╯︵ ┻━┻ to a plain-text message",
|
||||||
|
"Prepends ┬──┬ ノ( ゜-゜ノ) to a plain-text message": "Prepends ┬──┬ ノ( ゜-゜ノ) to a plain-text message",
|
||||||
"Prepends ( ͡° ͜ʖ ͡°) to a plain-text message": "Prepends ( ͡° ͜ʖ ͡°) to a plain-text message",
|
"Prepends ( ͡° ͜ʖ ͡°) to a plain-text message": "Prepends ( ͡° ͜ʖ ͡°) to a plain-text message",
|
||||||
"Sends a message as plain text, without interpreting it as markdown": "Sends a message as plain text, without interpreting it as markdown",
|
"Sends a message as plain text, without interpreting it as markdown": "Sends a message as plain text, without interpreting it as markdown",
|
||||||
"Sends a message as html, without interpreting it as markdown": "Sends a message as html, without interpreting it as markdown",
|
"Sends a message as html, without interpreting it as markdown": "Sends a message as html, without interpreting it as markdown",
|
||||||
|
@ -847,13 +849,18 @@
|
||||||
"This is your list of users/servers you have blocked - don't leave the room!": "This is your list of users/servers you have blocked - don't leave the room!",
|
"This is your list of users/servers you have blocked - don't leave the room!": "This is your list of users/servers you have blocked - don't leave the room!",
|
||||||
"Sends the given message with confetti": "Sends the given message with confetti",
|
"Sends the given message with confetti": "Sends the given message with confetti",
|
||||||
"sends confetti": "sends confetti",
|
"sends confetti": "sends confetti",
|
||||||
|
"Sends the given message with fireworks": "Sends the given message with fireworks",
|
||||||
|
"sends fireworks": "sends fireworks",
|
||||||
|
"Sends the given message with snowfall": "Sends the given message with snowfall",
|
||||||
|
"sends snowfall": "sends snowfall",
|
||||||
|
"You held the call <a>Switch</a>": "You held the call <a>Switch</a>",
|
||||||
"You held the call <a>Resume</a>": "You held the call <a>Resume</a>",
|
"You held the call <a>Resume</a>": "You held the call <a>Resume</a>",
|
||||||
"%(peerName)s held the call": "%(peerName)s held the call",
|
"%(peerName)s held the call": "%(peerName)s held the call",
|
||||||
"Video Call": "Video Call",
|
"Video Call": "Video Call",
|
||||||
"Voice Call": "Voice Call",
|
"Voice Call": "Voice Call",
|
||||||
"Fill Screen": "Fill Screen",
|
"Fill Screen": "Fill Screen",
|
||||||
"Return to call": "Return to call",
|
"Return to call": "Return to call",
|
||||||
"%(name)s paused": "%(name)s paused",
|
"%(name)s on hold": "%(name)s on hold",
|
||||||
"Unknown caller": "Unknown caller",
|
"Unknown caller": "Unknown caller",
|
||||||
"Incoming voice call": "Incoming voice call",
|
"Incoming voice call": "Incoming voice call",
|
||||||
"Incoming video call": "Incoming video call",
|
"Incoming video call": "Incoming video call",
|
||||||
|
|
|
@ -183,12 +183,14 @@ const escapeRegExp = function(string) {
|
||||||
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||||
};
|
};
|
||||||
|
|
||||||
// Recognise URLs from both our local vector and official vector as vector.
|
// Recognise URLs from both our local and official Element deployments.
|
||||||
// anyone else really should be using matrix.to.
|
// Anyone else really should be using matrix.to.
|
||||||
matrixLinkify.VECTOR_URL_PATTERN = "^(?:https?://)?(?:"
|
matrixLinkify.ELEMENT_URL_PATTERN =
|
||||||
+ escapeRegExp(window.location.host + window.location.pathname) + "|"
|
"^(?:https?://)?(?:" +
|
||||||
+ "(?:www\\.)?(?:riot|vector)\\.im/(?:app|beta|staging|develop)/"
|
escapeRegExp(window.location.host + window.location.pathname) + "|" +
|
||||||
+ ")(#.*)";
|
"(?:www\\.)?(?:riot|vector)\\.im/(?:app|beta|staging|develop)/|" +
|
||||||
|
"(?:app|beta|staging|develop)\\.element\\.io/" +
|
||||||
|
")(#.*)";
|
||||||
|
|
||||||
matrixLinkify.MATRIXTO_URL_PATTERN = "^(?:https?://)?(?:www\\.)?matrix\\.to/#/(([#@!+]).*)";
|
matrixLinkify.MATRIXTO_URL_PATTERN = "^(?:https?://)?(?:www\\.)?matrix\\.to/#/(([#@!+]).*)";
|
||||||
matrixLinkify.MATRIXTO_MD_LINK_PATTERN =
|
matrixLinkify.MATRIXTO_MD_LINK_PATTERN =
|
||||||
|
@ -253,7 +255,7 @@ matrixLinkify.options = {
|
||||||
target: function(href, type) {
|
target: function(href, type) {
|
||||||
if (type === 'url') {
|
if (type === 'url') {
|
||||||
const transformed = tryTransformPermalinkToLocalHref(href);
|
const transformed = tryTransformPermalinkToLocalHref(href);
|
||||||
if (transformed !== href || href.match(matrixLinkify.VECTOR_URL_PATTERN)) {
|
if (transformed !== href || href.match(matrixLinkify.ELEMENT_URL_PATTERN)) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return '_blank';
|
return '_blank';
|
||||||
|
|
|
@ -331,7 +331,7 @@ export function tryTransformPermalinkToLocalHref(permalink: string): string {
|
||||||
return permalink;
|
return permalink;
|
||||||
}
|
}
|
||||||
|
|
||||||
const m = permalink.match(matrixLinkify.VECTOR_URL_PATTERN);
|
const m = permalink.match(matrixLinkify.ELEMENT_URL_PATTERN);
|
||||||
if (m) {
|
if (m) {
|
||||||
return m[1];
|
return m[1];
|
||||||
}
|
}
|
||||||
|
@ -365,7 +365,7 @@ export function getPrimaryPermalinkEntity(permalink: string): string {
|
||||||
|
|
||||||
// If not a permalink, try the vector patterns.
|
// If not a permalink, try the vector patterns.
|
||||||
if (!permalinkParts) {
|
if (!permalinkParts) {
|
||||||
const m = permalink.match(matrixLinkify.VECTOR_URL_PATTERN);
|
const m = permalink.match(matrixLinkify.ELEMENT_URL_PATTERN);
|
||||||
if (m) {
|
if (m) {
|
||||||
// A bit of a hack, but it gets the job done
|
// A bit of a hack, but it gets the job done
|
||||||
const handler = new ElementPermalinkConstructor("http://localhost");
|
const handler = new ElementPermalinkConstructor("http://localhost");
|
||||||
|
|
42
yarn.lock
42
yarn.lock
|
@ -5058,9 +5058,9 @@ inherits@2, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3:
|
||||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||||
|
|
||||||
ini@^1.3.5, ini@~1.3.0:
|
ini@^1.3.5, ini@~1.3.0:
|
||||||
version "1.3.5"
|
version "1.3.7"
|
||||||
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
|
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.7.tgz#a09363e1911972ea16d7a8851005d84cf09a9a84"
|
||||||
integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
|
integrity sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==
|
||||||
|
|
||||||
inquirer@^7.0.0:
|
inquirer@^7.0.0:
|
||||||
version "7.3.2"
|
version "7.3.2"
|
||||||
|
@ -6429,6 +6429,13 @@ lru-cache@^5.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
yallist "^3.0.2"
|
yallist "^3.0.2"
|
||||||
|
|
||||||
|
lru-cache@^6.0.0:
|
||||||
|
version "6.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
|
||||||
|
integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
|
||||||
|
dependencies:
|
||||||
|
yallist "^4.0.0"
|
||||||
|
|
||||||
make-dir@^2.0.0, make-dir@^2.1.0:
|
make-dir@^2.0.0, make-dir@^2.1.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
|
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
|
||||||
|
@ -6513,8 +6520,8 @@ mathml-tag-names@^2.0.1:
|
||||||
integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==
|
integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==
|
||||||
|
|
||||||
"matrix-js-sdk@github:matrix-org/matrix-js-sdk#develop":
|
"matrix-js-sdk@github:matrix-org/matrix-js-sdk#develop":
|
||||||
version "9.3.0"
|
version "9.4.1"
|
||||||
resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/ff6612f9d0aa1a7c08b65a0b41c5ab997506016f"
|
resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/1717fcf499b943517213f2a81c41ffec0b50748e"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.12.5"
|
"@babel/runtime" "^7.12.5"
|
||||||
another-json "^0.2.0"
|
another-json "^0.2.0"
|
||||||
|
@ -6812,9 +6819,9 @@ node-modules-regexp@^1.0.0:
|
||||||
integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=
|
integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=
|
||||||
|
|
||||||
node-notifier@^8.0.0:
|
node-notifier@^8.0.0:
|
||||||
version "8.0.0"
|
version "8.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-8.0.0.tgz#a7eee2d51da6d0f7ff5094bc7108c911240c1620"
|
resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-8.0.1.tgz#f86e89bbc925f2b068784b31f382afdc6ca56be1"
|
||||||
integrity sha512-46z7DUmcjoYdaWyXouuFNNfUo6eFa94t23c53c+lG/9Cvauk4a98rAUp9672X5dxGdQmLpPzTxzu8f/OeEPaFA==
|
integrity sha512-BvEXF+UmsnAfYfoapKM9nGxnP+Wn7P91YfXmrKnfcYCx6VBeoN5Ez5Ogck6I8Bi5k4RlpqRYaw75pAwzX9OphA==
|
||||||
dependencies:
|
dependencies:
|
||||||
growly "^1.3.0"
|
growly "^1.3.0"
|
||||||
is-wsl "^2.2.0"
|
is-wsl "^2.2.0"
|
||||||
|
@ -8354,9 +8361,11 @@ semver@7.0.0:
|
||||||
integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==
|
integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==
|
||||||
|
|
||||||
semver@^7.2.1, semver@^7.3.2:
|
semver@^7.2.1, semver@^7.3.2:
|
||||||
version "7.3.2"
|
version "7.3.4"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97"
|
||||||
integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==
|
integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==
|
||||||
|
dependencies:
|
||||||
|
lru-cache "^6.0.0"
|
||||||
|
|
||||||
serialize-javascript@^2.1.2:
|
serialize-javascript@^2.1.2:
|
||||||
version "2.1.2"
|
version "2.1.2"
|
||||||
|
@ -9506,9 +9515,9 @@ uuid@^3.3.2:
|
||||||
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
|
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
|
||||||
|
|
||||||
uuid@^8.3.0:
|
uuid@^8.3.0:
|
||||||
version "8.3.1"
|
version "8.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.1.tgz#2ba2e6ca000da60fce5a196954ab241131e05a31"
|
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
|
||||||
integrity sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==
|
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
|
||||||
|
|
||||||
v8-compile-cache@^2.0.3:
|
v8-compile-cache@^2.0.3:
|
||||||
version "2.1.1"
|
version "2.1.1"
|
||||||
|
@ -9798,6 +9807,11 @@ yallist@^3.0.2:
|
||||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
|
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
|
||||||
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
|
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
|
||||||
|
|
||||||
|
yallist@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
|
||||||
|
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
|
||||||
|
|
||||||
yargs-parser@^10.0.0:
|
yargs-parser@^10.0.0:
|
||||||
version "10.1.0"
|
version "10.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8"
|
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8"
|
||||||
|
|
Loading…
Reference in a new issue