Improve pills (#6398)
This commit is contained in:
parent
c79596cfe6
commit
b5ac9493dd
15 changed files with 176 additions and 184 deletions
|
@ -163,6 +163,7 @@
|
||||||
@import "./views/elements/_InviteReason.scss";
|
@import "./views/elements/_InviteReason.scss";
|
||||||
@import "./views/elements/_ManageIntegsButton.scss";
|
@import "./views/elements/_ManageIntegsButton.scss";
|
||||||
@import "./views/elements/_MiniAvatarUploader.scss";
|
@import "./views/elements/_MiniAvatarUploader.scss";
|
||||||
|
@import "./views/elements/_Pill.scss";
|
||||||
@import "./views/elements/_PowerSelector.scss";
|
@import "./views/elements/_PowerSelector.scss";
|
||||||
@import "./views/elements/_ProgressBar.scss";
|
@import "./views/elements/_ProgressBar.scss";
|
||||||
@import "./views/elements/_QRCode.scss";
|
@import "./views/elements/_QRCode.scss";
|
||||||
|
|
|
@ -155,7 +155,7 @@ limitations under the License.
|
||||||
line-height: $font-20px;
|
line-height: $font-20px;
|
||||||
padding: 0 5px;
|
padding: 0 5px;
|
||||||
color: $accent-fg-color;
|
color: $accent-fg-color;
|
||||||
background-color: $rte-room-pill-color;
|
background-color: $pill-bg-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_RoomDirectory_topic {
|
.mx_RoomDirectory_topic {
|
||||||
|
|
64
res/css/views/elements/_Pill.scss
Normal file
64
res/css/views/elements/_Pill.scss
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021 Šimon Brandner <simon.bra.ag@gmail.com>
|
||||||
|
|
||||||
|
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_Pill {
|
||||||
|
padding: $font-1px 0.4em $font-1px 0;
|
||||||
|
line-height: $font-17px;
|
||||||
|
border-radius: $font-16px;
|
||||||
|
vertical-align: text-top;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
color: $accent-fg-color !important; // To override .markdown-body
|
||||||
|
background-color: $pill-bg-color !important; // To override .markdown-body
|
||||||
|
|
||||||
|
&.mx_UserPill_me,
|
||||||
|
&.mx_AtRoomPill {
|
||||||
|
background-color: $alert !important; // To override .markdown-body
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: $pill-hover-bg-color !important; // To override .markdown-body
|
||||||
|
}
|
||||||
|
|
||||||
|
&.mx_UserPill_me:hover {
|
||||||
|
background-color: #ff6b75 !important; // To override .markdown-body | same on both themes
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't want to indicate clickability
|
||||||
|
&.mx_AtRoomPill:hover {
|
||||||
|
background-color: $alert !important; // To override .markdown-body
|
||||||
|
cursor: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_BaseAvatar {
|
||||||
|
position: relative;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 10rem;
|
||||||
|
margin-right: 0.24rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
a& {
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
max-width: calc(100% - 1ch);
|
||||||
|
text-decoration: none !important; // To override .markdown-body
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,86 +2,6 @@
|
||||||
// naming scheme; it's completely unclear where or how they're being used
|
// naming scheme; it's completely unclear where or how they're being used
|
||||||
// --Matthew
|
// --Matthew
|
||||||
|
|
||||||
.mx_UserPill,
|
|
||||||
.mx_RoomPill,
|
|
||||||
.mx_AtRoomPill {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
vertical-align: middle;
|
|
||||||
border-radius: $font-16px;
|
|
||||||
line-height: $font-15px;
|
|
||||||
padding-left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
a.mx_Pill {
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_Pill {
|
|
||||||
padding: $font-1px;
|
|
||||||
padding-right: 0.4em;
|
|
||||||
vertical-align: text-top;
|
|
||||||
line-height: $font-17px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* More specific to override `.markdown-body a` text-decoration */
|
|
||||||
.mx_EventTile_content .markdown-body a.mx_Pill {
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* More specific to override `.markdown-body a` color */
|
|
||||||
.mx_EventTile_content .markdown-body a.mx_UserPill,
|
|
||||||
.mx_UserPill {
|
|
||||||
color: $primary-content;
|
|
||||||
background-color: $other-user-pill-bg-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_UserPill_selected {
|
|
||||||
background-color: $accent !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* More specific to override `.markdown-body a` color */
|
|
||||||
.mx_EventTile_highlight .mx_EventTile_content .markdown-body a.mx_UserPill_me,
|
|
||||||
.mx_EventTile_content .markdown-body a.mx_AtRoomPill,
|
|
||||||
.mx_EventTile_content .mx_AtRoomPill,
|
|
||||||
.mx_MessageComposer_input .mx_AtRoomPill {
|
|
||||||
color: $accent-fg-color;
|
|
||||||
background-color: $alert;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* More specific to override `.markdown-body a` color */
|
|
||||||
.mx_EventTile_content .markdown-body a.mx_RoomPill,
|
|
||||||
.mx_RoomPill {
|
|
||||||
color: $accent-fg-color;
|
|
||||||
background-color: $rte-room-pill-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_EventTile_body .mx_UserPill,
|
|
||||||
.mx_EventTile_body .mx_RoomPill {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_UserPill .mx_BaseAvatar,
|
|
||||||
.mx_RoomPill .mx_BaseAvatar,
|
|
||||||
.mx_AtRoomPill .mx_BaseAvatar {
|
|
||||||
position: relative;
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
border-radius: 10rem;
|
|
||||||
margin-right: 0.24rem;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_Emoji {
|
|
||||||
// Should be 1.8rem for our default 1.4rem message bodies,
|
|
||||||
// and scale with the size of the surrounding text
|
|
||||||
font-size: calc(18 / 14 * 1em);
|
|
||||||
vertical-align: bottom;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_Markdown_BOLD {
|
.mx_Markdown_BOLD {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,9 +51,15 @@ limitations under the License.
|
||||||
}
|
}
|
||||||
|
|
||||||
&.mx_BasicMessageComposer_input_shouldShowPillAvatar {
|
&.mx_BasicMessageComposer_input_shouldShowPillAvatar {
|
||||||
span.mx_UserPill, span.mx_RoomPill {
|
span.mx_UserPill, span.mx_RoomPill, span.mx_SpacePill {
|
||||||
position: relative;
|
|
||||||
user-select: all;
|
user-select: all;
|
||||||
|
position: relative;
|
||||||
|
cursor: unset; // We don't want indicate clickability
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
// We don't want indicate clickability | To override the overriding of .markdown-body
|
||||||
|
background-color: $pill-bg-color !important;
|
||||||
|
}
|
||||||
|
|
||||||
// avatar psuedo element
|
// avatar psuedo element
|
||||||
&::before {
|
&::before {
|
||||||
|
@ -72,14 +78,6 @@ limitations under the License.
|
||||||
font-size: $font-10-4px;
|
font-size: $font-10-4px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
span.mx_UserPill {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
span.mx_RoomPill {
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.mx_BasicMessageComposer_input_disabled {
|
&.mx_BasicMessageComposer_input_disabled {
|
||||||
|
|
|
@ -94,8 +94,8 @@ $roomheader-addroom-fg-color: $primary-content;
|
||||||
|
|
||||||
// Rich-text-editor
|
// Rich-text-editor
|
||||||
// ********************
|
// ********************
|
||||||
$rte-room-pill-color: $room-highlight-color;
|
$pill-bg-color: $room-highlight-color;
|
||||||
$other-user-pill-bg-color: $room-highlight-color;
|
$pill-hover-bg-color: #545a66;
|
||||||
// ********************
|
// ********************
|
||||||
|
|
||||||
// Inputs
|
// Inputs
|
||||||
|
|
|
@ -27,8 +27,8 @@ $light-fg-color: $header-panel-text-secondary-color;
|
||||||
// used for focusing form controls
|
// used for focusing form controls
|
||||||
$focus-bg-color: $room-highlight-color;
|
$focus-bg-color: $room-highlight-color;
|
||||||
|
|
||||||
$other-user-pill-bg-color: $room-highlight-color;
|
$pill-bg-color: $room-highlight-color;
|
||||||
$rte-room-pill-color: $room-highlight-color;
|
$pill-hover-bg-color: #545a66;
|
||||||
|
|
||||||
// informational plinth
|
// informational plinth
|
||||||
$info-plinth-bg-color: $header-panel-bg-color;
|
$info-plinth-bg-color: $header-panel-bg-color;
|
||||||
|
|
|
@ -37,8 +37,6 @@ $selection-fg-color: $primary-bg-color;
|
||||||
|
|
||||||
$focus-brightness: 105%;
|
$focus-brightness: 105%;
|
||||||
|
|
||||||
$other-user-pill-bg-color: rgba(0, 0, 0, 0.1);
|
|
||||||
|
|
||||||
// informational plinth
|
// informational plinth
|
||||||
$info-plinth-bg-color: #f7f7f7;
|
$info-plinth-bg-color: #f7f7f7;
|
||||||
$info-plinth-fg-color: #888;
|
$info-plinth-fg-color: #888;
|
||||||
|
@ -117,10 +115,12 @@ $settings-subsection-fg-color: #61708b;
|
||||||
|
|
||||||
$rte-bg-color: #e9e9e9;
|
$rte-bg-color: #e9e9e9;
|
||||||
$rte-code-bg-color: rgba(0, 0, 0, 0.04);
|
$rte-code-bg-color: rgba(0, 0, 0, 0.04);
|
||||||
$rte-room-pill-color: #aaa;
|
|
||||||
|
|
||||||
$header-panel-text-primary-color: #91a1c0;
|
$header-panel-text-primary-color: #91a1c0;
|
||||||
|
|
||||||
|
$pill-bg-color: #aaa;
|
||||||
|
$pill-hover-bg-color: #ccc;
|
||||||
|
|
||||||
$topleftmenu-color: #212121;
|
$topleftmenu-color: #212121;
|
||||||
$roomheader-bg-color: $primary-bg-color;
|
$roomheader-bg-color: $primary-bg-color;
|
||||||
$roomheader-addroom-bg-color: #91a1c0;
|
$roomheader-addroom-bg-color: #91a1c0;
|
||||||
|
|
|
@ -142,5 +142,6 @@ $eventbubble-reply-color: var(--eventbubble-reply-color, $eventbubble-reply-colo
|
||||||
$reaction-row-button-selected-bg-color: var(--reaction-row-button-selected-bg-color, $reaction-row-button-selected-bg-color);
|
$reaction-row-button-selected-bg-color: var(--reaction-row-button-selected-bg-color, $reaction-row-button-selected-bg-color);
|
||||||
|
|
||||||
$menu-selected-color: var(--menu-selected-color, $menu-selected-color);
|
$menu-selected-color: var(--menu-selected-color, $menu-selected-color);
|
||||||
$other-user-pill-bg-color: var(--other-user-pill-bg-color, $other-user-pill-bg-color);
|
$pill-bg-color: var(--other-user-pill-bg-color, $pill-bg-color);
|
||||||
|
$pill-hover-bg-color: var(--other-user-pill-bg-color, $pill-hover-bg-color);
|
||||||
$icon-button-color: var(--icon-button-color, $icon-button-color);
|
$icon-button-color: var(--icon-button-color, $icon-button-color);
|
||||||
|
|
|
@ -147,8 +147,8 @@ $roomheader-addroom-fg-color: #5c6470;
|
||||||
|
|
||||||
// Rich-text-editor
|
// Rich-text-editor
|
||||||
// ********************
|
// ********************
|
||||||
$rte-room-pill-color: #aaa;
|
$pill-bg-color: #aaa;
|
||||||
$other-user-pill-bg-color: rgba(0, 0, 0, 0.1);
|
$pill-hover-bg-color: #ccc;
|
||||||
$rte-bg-color: #e9e9e9;
|
$rte-bg-color: #e9e9e9;
|
||||||
$rte-code-bg-color: rgba(0, 0, 0, 0.04);
|
$rte-code-bg-color: rgba(0, 0, 0, 0.04);
|
||||||
// ********************
|
// ********************
|
||||||
|
|
|
@ -13,67 +13,82 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { Room } from 'matrix-js-sdk/src/models/room';
|
import { Room } from 'matrix-js-sdk/src/models/room';
|
||||||
import { RoomMember } from 'matrix-js-sdk/src/models/room-member';
|
import { RoomMember } from 'matrix-js-sdk/src/models/room-member';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
import { MatrixClient } from 'matrix-js-sdk/src/client';
|
||||||
|
|
||||||
import dis from '../../../dispatcher/dispatcher';
|
import dis from '../../../dispatcher/dispatcher';
|
||||||
import { MatrixClientPeg } from '../../../MatrixClientPeg';
|
import { MatrixClientPeg } from '../../../MatrixClientPeg';
|
||||||
import { getPrimaryPermalinkEntity, parsePermalink } from "../../../utils/permalinks/Permalinks";
|
import { getPrimaryPermalinkEntity, parsePermalink } from "../../../utils/permalinks/Permalinks";
|
||||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||||
import { Action } from "../../../dispatcher/actions";
|
import { Action } from "../../../dispatcher/actions";
|
||||||
import Tooltip from './Tooltip';
|
import Tooltip, { Alignment } from './Tooltip';
|
||||||
import RoomAvatar from "../avatars/RoomAvatar";
|
import RoomAvatar from '../avatars/RoomAvatar';
|
||||||
import MemberAvatar from "../avatars/MemberAvatar";
|
import MemberAvatar from '../avatars/MemberAvatar';
|
||||||
|
|
||||||
class Pill extends React.Component {
|
export enum PillType {
|
||||||
static roomNotifPos(text) {
|
UserMention = 'TYPE_USER_MENTION',
|
||||||
|
RoomMention = 'TYPE_ROOM_MENTION',
|
||||||
|
AtRoomMention = 'TYPE_AT_ROOM_MENTION', // '@room' mention
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
// The Type of this Pill. If url is given, this is auto-detected.
|
||||||
|
type?: PillType;
|
||||||
|
// The URL to pillify (no validation is done)
|
||||||
|
url?: string;
|
||||||
|
// Whether the pill is in a message
|
||||||
|
inMessage?: boolean;
|
||||||
|
// The room in which this pill is being rendered
|
||||||
|
room?: Room;
|
||||||
|
// Whether to include an avatar in the pill
|
||||||
|
shouldShowPillAvatar?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IState {
|
||||||
|
// ID/alias of the room/user
|
||||||
|
resourceId: string;
|
||||||
|
// Type of pill
|
||||||
|
pillType: string;
|
||||||
|
// The member related to the user pill
|
||||||
|
member?: RoomMember;
|
||||||
|
// The room related to the room pill
|
||||||
|
room?: Room;
|
||||||
|
// Is the user hovering the pill
|
||||||
|
hover: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class Pill extends React.Component<IProps, IState> {
|
||||||
|
private unmounted = true;
|
||||||
|
private matrixClient: MatrixClient;
|
||||||
|
|
||||||
|
public static roomNotifPos(text: string): number {
|
||||||
return text.indexOf("@room");
|
return text.indexOf("@room");
|
||||||
}
|
}
|
||||||
|
|
||||||
static roomNotifLen() {
|
public static roomNotifLen(): number {
|
||||||
return "@room".length;
|
return "@room".length;
|
||||||
}
|
}
|
||||||
|
|
||||||
static TYPE_USER_MENTION = 'TYPE_USER_MENTION';
|
constructor(props: IProps) {
|
||||||
static TYPE_ROOM_MENTION = 'TYPE_ROOM_MENTION';
|
super(props);
|
||||||
static TYPE_AT_ROOM_MENTION = 'TYPE_AT_ROOM_MENTION'; // '@room' mention
|
|
||||||
|
|
||||||
static propTypes = {
|
this.state = {
|
||||||
// The Type of this Pill. If url is given, this is auto-detected.
|
resourceId: null,
|
||||||
type: PropTypes.string,
|
pillType: null,
|
||||||
// The URL to pillify (no validation is done)
|
member: null,
|
||||||
url: PropTypes.string,
|
room: null,
|
||||||
// Whether the pill is in a message
|
hover: false,
|
||||||
inMessage: PropTypes.bool,
|
};
|
||||||
// The room in which this pill is being rendered
|
}
|
||||||
room: PropTypes.instanceOf(Room),
|
|
||||||
// Whether to include an avatar in the pill
|
|
||||||
shouldShowPillAvatar: PropTypes.bool,
|
|
||||||
// Whether to render this pill as if it were highlit by a selection
|
|
||||||
isSelected: PropTypes.bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
state = {
|
|
||||||
// ID/alias of the room/user
|
|
||||||
resourceId: null,
|
|
||||||
// Type of pill
|
|
||||||
pillType: null,
|
|
||||||
|
|
||||||
// The member related to the user pill
|
|
||||||
member: null,
|
|
||||||
// The room related to the room pill
|
|
||||||
room: null,
|
|
||||||
// Is the user hovering the pill
|
|
||||||
hover: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: [REACT-WARNING] Replace with appropriate lifecycle event
|
// TODO: [REACT-WARNING] Replace with appropriate lifecycle event
|
||||||
// eslint-disable-next-line camelcase
|
// eslint-disable-next-line camelcase, @typescript-eslint/naming-convention
|
||||||
async UNSAFE_componentWillReceiveProps(nextProps) {
|
public async UNSAFE_componentWillReceiveProps(nextProps: IProps): Promise<void> {
|
||||||
let resourceId;
|
let resourceId;
|
||||||
let prefix;
|
let prefix;
|
||||||
|
|
||||||
|
@ -89,28 +104,28 @@ class Pill extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
const pillType = this.props.type || {
|
const pillType = this.props.type || {
|
||||||
'@': Pill.TYPE_USER_MENTION,
|
'@': PillType.UserMention,
|
||||||
'#': Pill.TYPE_ROOM_MENTION,
|
'#': PillType.RoomMention,
|
||||||
'!': Pill.TYPE_ROOM_MENTION,
|
'!': PillType.RoomMention,
|
||||||
}[prefix];
|
}[prefix];
|
||||||
|
|
||||||
let member;
|
let member;
|
||||||
let room;
|
let room;
|
||||||
switch (pillType) {
|
switch (pillType) {
|
||||||
case Pill.TYPE_AT_ROOM_MENTION: {
|
case PillType.AtRoomMention: {
|
||||||
room = nextProps.room;
|
room = nextProps.room;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Pill.TYPE_USER_MENTION: {
|
case PillType.UserMention: {
|
||||||
const localMember = nextProps.room ? nextProps.room.getMember(resourceId) : undefined;
|
const localMember = nextProps.room ? nextProps.room.getMember(resourceId) : undefined;
|
||||||
member = localMember;
|
member = localMember;
|
||||||
if (!localMember) {
|
if (!localMember) {
|
||||||
member = new RoomMember(null, resourceId);
|
member = new RoomMember(null, resourceId);
|
||||||
this.doProfileLookup(resourceId, member);
|
this.doProfileLookup(resourceId, member);
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case Pill.TYPE_ROOM_MENTION: {
|
break;
|
||||||
|
case PillType.RoomMention: {
|
||||||
const localRoom = resourceId[0] === '#' ?
|
const localRoom = resourceId[0] === '#' ?
|
||||||
MatrixClientPeg.get().getRooms().find((r) => {
|
MatrixClientPeg.get().getRooms().find((r) => {
|
||||||
return r.getCanonicalAlias() === resourceId ||
|
return r.getCanonicalAlias() === resourceId ||
|
||||||
|
@ -122,39 +137,39 @@ class Pill extends React.Component {
|
||||||
// a room avatar and name.
|
// a room avatar and name.
|
||||||
// this.doRoomProfileLookup(resourceId, member);
|
// this.doRoomProfileLookup(resourceId, member);
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
this.setState({ resourceId, pillType, member, room });
|
this.setState({ resourceId, pillType, member, room });
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
public componentDidMount(): void {
|
||||||
this._unmounted = false;
|
this.unmounted = false;
|
||||||
this._matrixClient = MatrixClientPeg.get();
|
this.matrixClient = MatrixClientPeg.get();
|
||||||
|
|
||||||
// eslint-disable-next-line new-cap
|
// eslint-disable-next-line new-cap
|
||||||
this.UNSAFE_componentWillReceiveProps(this.props); // HACK: We shouldn't be calling lifecycle functions ourselves.
|
this.UNSAFE_componentWillReceiveProps(this.props); // HACK: We shouldn't be calling lifecycle functions ourselves.
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
public componentWillUnmount(): void {
|
||||||
this._unmounted = true;
|
this.unmounted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
onMouseOver = () => {
|
private onMouseOver = (): void => {
|
||||||
this.setState({
|
this.setState({
|
||||||
hover: true,
|
hover: true,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
onMouseLeave = () => {
|
private onMouseLeave = (): void => {
|
||||||
this.setState({
|
this.setState({
|
||||||
hover: false,
|
hover: false,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
doProfileLookup(userId, member) {
|
private doProfileLookup(userId: string, member): void {
|
||||||
MatrixClientPeg.get().getProfileInfo(userId).then((resp) => {
|
MatrixClientPeg.get().getProfileInfo(userId).then((resp) => {
|
||||||
if (this._unmounted) {
|
if (this.unmounted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
member.name = resp.displayname;
|
member.name = resp.displayname;
|
||||||
|
@ -173,7 +188,7 @@ class Pill extends React.Component {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onUserPillClicked = (e) => {
|
private onUserPillClicked = (e): void => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
dis.dispatch({
|
dis.dispatch({
|
||||||
action: Action.ViewUser,
|
action: Action.ViewUser,
|
||||||
|
@ -181,7 +196,7 @@ class Pill extends React.Component {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
public render(): JSX.Element {
|
||||||
const resource = this.state.resourceId;
|
const resource = this.state.resourceId;
|
||||||
|
|
||||||
let avatar = null;
|
let avatar = null;
|
||||||
|
@ -191,7 +206,7 @@ class Pill extends React.Component {
|
||||||
let href = this.props.url;
|
let href = this.props.url;
|
||||||
let onClick;
|
let onClick;
|
||||||
switch (this.state.pillType) {
|
switch (this.state.pillType) {
|
||||||
case Pill.TYPE_AT_ROOM_MENTION: {
|
case PillType.AtRoomMention: {
|
||||||
const room = this.props.room;
|
const room = this.props.room;
|
||||||
if (room) {
|
if (room) {
|
||||||
linkText = "@room";
|
linkText = "@room";
|
||||||
|
@ -200,9 +215,9 @@ class Pill extends React.Component {
|
||||||
}
|
}
|
||||||
pillClass = 'mx_AtRoomPill';
|
pillClass = 'mx_AtRoomPill';
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case Pill.TYPE_USER_MENTION: {
|
break;
|
||||||
|
case PillType.UserMention: {
|
||||||
// If this user is not a member of this room, default to the empty member
|
// If this user is not a member of this room, default to the empty member
|
||||||
const member = this.state.member;
|
const member = this.state.member;
|
||||||
if (member) {
|
if (member) {
|
||||||
|
@ -216,9 +231,9 @@ class Pill extends React.Component {
|
||||||
href = null;
|
href = null;
|
||||||
onClick = this.onUserPillClicked;
|
onClick = this.onUserPillClicked;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case Pill.TYPE_ROOM_MENTION: {
|
break;
|
||||||
|
case PillType.RoomMention: {
|
||||||
const room = this.state.room;
|
const room = this.state.room;
|
||||||
if (room) {
|
if (room) {
|
||||||
linkText = room.name || resource;
|
linkText = room.name || resource;
|
||||||
|
@ -226,31 +241,27 @@ class Pill extends React.Component {
|
||||||
avatar = <RoomAvatar room={room} width={16} height={16} aria-hidden="true" />;
|
avatar = <RoomAvatar room={room} width={16} height={16} aria-hidden="true" />;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pillClass = 'mx_RoomPill';
|
pillClass = room?.isSpaceRoom() ? "mx_SpacePill" : "mx_RoomPill";
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const classes = classNames("mx_Pill", pillClass, {
|
const classes = classNames("mx_Pill", pillClass, {
|
||||||
"mx_UserPill_me": userId === MatrixClientPeg.get().getUserId(),
|
"mx_UserPill_me": userId === MatrixClientPeg.get().getUserId(),
|
||||||
"mx_UserPill_selected": this.props.isSelected,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.state.pillType) {
|
if (this.state.pillType) {
|
||||||
const { yOffset } = this.props;
|
|
||||||
|
|
||||||
let tip;
|
let tip;
|
||||||
if (this.state.hover && resource) {
|
if (this.state.hover && resource) {
|
||||||
tip = <Tooltip label={resource} yOffset={yOffset} />;
|
tip = <Tooltip label={resource} alignment={Alignment.Right} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return <MatrixClientContext.Provider value={this._matrixClient}>
|
return <MatrixClientContext.Provider value={this.matrixClient}>
|
||||||
{ this.props.inMessage ?
|
{ this.props.inMessage ?
|
||||||
<a
|
<a
|
||||||
className={classes}
|
className={classes}
|
||||||
href={href}
|
href={href}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
data-offset-key={this.props.offsetKey}
|
|
||||||
onMouseOver={this.onMouseOver}
|
onMouseOver={this.onMouseOver}
|
||||||
onMouseLeave={this.onMouseLeave}
|
onMouseLeave={this.onMouseLeave}
|
||||||
>
|
>
|
||||||
|
@ -260,7 +271,6 @@ class Pill extends React.Component {
|
||||||
</a> :
|
</a> :
|
||||||
<span
|
<span
|
||||||
className={classes}
|
className={classes}
|
||||||
data-offset-key={this.props.offsetKey}
|
|
||||||
onMouseOver={this.onMouseOver}
|
onMouseOver={this.onMouseOver}
|
||||||
onMouseLeave={this.onMouseLeave}
|
onMouseLeave={this.onMouseLeave}
|
||||||
>
|
>
|
||||||
|
@ -275,5 +285,3 @@ class Pill extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Pill;
|
|
|
@ -31,7 +31,7 @@ import { getUserNameColorClass } from "../../../utils/FormattingUtils";
|
||||||
import { Action } from "../../../dispatcher/actions";
|
import { Action } from "../../../dispatcher/actions";
|
||||||
import Spinner from './Spinner';
|
import Spinner from './Spinner';
|
||||||
import ReplyTile from "../rooms/ReplyTile";
|
import ReplyTile from "../rooms/ReplyTile";
|
||||||
import Pill from './Pill';
|
import Pill, { PillType } from './Pill';
|
||||||
import { ButtonEvent } from './AccessibleButton';
|
import { ButtonEvent } from './AccessibleButton';
|
||||||
import { getParentEventId, shouldDisplayReply } from '../../../utils/Reply';
|
import { getParentEventId, shouldDisplayReply } from '../../../utils/Reply';
|
||||||
import RoomContext from "../../../contexts/RoomContext";
|
import RoomContext from "../../../contexts/RoomContext";
|
||||||
|
@ -223,7 +223,7 @@ export default class ReplyChain extends React.Component<IProps, IState> {
|
||||||
),
|
),
|
||||||
'pill': (
|
'pill': (
|
||||||
<Pill
|
<Pill
|
||||||
type={Pill.TYPE_USER_MENTION}
|
type={PillType.UserMention}
|
||||||
room={room}
|
room={room}
|
||||||
url={makeUserPermalink(ev.getSender())}
|
url={makeUserPermalink(ev.getSender())}
|
||||||
shouldShowPillAvatar={SettingsStore.getValue("Pill.shouldShowPillAvatar")}
|
shouldShowPillAvatar={SettingsStore.getValue("Pill.shouldShowPillAvatar")}
|
||||||
|
|
|
@ -21,7 +21,7 @@ import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
|
||||||
import { _t } from "../../../languageHandler";
|
import { _t } from "../../../languageHandler";
|
||||||
import Pill from "../elements/Pill";
|
import Pill, { PillType } from "../elements/Pill";
|
||||||
import { makeUserPermalink } from "../../../utils/permalinks/Permalinks";
|
import { makeUserPermalink } from "../../../utils/permalinks/Permalinks";
|
||||||
import BaseAvatar from "../avatars/BaseAvatar";
|
import BaseAvatar from "../avatars/BaseAvatar";
|
||||||
import SettingsStore from "../../../settings/SettingsStore";
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
|
@ -93,7 +93,7 @@ export default class BridgeTile extends React.PureComponent<IProps> {
|
||||||
if (content.creator) {
|
if (content.creator) {
|
||||||
creator = <li>{ _t("This bridge was provisioned by <user />.", {}, {
|
creator = <li>{ _t("This bridge was provisioned by <user />.", {}, {
|
||||||
user: () => <Pill
|
user: () => <Pill
|
||||||
type={Pill.TYPE_USER_MENTION}
|
type={PillType.UserMention}
|
||||||
room={this.props.room}
|
room={this.props.room}
|
||||||
url={makeUserPermalink(content.creator)}
|
url={makeUserPermalink(content.creator)}
|
||||||
shouldShowPillAvatar={SettingsStore.getValue("Pill.shouldShowPillAvatar")}
|
shouldShowPillAvatar={SettingsStore.getValue("Pill.shouldShowPillAvatar")}
|
||||||
|
@ -103,7 +103,7 @@ export default class BridgeTile extends React.PureComponent<IProps> {
|
||||||
|
|
||||||
const bot = <li>{ _t("This bridge is managed by <user />.", {}, {
|
const bot = <li>{ _t("This bridge is managed by <user />.", {}, {
|
||||||
user: () => <Pill
|
user: () => <Pill
|
||||||
type={Pill.TYPE_USER_MENTION}
|
type={PillType.UserMention}
|
||||||
room={this.props.room}
|
room={this.props.room}
|
||||||
url={makeUserPermalink(content.bridgebot)}
|
url={makeUserPermalink(content.bridgebot)}
|
||||||
shouldShowPillAvatar={SettingsStore.getValue("Pill.shouldShowPillAvatar")}
|
shouldShowPillAvatar={SettingsStore.getValue("Pill.shouldShowPillAvatar")}
|
||||||
|
|
|
@ -423,7 +423,7 @@ class RoomPillPart extends PillPart {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected get className() {
|
protected get className() {
|
||||||
return "mx_RoomPill mx_Pill";
|
return "mx_Pill " + (this.room.isSpaceRoom() ? "mx_SpacePill" : "mx_RoomPill");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||||
|
|
||||||
import { MatrixClientPeg } from '../MatrixClientPeg';
|
import { MatrixClientPeg } from '../MatrixClientPeg';
|
||||||
import SettingsStore from "../settings/SettingsStore";
|
import SettingsStore from "../settings/SettingsStore";
|
||||||
import Pill from "../components/views/elements/Pill";
|
import Pill, { PillType } from "../components/views/elements/Pill";
|
||||||
import { parsePermalink } from "./permalinks/Permalinks";
|
import { parsePermalink } from "./permalinks/Permalinks";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -113,7 +113,7 @@ export function pillifyLinks(nodes: ArrayLike<Element>, mxEvent: MatrixEvent, pi
|
||||||
|
|
||||||
const pillContainer = document.createElement('span');
|
const pillContainer = document.createElement('span');
|
||||||
const pill = <Pill
|
const pill = <Pill
|
||||||
type={Pill.TYPE_AT_ROOM_MENTION}
|
type={PillType.AtRoomMention}
|
||||||
inMessage={true}
|
inMessage={true}
|
||||||
room={room}
|
room={room}
|
||||||
shouldShowPillAvatar={shouldShowPillAvatar}
|
shouldShowPillAvatar={shouldShowPillAvatar}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue