From ff25a9b45de5e5125bfb6552ff7470df8327acd1 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 4 Nov 2020 17:00:07 +0000 Subject: [PATCH] Consolidate all EventTile bubble stuff into its own component and use it for the room continuation plinth --- res/css/_components.scss | 1 + res/css/views/messages/_CreateEvent.scss | 34 ++++------ res/css/views/messages/_EventTileBubble.scss | 63 +++++++++++++++++++ .../views/messages/_MJitsiWidgetEvent.scss | 33 ---------- .../views/messages/_common_CryptoEvent.scss | 48 +++----------- res/css/views/rooms/_EventTile.scss | 9 --- .../views/messages/EncryptionEvent.js | 45 ++++++------- .../views/messages/EventTileBubble.tsx | 34 ++++++++++ .../views/messages/MJitsiWidgetEvent.tsx | 42 +++++-------- .../messages/MKeyVerificationConclusion.js | 13 ++-- .../views/messages/MKeyVerificationRequest.js | 25 ++++---- src/components/views/messages/RoomCreate.js | 20 +++--- src/components/views/rooms/EventTile.js | 1 + 13 files changed, 182 insertions(+), 186 deletions(-) create mode 100644 res/css/views/messages/_EventTileBubble.scss create mode 100644 src/components/views/messages/EventTileBubble.tsx diff --git a/res/css/_components.scss b/res/css/_components.scss index 37d0e0d286..af3589a415 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -139,6 +139,7 @@ @import "./views/groups/_GroupUserSettings.scss"; @import "./views/messages/_CreateEvent.scss"; @import "./views/messages/_DateSeparator.scss"; +@import "./views/messages/_EventTileBubble.scss"; @import "./views/messages/_MEmoteBody.scss"; @import "./views/messages/_MFileBody.scss"; @import "./views/messages/_MImageBody.scss"; diff --git a/res/css/views/messages/_CreateEvent.scss b/res/css/views/messages/_CreateEvent.scss index d45645863f..1f75fb9693 100644 --- a/res/css/views/messages/_CreateEvent.scss +++ b/res/css/views/messages/_CreateEvent.scss @@ -1,5 +1,5 @@ /* -Copyright 2018 New Vector Ltd +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. @@ -15,25 +15,17 @@ limitations under the License. */ .mx_CreateEvent { - background-color: $info-plinth-bg-color; - padding-left: 20px; - padding-right: 20px; - padding-top: 10px; - padding-bottom: 10px; -} + // override default EventTileBubble styling + padding-left: 80px !important; -.mx_CreateEvent_image { - float: left; - margin-right: 20px; - width: 72px; - height: 34px; - - background-color: $primary-fg-color; - mask: url('$(res)/img/room-continuation.svg'); - mask-repeat: no-repeat; - mask-position: center; -} - -.mx_CreateEvent_header { - font-weight: bold; + &::before { + background-color: $primary-fg-color; + mask-image: url('$(res)/img/room-continuation.svg'); + mask-repeat: no-repeat; + mask-position: center; + mask-size: 100%; + width: 72px !important; + height: 34px !important; + left: -64px !important; + } } diff --git a/res/css/views/messages/_EventTileBubble.scss b/res/css/views/messages/_EventTileBubble.scss new file mode 100644 index 0000000000..99feb03ef9 --- /dev/null +++ b/res/css/views/messages/_EventTileBubble.scss @@ -0,0 +1,63 @@ +/* +Copyright 2019, 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. +*/ + +.mx_EventTileBubble { + background-color: $dark-panel-bg-color; + padding: 10px; + border-radius: 8px; + margin: 10px auto; + max-width: 75%; + box-sizing: border-box; + display: grid; + grid-template-columns: 24px minmax(0, 1fr) min-content; + + &::before, &::after { + position: relative; + grid-column: 1; + grid-row: 1 / 3; + width: 16px; + height: 16px; + content: ""; + top: 0; + bottom: 0; + left: 0; + right: 0; + mask-repeat: no-repeat; + mask-position: center; + mask-size: contain; + margin-top: 4px; + } + + .mx_EventTileBubble_title, .mx_EventTileBubble_subtitle { + overflow-wrap: break-word; + } + + .mx_EventTileBubble_title { + font-weight: 600; + font-size: $font-15px; + grid-column: 2; + grid-row: 1; + } + + .mx_EventTileBubble_subtitle { + grid-column: 2; + grid-row: 2; + } + + .mx_EventTileBubble_subtitle { + font-size: $font-12px; + } +} diff --git a/res/css/views/messages/_MJitsiWidgetEvent.scss b/res/css/views/messages/_MJitsiWidgetEvent.scss index 3e51e89744..bea8651543 100644 --- a/res/css/views/messages/_MJitsiWidgetEvent.scss +++ b/res/css/views/messages/_MJitsiWidgetEvent.scss @@ -15,41 +15,8 @@ limitations under the License. */ .mx_MJitsiWidgetEvent { - display: grid; - grid-template-columns: 24px minmax(0, 1fr) min-content; - &::before { - grid-column: 1; - grid-row: 1 / 3; - width: 16px; - height: 16px; - content: ""; - top: 0; - bottom: 0; - left: 0; - right: 0; - mask-repeat: no-repeat; - mask-position: center; - mask-size: contain; background-color: $composer-e2e-icon-color; // XXX: Variable abuse - margin-top: 4px; mask-image: url('$(res)/img/element-icons/call/video-call.svg'); } - - .mx_MJitsiWidgetEvent_title { - font-weight: 600; - font-size: $font-15px; - grid-column: 2; - grid-row: 1; - } - - .mx_MJitsiWidgetEvent_subtitle { - grid-column: 2; - grid-row: 2; - } - - .mx_MJitsiWidgetEvent_title, - .mx_MJitsiWidgetEvent_subtitle { - overflow-wrap: break-word; - } } diff --git a/res/css/views/messages/_common_CryptoEvent.scss b/res/css/views/messages/_common_CryptoEvent.scss index 09c78ae5b4..4faa4b594f 100644 --- a/res/css/views/messages/_common_CryptoEvent.scss +++ b/res/css/views/messages/_common_CryptoEvent.scss @@ -15,28 +15,6 @@ limitations under the License. */ .mx_cryptoEvent { - display: grid; - grid-template-columns: 24px minmax(0, 1fr) min-content; - - &.mx_cryptoEvent_icon::before, - &.mx_cryptoEvent_icon::after { - grid-column: 1; - grid-row: 1 / 3; - width: 16px; - height: 16px; - content: ""; - top: 0; - bottom: 0; - left: 0; - right: 0; - mask-repeat: no-repeat; - mask-position: center; - mask-size: contain; - mask-image: url('$(res)/img/e2e/normal.svg'); - background-color: $composer-e2e-icon-color; - margin-top: 4px; - } - // white infill for the transparency &.mx_cryptoEvent_icon::before { background-color: #ffffff; @@ -46,6 +24,11 @@ limitations under the License. mask-size: 90%; } + &.mx_cryptoEvent_icon::after { + mask-image: url('$(res)/img/e2e/normal.svg'); + background-color: $composer-e2e-icon-color; + } + &.mx_cryptoEvent_icon_verified::after { mask-image: url("$(res)/img/e2e/verified.svg"); background-color: $accent-color; @@ -56,25 +39,6 @@ limitations under the License. background-color: $notice-primary-color; } - .mx_cryptoEvent_title, .mx_cryptoEvent_subtitle, .mx_cryptoEvent_state { - overflow-wrap: break-word; - } - - .mx_cryptoEvent_title { - font-weight: 600; - font-size: $font-15px; - grid-column: 2; - grid-row: 1; - } - - .mx_cryptoEvent_subtitle { - grid-column: 2; - grid-row: 2; - } - - .mx_cryptoEvent_state, .mx_cryptoEvent_subtitle { - font-size: $font-12px; - } .mx_cryptoEvent_state, .mx_cryptoEvent_buttons { grid-column: 3; @@ -92,5 +56,7 @@ limitations under the License. margin: auto 0; text-align: center; color: $notice-secondary-color; + overflow-wrap: break-word; + font-size: $font-12px; } } diff --git a/res/css/views/rooms/_EventTile.scss b/res/css/views/rooms/_EventTile.scss index 3b9a491db5..18eb581776 100644 --- a/res/css/views/rooms/_EventTile.scss +++ b/res/css/views/rooms/_EventTile.scss @@ -25,15 +25,6 @@ $left-gutter: 64px; position: relative; } -.mx_EventTile_bubble { - background-color: $dark-panel-bg-color; - padding: 10px; - border-radius: 5px; - margin: 10px auto; - max-width: 75%; - box-sizing: border-box; -} - .mx_EventTile.mx_EventTile_info { padding-top: 0px; } diff --git a/src/components/views/messages/EncryptionEvent.js b/src/components/views/messages/EncryptionEvent.js index a9ce10d202..ee304b4fa3 100644 --- a/src/components/views/messages/EncryptionEvent.js +++ b/src/components/views/messages/EncryptionEvent.js @@ -18,42 +18,35 @@ import React from 'react'; import PropTypes from 'prop-types'; import { _t } from '../../../languageHandler'; import { MatrixClientPeg } from '../../../MatrixClientPeg'; +import EventTileBubble from "./EventTileBubble"; export default class EncryptionEvent extends React.Component { render() { const {mxEvent} = this.props; - let body; - let classes = "mx_EventTile_bubble mx_cryptoEvent mx_cryptoEvent_icon"; const isRoomEncrypted = MatrixClientPeg.get().isRoomEncrypted(mxEvent.getRoomId()); if (mxEvent.getContent().algorithm === 'm.megolm.v1.aes-sha2' && isRoomEncrypted) { - body =
-
{_t("Encryption enabled")}
-
- {_t( - "Messages in this room are end-to-end encrypted. " + - "Learn more & verify this user in their user profile.", - )} -
-
; + return ; } else if (isRoomEncrypted) { - body =
-
{_t("Encryption enabled")}
-
- {_t("Ignored attempt to disable encryption")} -
-
; - } else { - body =
-
{_t("Encryption not enabled")}
-
{_t("The encryption used by this room isn't supported.")}
-
; - classes += " mx_cryptoEvent_icon_warning"; + return ; } - return (
- {body} -
); + return ; } } diff --git a/src/components/views/messages/EventTileBubble.tsx b/src/components/views/messages/EventTileBubble.tsx new file mode 100644 index 0000000000..8a2cf0f01c --- /dev/null +++ b/src/components/views/messages/EventTileBubble.tsx @@ -0,0 +1,34 @@ +/* +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 React, {ReactNode} from "react"; +import classNames from "classnames"; + +interface IProps { + className: string; + title: string; + subtitle?: ReactNode; +} + +const EventTileBubble: React.FC = ({ className, title, subtitle, children }) => { + return
+
{ title }
+ { subtitle &&
{ subtitle }
} + { children } +
; +}; + +export default EventTileBubble; diff --git a/src/components/views/messages/MJitsiWidgetEvent.tsx b/src/components/views/messages/MJitsiWidgetEvent.tsx index 3d191209f9..82aa32d3b7 100644 --- a/src/components/views/messages/MJitsiWidgetEvent.tsx +++ b/src/components/views/messages/MJitsiWidgetEvent.tsx @@ -18,6 +18,7 @@ import React from 'react'; import { MatrixEvent } from "matrix-js-sdk/src/models/event"; import { _t } from "../../../languageHandler"; import WidgetStore from "../../../stores/WidgetStore"; +import EventTileBubble from "./EventTileBubble"; interface IProps { mxEvent: MatrixEvent; @@ -40,37 +41,24 @@ export default class MJitsiWidgetEvent extends React.PureComponent { if (!url) { // removed - return ( -
-
- {_t('Video conference ended by %(senderName)s', {senderName})} -
-
- ); + return ; } else if (prevUrl) { // modified - return ( -
-
- {_t('Video conference updated by %(senderName)s', {senderName})} -
-
- {joinCopy} -
-
- ); + return ; } else { // assume added - return ( -
-
- {_t("Video conference started by %(senderName)s", {senderName})} -
-
- {joinCopy} -
-
- ); + return ; } } } diff --git a/src/components/views/messages/MKeyVerificationConclusion.js b/src/components/views/messages/MKeyVerificationConclusion.js index ececfc60ed..880299d29d 100644 --- a/src/components/views/messages/MKeyVerificationConclusion.js +++ b/src/components/views/messages/MKeyVerificationConclusion.js @@ -21,6 +21,7 @@ import {MatrixClientPeg} from '../../../MatrixClientPeg'; import { _t } from '../../../languageHandler'; import {getNameForEventRoom, userLabelForEventRoom} from '../../../utils/KeyVerificationStateObserver'; +import EventTileBubble from "./EventTileBubble"; export default class MKeyVerificationConclusion extends React.Component { constructor(props) { @@ -115,14 +116,14 @@ export default class MKeyVerificationConclusion extends React.Component { } if (title) { - const subtitle = userLabelForEventRoom(request.otherUserId, mxEvent.getRoomId()); - const classes = classNames("mx_EventTile_bubble", "mx_cryptoEvent", "mx_cryptoEvent_icon", { + const classes = classNames("mx_cryptoEvent mx_cryptoEvent_icon", { mx_cryptoEvent_icon_verified: request.done, }); - return (
-
{title}
-
{subtitle}
-
); + return ; } return null; diff --git a/src/components/views/messages/MKeyVerificationRequest.js b/src/components/views/messages/MKeyVerificationRequest.js index 01a5c2663e..d9594091c5 100644 --- a/src/components/views/messages/MKeyVerificationRequest.js +++ b/src/components/views/messages/MKeyVerificationRequest.js @@ -24,6 +24,7 @@ import {getNameForEventRoom, userLabelForEventRoom} import dis from "../../../dispatcher/dispatcher"; import {RightPanelPhases} from "../../../stores/RightPanelStorePhases"; import {Action} from "../../../dispatcher/actions"; +import EventTileBubble from "./EventTileBubble"; export default class MKeyVerificationRequest extends React.Component { constructor(props) { @@ -146,10 +147,8 @@ export default class MKeyVerificationRequest extends React.Component { if (!request.initiatedByMe) { const name = getNameForEventRoom(request.requestingUserId, mxEvent.getRoomId()); - title = (
{ - _t("%(name)s wants to verify", {name})}
); - subtitle = (
{ - userLabelForEventRoom(request.requestingUserId, mxEvent.getRoomId())}
); + title = _t("%(name)s wants to verify", {name}); + subtitle = userLabelForEventRoom(request.requestingUserId, mxEvent.getRoomId()); if (request.canAccept) { stateNode = (
@@ -157,18 +156,18 @@ export default class MKeyVerificationRequest extends React.Component {
); } } else { // request sent by us - title = (
{ - _t("You sent a verification request")}
); - subtitle = (
{ - userLabelForEventRoom(request.receivingUserId, mxEvent.getRoomId())}
); + title = _t("You sent a verification request"); + subtitle = userLabelForEventRoom(request.receivingUserId, mxEvent.getRoomId()); } if (title) { - return (
- {title} - {subtitle} - {stateNode} -
); + return + { stateNode } + ; } return null; } diff --git a/src/components/views/messages/RoomCreate.js b/src/components/views/messages/RoomCreate.js index 6098b1217e..479592aa42 100644 --- a/src/components/views/messages/RoomCreate.js +++ b/src/components/views/messages/RoomCreate.js @@ -22,6 +22,7 @@ import dis from '../../../dispatcher/dispatcher'; import { RoomPermalinkCreator } from '../../../utils/permalinks/Permalinks'; import { _t } from '../../../languageHandler'; import {MatrixClientPeg} from '../../../MatrixClientPeg'; +import EventTileBubble from "./EventTileBubble"; export default class RoomCreate extends React.Component { static propTypes = { @@ -51,17 +52,16 @@ export default class RoomCreate extends React.Component { const permalinkCreator = new RoomPermalinkCreator(prevRoom, predecessor['room_id']); permalinkCreator.load(); const predecessorPermalink = permalinkCreator.forEvent(predecessor['event_id']); - return
-
-
- {_t("This room is a continuation of another conversation.")} -
- + const link = ( + {_t("Click here to see older messages.")} -
; + ); + + return ; } } diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index 48ab6831d9..9060ddb02b 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -647,6 +647,7 @@ export default class EventTile extends React.Component { // Info messages are basically information about commands processed on a room const isBubbleMessage = eventType.startsWith("m.key.verification") || (eventType === "m.room.message" && msgtype && msgtype.startsWith("m.key.verification")) || + (eventType === "m.room.create") || (eventType === "m.room.encryption") || (tileHandler === "messages.MJitsiWidgetEvent"); let isInfoMessage = (