mirror of https://github.com/vector-im/riot-web
Replace timeline tooltips to match breadcrumb tooltips
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>pull/21833/head
parent
145b154a01
commit
646c5d4a64
|
@ -76,17 +76,16 @@ limitations under the License.
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_Tooltip_timeline {
|
.mx_Tooltip_timeline {
|
||||||
box-shadow: none;
|
margin-left: -42px;
|
||||||
background-color: $tooltip-timeline-bg-color;
|
margin-top: -42px;
|
||||||
color: $tooltip-timeline-fg-color;
|
|
||||||
text-align: center;
|
|
||||||
border: none;
|
|
||||||
border-radius: 3px;
|
|
||||||
font-size: $font-14px;
|
|
||||||
line-height: 1.2;
|
|
||||||
padding: 6px 8px;
|
|
||||||
|
|
||||||
.mx_Tooltip_chevron::after {
|
&.mx_Tooltip {
|
||||||
border-right-color: $tooltip-timeline-bg-color;
|
background-color: $inverted-bg-color;
|
||||||
|
color: $accent-fg-color;
|
||||||
|
border: 0;
|
||||||
|
|
||||||
|
.mx_Tooltip_chevron {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import Tooltip from './Tooltip';
|
||||||
|
|
||||||
interface ITooltipProps extends IProps {
|
interface ITooltipProps extends IProps {
|
||||||
title: string;
|
title: string;
|
||||||
|
tooltip?: React.ReactNode;
|
||||||
tooltipClassName?: string;
|
tooltipClassName?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +53,7 @@ export default class AccessibleTooltipButton extends React.PureComponent<IToolti
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {title, children, ...props} = this.props;
|
const {title, children, tooltip, ...props} = this.props;
|
||||||
const tooltipClassName = classnames(
|
const tooltipClassName = classnames(
|
||||||
"mx_AccessibleTooltipButton_tooltip",
|
"mx_AccessibleTooltipButton_tooltip",
|
||||||
this.props.tooltipClassName,
|
this.props.tooltipClassName,
|
||||||
|
@ -61,7 +62,7 @@ export default class AccessibleTooltipButton extends React.PureComponent<IToolti
|
||||||
const tip = this.state.hover ? <Tooltip
|
const tip = this.state.hover ? <Tooltip
|
||||||
className="mx_AccessibleTooltipButton_container"
|
className="mx_AccessibleTooltipButton_container"
|
||||||
tooltipClassName={tooltipClassName}
|
tooltipClassName={tooltipClassName}
|
||||||
label={title}
|
label={tooltip || title}
|
||||||
/> : <div />;
|
/> : <div />;
|
||||||
return (
|
return (
|
||||||
<AccessibleButton {...props} onMouseOver={this.onMouseOver} onMouseOut={this.onMouseOut} aria-label={title}>
|
<AccessibleButton {...props} onMouseOver={this.onMouseOver} onMouseOut={this.onMouseOut} aria-label={title}>
|
||||||
|
|
|
@ -19,10 +19,11 @@ import PropTypes from 'prop-types';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
||||||
import * as sdk from '../../../index';
|
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
import { formatCommaSeparatedList } from '../../../utils/FormattingUtils';
|
import { formatCommaSeparatedList } from '../../../utils/FormattingUtils';
|
||||||
import dis from "../../../dispatcher/dispatcher";
|
import dis from "../../../dispatcher/dispatcher";
|
||||||
|
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
|
||||||
|
import {unicodeToShortcode} from "../../../HtmlUtils";
|
||||||
|
|
||||||
export default class ReactionsRowButton extends React.PureComponent {
|
export default class ReactionsRowButton extends React.PureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
@ -38,14 +39,6 @@ export default class ReactionsRowButton extends React.PureComponent {
|
||||||
myReactionEvent: PropTypes.object,
|
myReactionEvent: PropTypes.object,
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
tooltipVisible: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
onClick = (ev) => {
|
onClick = (ev) => {
|
||||||
const { mxEvent, myReactionEvent, content } = this.props;
|
const { mxEvent, myReactionEvent, content } = this.props;
|
||||||
if (myReactionEvent) {
|
if (myReactionEvent) {
|
||||||
|
@ -65,24 +58,7 @@ export default class ReactionsRowButton extends React.PureComponent {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onMouseOver = () => {
|
|
||||||
this.setState({
|
|
||||||
// To avoid littering the DOM with a tooltip for every reaction,
|
|
||||||
// only render it on first use.
|
|
||||||
tooltipRendered: true,
|
|
||||||
tooltipVisible: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onMouseOut = () => {
|
|
||||||
this.setState({
|
|
||||||
tooltipVisible: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const ReactionsRowButtonTooltip =
|
|
||||||
sdk.getComponent('messages.ReactionsRowButtonTooltip');
|
|
||||||
const { mxEvent, content, count, reactionEvents, myReactionEvent } = this.props;
|
const { mxEvent, content, count, reactionEvents, myReactionEvent } = this.props;
|
||||||
|
|
||||||
const classes = classNames({
|
const classes = classNames({
|
||||||
|
@ -90,18 +66,9 @@ export default class ReactionsRowButton extends React.PureComponent {
|
||||||
mx_ReactionsRowButton_selected: !!myReactionEvent,
|
mx_ReactionsRowButton_selected: !!myReactionEvent,
|
||||||
});
|
});
|
||||||
|
|
||||||
let tooltip;
|
|
||||||
if (this.state.tooltipRendered) {
|
|
||||||
tooltip = <ReactionsRowButtonTooltip
|
|
||||||
mxEvent={this.props.mxEvent}
|
|
||||||
content={content}
|
|
||||||
reactionEvents={reactionEvents}
|
|
||||||
visible={this.state.tooltipVisible}
|
|
||||||
/>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const room = MatrixClientPeg.get().getRoom(mxEvent.getRoomId());
|
const room = MatrixClientPeg.get().getRoom(mxEvent.getRoomId());
|
||||||
let label;
|
let label;
|
||||||
|
let tooltip;
|
||||||
if (room) {
|
if (room) {
|
||||||
const senders = [];
|
const senders = [];
|
||||||
for (const reactionEvent of reactionEvents) {
|
for (const reactionEvent of reactionEvents) {
|
||||||
|
@ -126,14 +93,37 @@ export default class ReactionsRowButton extends React.PureComponent {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const shortName = unicodeToShortcode(content);
|
||||||
|
tooltip = <div>{_t(
|
||||||
|
"<reactors/><reactedWith>reacted with %(shortName)s</reactedWith>",
|
||||||
|
{
|
||||||
|
shortName,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reactors: () => {
|
||||||
|
return <div className="mx_ReactionsRowButtonTooltip_senders">
|
||||||
|
{formatCommaSeparatedList(senders, 6)}
|
||||||
|
</div>;
|
||||||
|
},
|
||||||
|
reactedWith: (sub) => {
|
||||||
|
if (!shortName) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return <div className="mx_ReactionsRowButtonTooltip_reactedWith">
|
||||||
|
{sub}
|
||||||
|
</div>;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)}</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
|
return <AccessibleTooltipButton
|
||||||
return <AccessibleButton className={classes}
|
className={classes}
|
||||||
aria-label={label}
|
|
||||||
onClick={this.onClick}
|
onClick={this.onClick}
|
||||||
onMouseOver={this.onMouseOver}
|
title={label}
|
||||||
onMouseOut={this.onMouseOut}
|
tooltip={tooltip}
|
||||||
|
tooltipClassName="mx_Tooltip_timeline"
|
||||||
>
|
>
|
||||||
<span className="mx_ReactionsRowButton_content" aria-hidden="true">
|
<span className="mx_ReactionsRowButton_content" aria-hidden="true">
|
||||||
{content}
|
{content}
|
||||||
|
@ -141,7 +131,6 @@ export default class ReactionsRowButton extends React.PureComponent {
|
||||||
<span className="mx_ReactionsRowButton_count" aria-hidden="true">
|
<span className="mx_ReactionsRowButton_count" aria-hidden="true">
|
||||||
{count}
|
{count}
|
||||||
</span>
|
</span>
|
||||||
{tooltip}
|
</AccessibleTooltipButton>;
|
||||||
</AccessibleButton>;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,85 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2019 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 from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
|
||||||
import * as sdk from '../../../index';
|
|
||||||
import { unicodeToShortcode } from '../../../HtmlUtils';
|
|
||||||
import { _t } from '../../../languageHandler';
|
|
||||||
import { formatCommaSeparatedList } from '../../../utils/FormattingUtils';
|
|
||||||
|
|
||||||
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,
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const Tooltip = sdk.getComponent('elements.Tooltip');
|
|
||||||
const { content, reactionEvents, mxEvent, visible } = this.props;
|
|
||||||
|
|
||||||
const room = MatrixClientPeg.get().getRoom(mxEvent.getRoomId());
|
|
||||||
let tooltipLabel;
|
|
||||||
if (room) {
|
|
||||||
const senders = [];
|
|
||||||
for (const reactionEvent of reactionEvents) {
|
|
||||||
const member = room.getMember(reactionEvent.getSender());
|
|
||||||
const name = member ? member.name : reactionEvent.getSender();
|
|
||||||
senders.push(name);
|
|
||||||
}
|
|
||||||
const shortName = unicodeToShortcode(content);
|
|
||||||
tooltipLabel = <div>{_t(
|
|
||||||
"<reactors/><reactedWith>reacted with %(shortName)s</reactedWith>",
|
|
||||||
{
|
|
||||||
shortName,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
reactors: () => {
|
|
||||||
return <div className="mx_ReactionsRowButtonTooltip_senders">
|
|
||||||
{formatCommaSeparatedList(senders, 6)}
|
|
||||||
</div>;
|
|
||||||
},
|
|
||||||
reactedWith: (sub) => {
|
|
||||||
if (!shortName) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return <div className="mx_ReactionsRowButtonTooltip_reactedWith">
|
|
||||||
{sub}
|
|
||||||
</div>;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)}</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
let tooltip;
|
|
||||||
if (tooltipLabel) {
|
|
||||||
tooltip = <Tooltip
|
|
||||||
tooltipClassName="mx_Tooltip_timeline"
|
|
||||||
visible={visible}
|
|
||||||
label={tooltipLabel}
|
|
||||||
/>;
|
|
||||||
}
|
|
||||||
|
|
||||||
return tooltip;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -35,6 +35,7 @@ import {IntegrationManagers} from "../../../integrations/IntegrationManagers";
|
||||||
import {isPermalinkHost} from "../../../utils/permalinks/Permalinks";
|
import {isPermalinkHost} from "../../../utils/permalinks/Permalinks";
|
||||||
import {toRightOf} from "../../structures/ContextMenu";
|
import {toRightOf} from "../../structures/ContextMenu";
|
||||||
import {copyPlaintext} from "../../../utils/strings";
|
import {copyPlaintext} from "../../../utils/strings";
|
||||||
|
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
|
||||||
|
|
||||||
export default createReactClass({
|
export default createReactClass({
|
||||||
displayName: 'TextualBody',
|
displayName: 'TextualBody',
|
||||||
|
@ -146,7 +147,6 @@ export default createReactClass({
|
||||||
nextProps.showUrlPreview !== this.props.showUrlPreview ||
|
nextProps.showUrlPreview !== this.props.showUrlPreview ||
|
||||||
nextProps.editState !== this.props.editState ||
|
nextProps.editState !== this.props.editState ||
|
||||||
nextState.links !== this.state.links ||
|
nextState.links !== this.state.links ||
|
||||||
nextState.editedMarkerHovered !== this.state.editedMarkerHovered ||
|
|
||||||
nextState.widgetHidden !== this.state.widgetHidden);
|
nextState.widgetHidden !== this.state.widgetHidden);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -367,42 +367,24 @@ export default createReactClass({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
_onMouseEnterEditedMarker: function() {
|
|
||||||
this.setState({editedMarkerHovered: true});
|
|
||||||
},
|
|
||||||
|
|
||||||
_onMouseLeaveEditedMarker: function() {
|
|
||||||
this.setState({editedMarkerHovered: false});
|
|
||||||
},
|
|
||||||
|
|
||||||
_openHistoryDialog: async function() {
|
_openHistoryDialog: async function() {
|
||||||
const MessageEditHistoryDialog = sdk.getComponent("views.dialogs.MessageEditHistoryDialog");
|
const MessageEditHistoryDialog = sdk.getComponent("views.dialogs.MessageEditHistoryDialog");
|
||||||
Modal.createDialog(MessageEditHistoryDialog, {mxEvent: this.props.mxEvent});
|
Modal.createDialog(MessageEditHistoryDialog, {mxEvent: this.props.mxEvent});
|
||||||
},
|
},
|
||||||
|
|
||||||
_renderEditedMarker: function() {
|
_renderEditedMarker: function() {
|
||||||
let editedTooltip;
|
const date = this.props.mxEvent.replacingEventDate();
|
||||||
if (this.state.editedMarkerHovered) {
|
const dateString = date && formatDate(date);
|
||||||
const Tooltip = sdk.getComponent('elements.Tooltip');
|
|
||||||
const date = this.props.mxEvent.replacingEventDate();
|
|
||||||
const dateString = date && formatDate(date);
|
|
||||||
editedTooltip = <Tooltip
|
|
||||||
tooltipClassName="mx_Tooltip_timeline"
|
|
||||||
label={_t("Edited at %(date)s. Click to view edits.", {date: dateString})}
|
|
||||||
/>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
|
|
||||||
return (
|
return (
|
||||||
<AccessibleButton
|
<AccessibleTooltipButton
|
||||||
key="editedMarker"
|
|
||||||
className="mx_EventTile_edited"
|
className="mx_EventTile_edited"
|
||||||
onClick={this._openHistoryDialog}
|
onClick={this._openHistoryDialog}
|
||||||
onMouseEnter={this._onMouseEnterEditedMarker}
|
title={_t("Edited at %(date)s. Click to view edits.", {date: dateString})}
|
||||||
onMouseLeave={this._onMouseLeaveEditedMarker}
|
tooltipClassName="mx_Tooltip_timeline"
|
||||||
>
|
>
|
||||||
{ editedTooltip }<span>{`(${_t("edited")})`}</span>
|
<span>{`(${_t("edited")})`}</span>
|
||||||
</AccessibleButton>
|
</AccessibleTooltipButton>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue