mirror of
https://github.com/element-hq/element-web
synced 2024-11-24 10:15:43 +03:00
Further improve replies (#6396)
* Give reply tile an avatar Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com> * Improve `in reply to` Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com> * Drop `In reply to` for `Expand thread` Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com> * Fix avatar alignment Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com> * Fix default avatar alignment Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com> * Simplifie code Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com> * Simplifie some more code Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com> * Make replies lighter Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com> * Give replies a hover effect Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com> * Revert changes to sender profile in replies Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com> * Improve padding Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com> * Increase line height of replies to keep descenders from being cut off, and generally give them more room to breathe. Signed-off-by: Robin Townsend <robin@robin.town> * Replace reply hover effect with a color change Signed-off-by: Robin Townsend <robin@robin.town> * Replace expand thread hover effect with an opacity change Signed-off-by: Robin Townsend <robin@robin.town> * Simplify image and sticker reply designs Signed-off-by: Robin Townsend <robin@robin.town> * Revise file and deleted message padding to match new reply layout Signed-off-by: Robin Townsend <robin@robin.town> * Remove unneeded CSS Since the download button for files got moved out of the timeline and into the message action bar, hiding it manually is no longer necessary. Signed-off-by: Robin Townsend <robin@robin.town> * Hide edited indicator from replies There are a few reasons for this: it adds visual noise to what is meant to be a brief preview, it can sometimes add an extra line to the reply preview, and clicking on it inside a reply was broken due to the stacking of event listeners. Signed-off-by: Robin Townsend <robin@robin.town> * Fix i18n Signed-off-by: Robin Townsend <robin@robin.town> * "Expand thread" -> "Expand replies" Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com> * Add a missing import Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com> * Remove unused import Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com> * Remove unused import Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com> * Use `this.state` Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com> * Fix sender profile confusion Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com> * Implement suggested changes * Make "In reply to" the same color as reply previews Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com> Signed-off-by: Robin Townsend <robin@robin.town> Co-authored-by: Robin Townsend <robin@robin.town>
This commit is contained in:
parent
ad090ac4cd
commit
6b3098d8fe
4 changed files with 67 additions and 63 deletions
|
@ -16,50 +16,51 @@ limitations under the License.
|
|||
|
||||
.mx_ReplyChain {
|
||||
margin: 0 0 $spacing-8 0;
|
||||
padding: 0 10px; /* TODO: Use a spacing variable */
|
||||
border-left: 2px solid $accent;
|
||||
border-radius: 2px;
|
||||
padding-left: 10px; // TODO: Use a spacing variable
|
||||
border-left: 2px solid var(--username-color); // TODO: Use a spacing variable
|
||||
border-radius: 2px; // TODO: Use a spacing variable
|
||||
|
||||
.mx_ReplyChain_show {
|
||||
&.mx_AccessibleButton_kind_link_inline {
|
||||
color: unset;
|
||||
white-space: nowrap; /* Enforce 'In reply to' to be a single line */
|
||||
color: $secondary-content;
|
||||
transition: color ease 0.15s;
|
||||
|
||||
&:hover {
|
||||
color: $links;
|
||||
color: $primary-content;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.mx_ReplyChain_color1 {
|
||||
border-left-color: $username-variant1-color;
|
||||
--username-color: $username-variant1-color;
|
||||
}
|
||||
|
||||
&.mx_ReplyChain_color2 {
|
||||
border-left-color: $username-variant2-color;
|
||||
--username-color: $username-variant2-color;
|
||||
}
|
||||
|
||||
&.mx_ReplyChain_color3 {
|
||||
border-left-color: $username-variant3-color;
|
||||
--username-color: $username-variant3-color;
|
||||
}
|
||||
|
||||
&.mx_ReplyChain_color4 {
|
||||
border-left-color: $username-variant4-color;
|
||||
--username-color: $username-variant4-color;
|
||||
}
|
||||
|
||||
&.mx_ReplyChain_color5 {
|
||||
border-left-color: $username-variant5-color;
|
||||
--username-color: $username-variant5-color;
|
||||
}
|
||||
|
||||
&.mx_ReplyChain_color6 {
|
||||
border-left-color: $username-variant6-color;
|
||||
--username-color: $username-variant6-color;
|
||||
}
|
||||
|
||||
&.mx_ReplyChain_color7 {
|
||||
border-left-color: $username-variant7-color;
|
||||
--username-color: $username-variant7-color;
|
||||
}
|
||||
|
||||
&.mx_ReplyChain_color8 {
|
||||
border-left-color: $username-variant8-color;
|
||||
--username-color: $username-variant8-color;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,22 +27,22 @@ limitations under the License.
|
|||
mask-image: url("$(res)/img/element-icons/call/video-call.svg");
|
||||
}
|
||||
|
||||
.mx_MFileBody {
|
||||
.mx_MFileBody_info {
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.mx_MFileBody_download {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
> a {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-decoration: none;
|
||||
color: $secondary-content;
|
||||
transition: color ease 0.15s;
|
||||
gap: 2px;
|
||||
|
||||
&:hover {
|
||||
color: $primary-content;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_RedactedBody {
|
||||
line-height: $font-18px;
|
||||
}
|
||||
|
||||
.mx_RedactedBody,
|
||||
.mx_HiddenBody {
|
||||
|
@ -52,13 +52,14 @@ limitations under the License.
|
|||
&::before {
|
||||
height: 13px;
|
||||
width: 13px;
|
||||
top: 5px;
|
||||
top: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
/* We do reply size limiting with CSS to avoid duplicating the TextualBody component. */
|
||||
.mx_EventTile_content {
|
||||
$reply-lines: 2;
|
||||
$line-height: $font-18px;
|
||||
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
|
@ -70,8 +71,8 @@ limitations under the License.
|
|||
font-size: $font-14px !important; /* Override the big emoji override */
|
||||
}
|
||||
|
||||
/* Hide line numbers */
|
||||
.mx_EventTile_lineNumbers {
|
||||
// Hide line numbers and edited indicator
|
||||
.mx_EventTile_lineNumbers, .mx_EventTile_edited {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
@ -101,7 +102,26 @@ limitations under the License.
|
|||
padding-top: 0;
|
||||
}
|
||||
|
||||
.mx_ReplyTile_sender {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
|
||||
.mx_DisambiguatedProfile {
|
||||
line-height: $font-17px;
|
||||
font-size: $font-14px;
|
||||
|
||||
display: inline-block; // anti-zalgo, with overflow hidden
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
||||
// truncate long display names
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.mx_BaseAvatar {
|
||||
line-height: 14px; // To match size
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,13 +15,9 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from "react";
|
||||
import { EventType } from "matrix-js-sdk/src/@types/event";
|
||||
|
||||
import MImageBody from "./MImageBody";
|
||||
import { presentableTextForFile } from "../../../utils/FileUtils";
|
||||
import { IMediaEventContent } from "../../../customisations/models/IMediaEventContent";
|
||||
import SenderProfile from "./SenderProfile";
|
||||
import { _t } from "../../../languageHandler";
|
||||
|
||||
const FORCED_IMAGE_HEIGHT = 44;
|
||||
|
||||
|
@ -34,16 +30,6 @@ export default class MImageReplyBody extends MImageBody {
|
|||
return children;
|
||||
}
|
||||
|
||||
// Don't show "Download this_file.png ..."
|
||||
public getFileBody(): string {
|
||||
const sticker = this.props.mxEvent.getType() === EventType.Sticker;
|
||||
return presentableTextForFile(this.props.mxEvent.getContent(), sticker ? _t("Sticker") : _t("Image"), !sticker);
|
||||
}
|
||||
|
||||
protected getBanner(content: IMediaEventContent): JSX.Element {
|
||||
return null; // we don't need a banner, nor have space for one
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.error) {
|
||||
return super.render();
|
||||
|
@ -51,17 +37,9 @@ export default class MImageReplyBody extends MImageBody {
|
|||
|
||||
const content = this.props.mxEvent.getContent<IMediaEventContent>();
|
||||
const thumbnail = this.messageContent(this.state.contentUrl, this.state.thumbUrl, content, FORCED_IMAGE_HEIGHT);
|
||||
const fileBody = this.getFileBody();
|
||||
const sender = <SenderProfile
|
||||
mxEvent={this.props.mxEvent}
|
||||
/>;
|
||||
|
||||
return <div className="mx_MImageReplyBody">
|
||||
{ thumbnail }
|
||||
<div className="mx_MImageReplyBody_info">
|
||||
<div className="mx_MImageReplyBody_sender">{ sender }</div>
|
||||
<div className="mx_MImageReplyBody_filename">{ fileBody }</div>
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import MImageReplyBody from "../messages/MImageReplyBody";
|
|||
import { isVoiceMessage } from '../../../utils/EventUtils';
|
||||
import { getEventDisplayInfo } from "../../../utils/EventRenderingUtils";
|
||||
import MFileBody from "../messages/MFileBody";
|
||||
import MemberAvatar from '../avatars/MemberAvatar';
|
||||
import MVoiceMessageBody from "../messages/MVoiceMessageBody";
|
||||
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
|
||||
import { renderReplyTile } from "../../../events/EventTileFactory";
|
||||
|
@ -106,7 +107,7 @@ export default class ReplyTile extends React.PureComponent<IProps> {
|
|||
render() {
|
||||
const mxEvent = this.props.mxEvent;
|
||||
const msgType = mxEvent.getContent().msgtype;
|
||||
const evType = mxEvent.getType() as EventType;
|
||||
const evType = mxEvent.getType();
|
||||
|
||||
const {
|
||||
hasRenderer, isInfoMessage, isSeeingThroughMessageHiddenForModeration,
|
||||
|
@ -133,17 +134,21 @@ export default class ReplyTile extends React.PureComponent<IProps> {
|
|||
}
|
||||
|
||||
let sender;
|
||||
const needsSenderProfile = (
|
||||
!isInfoMessage
|
||||
&& msgType !== MsgType.Image
|
||||
&& evType !== EventType.Sticker
|
||||
&& evType !== EventType.RoomCreate
|
||||
);
|
||||
|
||||
if (needsSenderProfile) {
|
||||
sender = <SenderProfile
|
||||
const hasOwnSender = isInfoMessage || evType === EventType.RoomCreate;
|
||||
if (!hasOwnSender) {
|
||||
sender = (
|
||||
<div className="mx_ReplyTile_sender">
|
||||
<MemberAvatar
|
||||
member={mxEvent.sender}
|
||||
fallbackUserId={mxEvent.getSender()}
|
||||
width={16}
|
||||
height={16}
|
||||
/>
|
||||
<SenderProfile
|
||||
mxEvent={mxEvent}
|
||||
/>;
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const msgtypeOverrides: Record<string, typeof React.Component> = {
|
||||
|
|
Loading…
Reference in a new issue