From 2c89be312af0cd69a8504556c4f5cb692b88b302 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Wed, 12 May 2021 13:30:00 +0100
Subject: [PATCH 1/9] Disable space fields whilst their form is busy
---
src/components/structures/SpaceRoomView.tsx | 2 ++
src/components/views/dialogs/SpaceSettingsDialog.tsx | 6 +++---
src/components/views/spaces/SpaceCreateMenu.tsx | 4 +++-
3 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/src/components/structures/SpaceRoomView.tsx b/src/components/structures/SpaceRoomView.tsx
index 004fa5d98f..ed0ae1afe7 100644
--- a/src/components/structures/SpaceRoomView.tsx
+++ b/src/components/structures/SpaceRoomView.tsx
@@ -451,6 +451,7 @@ const SpaceSetupFirstRooms = ({ space, title, description, onFinished }) => {
value={roomNames[i]}
onChange={ev => setRoomName(i, ev.target.value)}
autoFocus={i === 2}
+ disabled={busy}
/>;
});
@@ -658,6 +659,7 @@ const SpaceSetupPrivateInvite = ({ space, onFinished }) => {
ref={fieldRefs[i]}
onValidate={validateEmailRules}
autoFocus={i === 0}
+ disabled={busy}
/>;
});
diff --git a/src/components/views/dialogs/SpaceSettingsDialog.tsx b/src/components/views/dialogs/SpaceSettingsDialog.tsx
index dfee5d63e3..dc6052650a 100644
--- a/src/components/views/dialogs/SpaceSettingsDialog.tsx
+++ b/src/components/views/dialogs/SpaceSettingsDialog.tsx
@@ -116,13 +116,13 @@ const SpaceSettingsDialog: React.FC = ({ matrixClient: cli, space, onFin
diff --git a/src/components/views/spaces/SpaceCreateMenu.tsx b/src/components/views/spaces/SpaceCreateMenu.tsx
index b461e2230e..0ebf511018 100644
--- a/src/components/views/spaces/SpaceCreateMenu.tsx
+++ b/src/components/views/spaces/SpaceCreateMenu.tsx
@@ -178,7 +178,7 @@ const SpaceCreateMenu = ({ onFinished }) => {
From 607ca179716ce536a011bc2d8442aa05fd3c4279 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Wed, 12 May 2021 16:11:38 +0100
Subject: [PATCH 2/9] Iterate beta feedback dialog
---
res/css/views/dialogs/_BetaFeedbackDialog.scss | 2 +-
src/components/views/dialogs/BetaFeedbackDialog.tsx | 3 ++-
src/i18n/strings/en_EN.json | 3 ++-
src/settings/Settings.tsx | 4 ++--
4 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/res/css/views/dialogs/_BetaFeedbackDialog.scss b/res/css/views/dialogs/_BetaFeedbackDialog.scss
index fe3df01986..9f5f6b512e 100644
--- a/res/css/views/dialogs/_BetaFeedbackDialog.scss
+++ b/res/css/views/dialogs/_BetaFeedbackDialog.scss
@@ -16,7 +16,7 @@ limitations under the License.
.mx_BetaFeedbackDialog {
.mx_BetaFeedbackDialog_subheading {
- color: $secondary-fg-color;
+ color: $primary-fg-color;
font-size: $font-14px;
line-height: $font-20px;
margin-bottom: 24px;
diff --git a/src/components/views/dialogs/BetaFeedbackDialog.tsx b/src/components/views/dialogs/BetaFeedbackDialog.tsx
index 6619f11b33..1ae50dd66f 100644
--- a/src/components/views/dialogs/BetaFeedbackDialog.tsx
+++ b/src/components/views/dialogs/BetaFeedbackDialog.tsx
@@ -59,7 +59,7 @@ const BetaFeedbackDialog: React.FC = ({featureId, onFinished}) => {
return (
{ _t(info.feedbackSubheading) }
@@ -87,6 +87,7 @@ const BetaFeedbackDialog: React.FC
= ({featureId, onFinished}) => {
onChange={(ev) => {
setComment(ev.target.value);
}}
+ autoFocus={true}
/>
;
},
image: require("../../res/img/betas/spaces.png"),
- feedbackSubheading: _td("You’re using an early version of Spaces, " +
- "your feedback will really help inform the next versions."),
+ feedbackSubheading: _td("Your feedback will help make spaces better. " +
+ "The more detail you can go into, the better."),
feedbackLabel: "spaces-feedback",
},
},
From dd04b479a1c751da456c8d55236e6c661ce45e36 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Thu, 13 May 2021 10:20:27 +0100
Subject: [PATCH 3/9] Wrap decodeURIComponent in try-catch to protect against
malformed URIs
---
src/linkify-matrix.js | 14 +++++++++-----
src/utils/permalinks/Permalinks.ts | 11 ++++++++---
2 files changed, 17 insertions(+), 8 deletions(-)
diff --git a/src/linkify-matrix.js b/src/linkify-matrix.js
index 84a131f23a..feda257d8b 100644
--- a/src/linkify-matrix.js
+++ b/src/linkify-matrix.js
@@ -254,11 +254,15 @@ matrixLinkify.options = {
target: function(href, type) {
if (type === 'url') {
- const transformed = tryTransformPermalinkToLocalHref(href);
- if (transformed !== href || decodeURIComponent(href).match(matrixLinkify.ELEMENT_URL_PATTERN)) {
- return null;
- } else {
- return '_blank';
+ try {
+ const transformed = tryTransformPermalinkToLocalHref(href);
+ if (transformed !== href || decodeURIComponent(href).match(matrixLinkify.ELEMENT_URL_PATTERN)) {
+ return null;
+ } else {
+ return '_blank';
+ }
+ } catch (e) {
+ // malformed URI
}
}
return null;
diff --git a/src/utils/permalinks/Permalinks.ts b/src/utils/permalinks/Permalinks.ts
index 015ecca22e..d87c826cc2 100644
--- a/src/utils/permalinks/Permalinks.ts
+++ b/src/utils/permalinks/Permalinks.ts
@@ -346,9 +346,14 @@ export function tryTransformPermalinkToLocalHref(permalink: string): string {
return permalink;
}
- const m = decodeURIComponent(permalink).match(matrixLinkify.ELEMENT_URL_PATTERN);
- if (m) {
- return m[1];
+ try {
+ const m = decodeURIComponent(permalink).match(matrixLinkify.ELEMENT_URL_PATTERN);
+ if (m) {
+ return m[1];
+ }
+ } catch (e) {
+ // Not a valid URI
+ return permalink;
}
// A bit of a hack to convert permalinks of unknown origin to Element links
From 3af0138e9d1ee380bea09e8a837ffe718443c09b Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Thu, 13 May 2021 10:28:35 +0100
Subject: [PATCH 4/9] Update emoji icons to new style
---
res/css/views/messages/_MessageActionBar.scss | 1 +
res/img/element-icons/room/composer/emoji.svg | 10 +++++-----
res/img/element-icons/room/message-bar/emoji.svg | 6 ++----
3 files changed, 8 insertions(+), 9 deletions(-)
diff --git a/res/css/views/messages/_MessageActionBar.scss b/res/css/views/messages/_MessageActionBar.scss
index 3ecbef0d1f..d41ac3a4ba 100644
--- a/res/css/views/messages/_MessageActionBar.scss
+++ b/res/css/views/messages/_MessageActionBar.scss
@@ -85,6 +85,7 @@ limitations under the License.
left: 0;
height: 100%;
width: 100%;
+ mask-size: 18px;
mask-repeat: no-repeat;
mask-position: center;
background-color: $message-action-bar-fg-color;
diff --git a/res/img/element-icons/room/composer/emoji.svg b/res/img/element-icons/room/composer/emoji.svg
index 9613d9edd9..b02cb69364 100644
--- a/res/img/element-icons/room/composer/emoji.svg
+++ b/res/img/element-icons/room/composer/emoji.svg
@@ -1,7 +1,7 @@
diff --git a/res/img/element-icons/room/message-bar/emoji.svg b/res/img/element-icons/room/message-bar/emoji.svg
index 697f656b8a..07fee5b834 100644
--- a/res/img/element-icons/room/message-bar/emoji.svg
+++ b/res/img/element-icons/room/message-bar/emoji.svg
@@ -1,5 +1,3 @@
- ;
}
}
From 87ae47bd6114d660735bba82a71c4fc0883b5314 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Thu, 13 May 2021 13:59:10 +0100
Subject: [PATCH 7/9] tweak reactions row some more, third try lucky
---
res/css/views/messages/_ReactionsRow.scss | 36 ++++++++++++-------
src/components/views/messages/ReactionsRow.js | 5 ++-
2 files changed, 28 insertions(+), 13 deletions(-)
diff --git a/res/css/views/messages/_ReactionsRow.scss b/res/css/views/messages/_ReactionsRow.scss
index 15d251bd68..f1c19f45a9 100644
--- a/res/css/views/messages/_ReactionsRow.scss
+++ b/res/css/views/messages/_ReactionsRow.scss
@@ -20,23 +20,33 @@ limitations under the License.
.mx_ReactionsRow_addReactionButton {
position: relative;
- display: none;
- width: 16px;
- height: 16px;
+ display: none; // show on hover of the .mx_EventTile
+ width: 24px;
+ height: 24px;
vertical-align: middle;
- margin-left: 6px;
+ margin-left: 4px;
&::before {
content: '';
position: absolute;
height: 100%;
width: 100%;
- mask-size: cover;
+ mask-size: 16px;
mask-repeat: no-repeat;
mask-position: center;
background-color: $tertiary-fg-color;
mask-image: url('$(res)/img/element-icons/room/message-bar/emoji.svg');
}
+
+ &.mx_ReactionsRow_addReactionButton_active {
+ display: inline-block; // keep showing whilst the context menu is shown
+ }
+
+ &:hover, &.mx_ReactionsRow_addReactionButton_active {
+ &::before {
+ background-color: $primary-fg-color;
+ }
+ }
}
}
@@ -46,14 +56,16 @@ limitations under the License.
.mx_ReactionsRow_showAll {
text-decoration: none;
- font-size: $font-10px;
- font-weight: 600;
- margin-left: 6px;
+ font-size: $font-12px;
+ line-height: $font-20px;
+ margin-left: 4px;
vertical-align: middle;
- &:hover,
- &:link,
- &:visited {
- color: $accent-color;
+ &:link, &:visited {
+ color: $tertiary-fg-color
+ }
+
+ &:hover {
+ color: $primary-fg-color;
}
}
diff --git a/src/components/views/messages/ReactionsRow.js b/src/components/views/messages/ReactionsRow.js
index 2a67519d6b..a7997c0e32 100644
--- a/src/components/views/messages/ReactionsRow.js
+++ b/src/components/views/messages/ReactionsRow.js
@@ -17,6 +17,7 @@ limitations under the License.
import React from 'react';
import PropTypes from 'prop-types';
import { EventType } from "matrix-js-sdk/src/@types/event";
+import classNames from "classnames";
import * as sdk from '../../../index';
import { _t } from '../../../languageHandler';
@@ -43,7 +44,9 @@ const ReactButton = ({ mxEvent, reactions }) => {
return
Date: Thu, 13 May 2021 14:13:00 +0100
Subject: [PATCH 8/9] Convert to Typescript and move from ClientPeg to Context
---
res/css/views/messages/_ReactionsRow.scss | 2 +-
.../{ReactionsRow.js => ReactionsRow.tsx} | 55 ++++++++-------
...onsRowButton.js => ReactionsRowButton.tsx} | 70 ++++++++++---------
...oltip.js => ReactionsRowButtonTooltip.tsx} | 37 +++++-----
4 files changed, 87 insertions(+), 77 deletions(-)
rename src/components/views/messages/{ReactionsRow.js => ReactionsRow.tsx} (82%)
rename src/components/views/messages/{ReactionsRowButton.js => ReactionsRowButton.tsx} (73%)
rename src/components/views/messages/{ReactionsRowButtonTooltip.js => ReactionsRowButtonTooltip.tsx} (74%)
diff --git a/res/css/views/messages/_ReactionsRow.scss b/res/css/views/messages/_ReactionsRow.scss
index f1c19f45a9..244439bf74 100644
--- a/res/css/views/messages/_ReactionsRow.scss
+++ b/res/css/views/messages/_ReactionsRow.scss
@@ -62,7 +62,7 @@ limitations under the License.
vertical-align: middle;
&:link, &:visited {
- color: $tertiary-fg-color
+ color: $tertiary-fg-color;
}
&:hover {
diff --git a/src/components/views/messages/ReactionsRow.js b/src/components/views/messages/ReactionsRow.tsx
similarity index 82%
rename from src/components/views/messages/ReactionsRow.js
rename to src/components/views/messages/ReactionsRow.tsx
index a7997c0e32..e1fcbe5364 100644
--- a/src/components/views/messages/ReactionsRow.js
+++ b/src/components/views/messages/ReactionsRow.tsx
@@ -1,5 +1,5 @@
/*
-Copyright 2019 New Vector Ltd
+Copyright 2019, 2021 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.
@@ -14,29 +14,30 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import React from 'react';
-import PropTypes from 'prop-types';
-import { EventType } from "matrix-js-sdk/src/@types/event";
+import React from "react";
import classNames from "classnames";
+import { EventType } from "matrix-js-sdk/src/@types/event";
+import { MatrixEvent } from "matrix-js-sdk/src/models/event";
+import { Relations } from "matrix-js-sdk/src/models/relations";
-import * as sdk from '../../../index';
import { _t } from '../../../languageHandler';
import { isContentActionable } from '../../../utils/EventUtils';
-import {MatrixClientPeg} from '../../../MatrixClientPeg';
-import {replaceableComponent} from "../../../utils/replaceableComponent";
-import {ContextMenuTooltipButton} from "../../../accessibility/context_menu/ContextMenuTooltipButton";
-import {aboveLeftOf, ContextMenu, useContextMenu} from "../../structures/ContextMenu";
+import { replaceableComponent } from "../../../utils/replaceableComponent";
+import { ContextMenuTooltipButton } from "../../../accessibility/context_menu/ContextMenuTooltipButton";
+import { aboveLeftOf, ContextMenu, useContextMenu } from "../../structures/ContextMenu";
+import ReactionPicker from "../emojipicker/ReactionPicker";
+import ReactionsRowButton from "./ReactionsRowButton";
+import MatrixClientContext from "../../../contexts/MatrixClientContext";
// The maximum number of reactions to initially show on a message.
const MAX_ITEMS_WHEN_LIMITED = 8;
-const ReactButton = ({ mxEvent, reactions }) => {
+const ReactButton = ({ mxEvent, reactions }: IProps) => {
const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu();
let contextMenu;
if (menuDisplayed) {
const buttonRect = button.current.getBoundingClientRect();
- const ReactionPicker = sdk.getComponent('emojipicker.ReactionPicker');
contextMenu =
;
@@ -57,17 +58,24 @@ const ReactButton = ({ mxEvent, reactions }) => {
;
};
-@replaceableComponent("views.messages.ReactionsRow")
-export default class ReactionsRow extends React.PureComponent {
- static propTypes = {
- // The event we're displaying reactions for
- mxEvent: PropTypes.object.isRequired,
- // The Relations model from the JS SDK for reactions to `mxEvent`
- reactions: PropTypes.object,
- }
+interface IProps {
+ // The event we're displaying reactions for
+ mxEvent: MatrixEvent;
+ // The Relations model from the JS SDK for reactions to `mxEvent`
+ reactions?: Relations;
+}
- constructor(props) {
- super(props);
+interface IState {
+ myReactions: MatrixEvent[];
+ showAll: boolean;
+}
+
+@replaceableComponent("views.messages.ReactionsRow")
+export default class ReactionsRow extends React.PureComponent {
+ static contextType = MatrixClientContext;
+
+ constructor(props, context) {
+ super(props, context);
if (props.reactions) {
props.reactions.on("Relations.add", this.onReactionsChange);
@@ -123,7 +131,7 @@ export default class ReactionsRow extends React.PureComponent {
if (!reactions) {
return null;
}
- const userId = MatrixClientPeg.get().getUserId();
+ const userId = this.context.getUserId();
const myReactions = reactions.getAnnotationsBySender()[userId];
if (!myReactions) {
return null;
@@ -145,7 +153,6 @@ export default class ReactionsRow extends React.PureComponent {
return null;
}
- const ReactionsRowButton = sdk.getComponent('messages.ReactionsRowButton');
let items = reactions.getSortedAnnotationsByKey().map(([content, events]) => {
const count = events.size;
if (!count) {
@@ -182,7 +189,7 @@ export default class ReactionsRow extends React.PureComponent {
;
}
- const cli = MatrixClientPeg.get();
+ const cli = this.context;
let addReactionButton;
if (cli.getRoom(mxEvent.getRoomId()).currentState.maySendEvent(EventType.Reaction, cli.getUserId())) {
diff --git a/src/components/views/messages/ReactionsRowButton.js b/src/components/views/messages/ReactionsRowButton.tsx
similarity index 73%
rename from src/components/views/messages/ReactionsRowButton.js
rename to src/components/views/messages/ReactionsRowButton.tsx
index b37a949e57..393c6bca88 100644
--- a/src/components/views/messages/ReactionsRowButton.js
+++ b/src/components/views/messages/ReactionsRowButton.tsx
@@ -1,5 +1,5 @@
/*
-Copyright 2019 New Vector Ltd
+Copyright 2019, 2021 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.
@@ -14,49 +14,54 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import React from 'react';
-import PropTypes from 'prop-types';
-import classNames from 'classnames';
+import React from "react";
+import classNames from "classnames";
+import { MatrixEvent } from "matrix-js-sdk/src/models/event";
-import {MatrixClientPeg} from '../../../MatrixClientPeg';
-import * as sdk from '../../../index';
import { _t } from '../../../languageHandler';
import { formatCommaSeparatedList } from '../../../utils/FormattingUtils';
import dis from "../../../dispatcher/dispatcher";
-import {replaceableComponent} from "../../../utils/replaceableComponent";
+import { replaceableComponent } from "../../../utils/replaceableComponent";
+import ReactionsRowButtonTooltip from "./ReactionsRowButtonTooltip";
+import AccessibleButton from "../elements/AccessibleButton";
+import MatrixClientContext from "../../../contexts/MatrixClientContext";
+
+interface IProps {
+ // The event we're displaying reactions for
+ mxEvent: MatrixEvent;
+ // The reaction content / key / emoji
+ content: string;
+ // The count of votes for this key
+ count: number;
+ // A Set of Martix reaction events for this key
+ reactionEvents: Set;
+ // A possible Matrix event if the current user has voted for this type
+ myReactionEvent?: MatrixEvent;
+}
+
+interface IState {
+ tooltipRendered: boolean;
+ tooltipVisible: boolean;
+}
@replaceableComponent("views.messages.ReactionsRowButton")
-export default class ReactionsRowButton extends React.PureComponent {
- static propTypes = {
- // The event we're displaying reactions for
- mxEvent: PropTypes.object.isRequired,
- // The reaction content / key / emoji
- content: PropTypes.string.isRequired,
- // The count of votes for this key
- count: PropTypes.number.isRequired,
- // A Set of Martix reaction events for this key
- reactionEvents: PropTypes.object.isRequired,
- // A possible Matrix event if the current user has voted for this type
- myReactionEvent: PropTypes.object,
- }
+export default class ReactionsRowButton extends React.PureComponent {
+ static contextType = MatrixClientContext;
- constructor(props) {
- super(props);
+ state = {
+ tooltipRendered: false,
+ tooltipVisible: false,
+ };
- this.state = {
- tooltipVisible: false,
- };
- }
-
- onClick = (ev) => {
+ onClick = () => {
const { mxEvent, myReactionEvent, content } = this.props;
if (myReactionEvent) {
- MatrixClientPeg.get().redactEvent(
+ this.context.redactEvent(
mxEvent.getRoomId(),
myReactionEvent.getId(),
);
} else {
- MatrixClientPeg.get().sendEvent(mxEvent.getRoomId(), "m.reaction", {
+ this.context.sendEvent(mxEvent.getRoomId(), "m.reaction", {
"m.relates_to": {
"rel_type": "m.annotation",
"event_id": mxEvent.getId(),
@@ -83,8 +88,6 @@ export default class ReactionsRowButton extends React.PureComponent {
}
render() {
- const ReactionsRowButtonTooltip =
- sdk.getComponent('messages.ReactionsRowButtonTooltip');
const { mxEvent, content, count, reactionEvents, myReactionEvent } = this.props;
const classes = classNames({
@@ -102,7 +105,7 @@ export default class ReactionsRowButton extends React.PureComponent {
/>;
}
- const room = MatrixClientPeg.get().getRoom(mxEvent.getRoomId());
+ const room = this.context.getRoom(mxEvent.getRoomId());
let label;
if (room) {
const senders = [];
@@ -130,7 +133,6 @@ export default class ReactionsRowButton extends React.PureComponent {
);
}
const isPeeking = room.getMyMembership() !== "join";
- const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
return ;
+ visible: boolean;
+}
@replaceableComponent("views.messages.ReactionsRowButtonTooltip")
-export default class ReactionsRowButtonTooltip extends React.PureComponent {
- static propTypes = {
- // The event we're displaying reactions for
- mxEvent: PropTypes.object.isRequired,
- // The reaction content / key / emoji
- content: PropTypes.string.isRequired,
- // A Set of Martix reaction events for this key
- reactionEvents: PropTypes.object.isRequired,
- visible: PropTypes.bool.isRequired,
- }
+export default class ReactionsRowButtonTooltip extends React.PureComponent {
+ static contextType = MatrixClientContext;
render() {
- const Tooltip = sdk.getComponent('elements.Tooltip');
const { content, reactionEvents, mxEvent, visible } = this.props;
- const room = MatrixClientPeg.get().getRoom(mxEvent.getRoomId());
+ const room = this.context.getRoom(mxEvent.getRoomId());
let tooltipLabel;
if (room) {
const senders = [];
From a41d76b588cd619a17770102457dbc57243e1e2f Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Thu, 13 May 2021 14:14:01 +0100
Subject: [PATCH 9/9] fix typos
---
src/components/views/messages/ReactionsRowButton.tsx | 2 +-
src/components/views/messages/ReactionsRowButtonTooltip.tsx | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/components/views/messages/ReactionsRowButton.tsx b/src/components/views/messages/ReactionsRowButton.tsx
index 393c6bca88..d163f1ad30 100644
--- a/src/components/views/messages/ReactionsRowButton.tsx
+++ b/src/components/views/messages/ReactionsRowButton.tsx
@@ -33,7 +33,7 @@ interface IProps {
content: string;
// The count of votes for this key
count: number;
- // A Set of Martix reaction events for this key
+ // A Set of Matrix reaction events for this key
reactionEvents: Set;
// A possible Matrix event if the current user has voted for this type
myReactionEvent?: MatrixEvent;
diff --git a/src/components/views/messages/ReactionsRowButtonTooltip.tsx b/src/components/views/messages/ReactionsRowButtonTooltip.tsx
index d9e8a45b28..e60174530a 100644
--- a/src/components/views/messages/ReactionsRowButtonTooltip.tsx
+++ b/src/components/views/messages/ReactionsRowButtonTooltip.tsx
@@ -29,7 +29,7 @@ interface IProps {
mxEvent: MatrixEvent;
// The reaction content / key / emoji
content: string;
- // A Set of Martix reaction events for this key
+ // A Set of Matrix reaction events for this key
reactionEvents: Set;
visible: boolean;
}