Tweak appearance of invite reason

This adjusts the display of invite reasons to match design feedback.

Fixes https://github.com/vector-im/element-web/issues/16869
pull/21833/head
J. Ryan Stinnett 2021-04-12 12:28:42 +01:00
parent f83aacbe9b
commit 650421eefb
11 changed files with 127 additions and 91 deletions

View File

@ -123,6 +123,7 @@
@import "./views/elements/_ImageView.scss";
@import "./views/elements/_InfoTooltip.scss";
@import "./views/elements/_InlineSpinner.scss";
@import "./views/elements/_InviteReason.scss";
@import "./views/elements/_ManageIntegsButton.scss";
@import "./views/elements/_MiniAvatarUploader.scss";
@import "./views/elements/_PowerSelector.scss";

View File

@ -0,0 +1,58 @@
/*
Copyright 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.
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_InviteReason {
position: relative;
margin-bottom: 1em;
.mx_InviteReason_reason {
filter: none;
transition-duration: 0.5s;
}
.mx_InviteReason_toggle {
display: none;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
justify-content: center;
align-items: center;
cursor: pointer;
color: $secondary-fg-color;
&::before {
content: "";
margin-right: 8px;
background-color: $secondary-fg-color;
mask-image: url('$(res)/img/feather-customised/eye.svg');
display: inline-block;
width: 18px;
height: 14px;
}
}
}
.mx_InviteReason_hidden {
.mx_InviteReason_reason {
filter: blur(5px) saturate(0.1) sepia(1);
}
.mx_InviteReason_toggle {
display: flex;
}
}

View File

@ -40,35 +40,6 @@ limitations under the License.
word-break: break-word;
}
.mx_RoomPreviewBar_reason {
text-align: left;
background-color: $primary-bg-color;
border: 1px solid $invite-reason-border-color;
border-radius: 10px;
padding: 0 16px 12px 16px;
margin: 5px 0 20px 0;
div {
pointer-events: none;
}
.mx_EventTile_msgOption {
display: none;
}
.mx_MatrixChat_useCompactLayout & {
padding-top: 9px;
}
&.mx_EventTilePreview_faded {
cursor: pointer;
.mx_SenderProfile, .mx_EventTile_avatar {
opacity: 0.3;
}
}
}
.mx_Spinner {
width: auto;
height: auto;

View File

@ -209,8 +209,6 @@ $message-body-panel-fg-color: $primary-fg-color;
// Appearance tab colors
$appearance-tab-border-color: $room-highlight-color;
$invite-reason-border-color: $room-highlight-color;
// blur amounts for left left panel (only for element theme, used in _mods.scss)
$roomlist-background-blur-amount: 60px;
$groupFilterPanel-background-blur-amount: 30px;

View File

@ -204,8 +204,6 @@ $message-body-panel-fg-color: $primary-fg-color;
// Appearance tab colors
$appearance-tab-border-color: $room-highlight-color;
$invite-reason-border-color: $room-highlight-color;
$composer-shadow-color: tranparent;
// ***** Mixins! *****

View File

@ -333,8 +333,6 @@ $message-body-panel-fg-color: $muted-fg-color;
// FontSlider colors
$appearance-tab-border-color: $input-darker-bg-color;
$invite-reason-border-color: $input-darker-bg-color;
$composer-shadow-color: tranparent;
// ***** Mixins! *****

View File

@ -331,8 +331,6 @@ $message-body-panel-fg-color: $muted-fg-color;
// FontSlider colors
$appearance-tab-border-color: $input-darker-bg-color;
$invite-reason-border-color: $input-darker-bg-color;
// blur amounts for left left panel (only for element theme, used in _mods.scss)
$roomlist-background-blur-amount: 40px;
$groupFilterPanel-background-blur-amount: 20px;

View File

@ -55,22 +55,10 @@ interface IProps {
* The mxc:// avatar URL of the displayed user
*/
avatarUrl?: string;
/**
* Whether the EventTile should appear faded
*/
faded?: boolean;
/**
* Callback for when the component is clicked
*/
onClick?: () => void;
}
interface IState {
message: string;
faded: boolean;
eventTileKey: number;
}
const AVATAR_SIZE = 32;
@ -81,23 +69,9 @@ export default class EventTilePreview extends React.Component<IProps, IState> {
super(props);
this.state = {
message: props.message,
faded: !!props.faded,
eventTileKey: 0,
};
}
changeMessage(message: string) {
this.setState({
message,
// Change the EventTile key to force React to create a new instance
eventTileKey: this.state.eventTileKey + 1,
});
}
unfade() {
this.setState({ faded: false });
}
private fakeEvent({message}: IState) {
// Fake it till we make it
/* eslint-disable quote-props */
@ -147,12 +121,10 @@ export default class EventTilePreview extends React.Component<IProps, IState> {
const className = classnames(this.props.className, {
"mx_IRCLayout": this.props.layout == Layout.IRC,
"mx_GroupLayout": this.props.layout == Layout.Group,
"mx_EventTilePreview_faded": this.state.faded,
});
return <div className={className} onClick={this.props.onClick}>
return <div className={className}>
<EventTile
key={this.state.eventTileKey}
mxEvent={event}
layout={this.props.layout}
enableFlair={SettingsStore.getValue(UIFeature.Flair)}

View File

@ -0,0 +1,62 @@
/*
Copyright 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.
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 classNames from "classnames";
import React from "react";
import { _t } from "../../../languageHandler";
import { replaceableComponent } from "../../../utils/replaceableComponent";
interface IProps {
reason: string;
}
interface IState {
hidden: boolean;
}
@replaceableComponent("views.elements.InviteReason")
export default class InviteReason extends React.PureComponent<IProps, IState> {
constructor(props) {
super(props);
this.state = {
// We hide the reason for invitation by default, since it can be a
// vector for spam/harassment.
hidden: true,
};
}
onToggleClick = () => {
this.setState({
hidden: false,
});
}
render() {
const classes = classNames({
"mx_InviteReason": true,
"mx_InviteReason_hidden": this.state.hidden,
});
return <div className={classes}>
<div className="mx_InviteReason_reason">{this.props.reason}</div>
<div className="mx_InviteReason_toggle"
onClick={this.onToggleClick}
>
{_t("View message")}
</div>
</div>;
}
}

View File

@ -1,7 +1,5 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
Copyright 2017 Vector Creations Ltd
Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
Copyright 2015-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.
@ -25,10 +23,10 @@ import classNames from 'classnames';
import { _t } from '../../../languageHandler';
import SdkConfig from "../../../SdkConfig";
import IdentityAuthClient from '../../../IdentityAuthClient';
import SettingsStore from "../../../settings/SettingsStore";
import {CommunityPrototypeStore} from "../../../stores/CommunityPrototypeStore";
import {UPDATE_EVENT} from "../../../stores/AsyncStore";
import {replaceableComponent} from "../../../utils/replaceableComponent";
import { replaceableComponent } from "../../../utils/replaceableComponent";
import InviteReason from "../elements/InviteReason";
const MessageCase = Object.freeze({
NotLoggedIn: "NotLoggedIn",
@ -303,7 +301,6 @@ export default class RoomPreviewBar extends React.Component {
const brand = SdkConfig.get().brand;
const Spinner = sdk.getComponent('elements.Spinner');
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
const EventTilePreview = sdk.getComponent('elements.EventTilePreview');
let showSpinner = false;
let title;
@ -497,24 +494,7 @@ export default class RoomPreviewBar extends React.Component {
const myUserId = MatrixClientPeg.get().getUserId();
const reason = this.props.room.currentState.getMember(myUserId).events.member.event.content.reason;
if (reason) {
this.reasonElement = React.createRef();
// We hide the reason for invitation by default, since it can be a
// vector for spam/harassment.
const showReason = () => {
this.reasonElement.current.unfade();
this.reasonElement.current.changeMessage(reason);
};
reasonElement = <EventTilePreview
ref={this.reasonElement}
onClick={showReason}
className="mx_RoomPreviewBar_reason"
message={_t("Invite messages are hidden by default. Click to show the message.")}
layout={SettingsStore.getValue("layout")}
userId={inviteMember.userId}
displayName={inviteMember.rawDisplayName}
avatarUrl={inviteMember.events.member.event.content.avatar_url}
faded={true}
/>;
reasonElement = <InviteReason reason={reason} />;
}
primaryActionHandler = this.props.onJoinClick;

View File

@ -1578,7 +1578,6 @@
"Start chatting": "Start chatting",
"Do you want to join %(roomName)s?": "Do you want to join %(roomName)s?",
"<userName/> invited you": "<userName/> invited you",
"Invite messages are hidden by default. Click to show the message.": "Invite messages are hidden by default. Click to show the message.",
"Reject": "Reject",
"Reject & Ignore user": "Reject & Ignore user",
"You're previewing %(roomName)s. Want to join it?": "You're previewing %(roomName)s. Want to join it?",
@ -1925,6 +1924,7 @@
"Rotate clockwise": "Rotate clockwise",
"Download this file": "Download this file",
"Information": "Information",
"View message": "View message",
"Language Dropdown": "Language Dropdown",
"%(nameList)s %(transitionList)s": "%(nameList)s %(transitionList)s",
"%(severalUsers)sjoined %(count)s times|other": "%(severalUsers)sjoined %(count)s times",