Reuse CopyableText component in all places it can be (#7701)
parent
292971dd0e
commit
75b03ca101
|
@ -130,12 +130,8 @@ limitations under the License.
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_InviteDialog_footer_link {
|
.mx_CopyableText {
|
||||||
display: flex;
|
width: unset; // full width
|
||||||
justify-content: space-between;
|
|
||||||
border-radius: 4px;
|
|
||||||
border: solid 1px $light-fg-color;
|
|
||||||
padding: 8px;
|
|
||||||
|
|
||||||
> a {
|
> a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
@ -144,22 +140,6 @@ limitations under the License.
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_InviteDialog_footer_link_copy {
|
|
||||||
flex-shrink: 0;
|
|
||||||
cursor: pointer;
|
|
||||||
margin-left: 20px;
|
|
||||||
display: inherit;
|
|
||||||
|
|
||||||
> div {
|
|
||||||
mask-image: url($copy-button-url);
|
|
||||||
background-color: $message-action-bar-fg-color;
|
|
||||||
margin-left: 5px;
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_InviteDialog_roomTile {
|
.mx_InviteDialog_roomTile {
|
||||||
|
|
|
@ -20,44 +20,20 @@ limitations under the License.
|
||||||
border-color: $light-fg-color;
|
border-color: $light-fg-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_ShareDialog_content {
|
.mx_ShareDialog .mx_ShareDialog_content {
|
||||||
margin: 10px 0;
|
margin: 10px 0;
|
||||||
}
|
|
||||||
|
|
||||||
.mx_ShareDialog_matrixto {
|
.mx_CopyableText {
|
||||||
display: flex;
|
width: unset; // full width
|
||||||
justify-content: space-between;
|
|
||||||
border-radius: 5px;
|
|
||||||
border: solid 1px $light-fg-color;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
margin-top: 30px;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_ShareDialog_matrixto a {
|
> a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
flex-shrink: 1;
|
||||||
|
overflow: hidden;
|
||||||
.mx_ShareDialog_matrixto_link {
|
text-overflow: ellipsis;
|
||||||
flex-shrink: 1;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
}
|
||||||
text-overflow: ellipsis;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.mx_ShareDialog_matrixto_copy {
|
|
||||||
flex-shrink: 0;
|
|
||||||
cursor: pointer;
|
|
||||||
margin-left: 20px;
|
|
||||||
display: inherit;
|
|
||||||
}
|
|
||||||
.mx_ShareDialog_matrixto_copy::after {
|
|
||||||
content: "";
|
|
||||||
mask-image: url($copy-button-url);
|
|
||||||
background-color: $message-action-bar-fg-color;
|
|
||||||
margin-left: 5px;
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_ShareDialog_split {
|
.mx_ShareDialog_split {
|
||||||
|
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
|
|
||||||
.mx_CopyableText {
|
.mx_CopyableText {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
border: solid 1px $light-fg-color;
|
border: solid 1px $light-fg-color;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
|
|
|
@ -58,11 +58,7 @@ import { mediaFromMxc } from "../../../customisations/Media";
|
||||||
import { getAddressType } from "../../../UserAddress";
|
import { getAddressType } from "../../../UserAddress";
|
||||||
import BaseAvatar from '../avatars/BaseAvatar';
|
import BaseAvatar from '../avatars/BaseAvatar';
|
||||||
import AccessibleButton, { ButtonEvent } from '../elements/AccessibleButton';
|
import AccessibleButton, { ButtonEvent } from '../elements/AccessibleButton';
|
||||||
import { compare, copyPlaintext, selectText } from '../../../utils/strings';
|
import { compare, selectText } from '../../../utils/strings';
|
||||||
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
|
|
||||||
import * as ContextMenu from "../../structures/ContextMenu";
|
|
||||||
import { toRightOf } from "../../structures/ContextMenu";
|
|
||||||
import GenericTextContextMenu from "../context_menus/GenericTextContextMenu";
|
|
||||||
import Field from '../elements/Field';
|
import Field from '../elements/Field';
|
||||||
import TabbedView, { Tab, TabLocation } from '../../structures/TabbedView';
|
import TabbedView, { Tab, TabLocation } from '../../structures/TabbedView';
|
||||||
import Dialpad from '../voip/DialPad';
|
import Dialpad from '../voip/DialPad';
|
||||||
|
@ -73,6 +69,7 @@ import DialPadBackspaceButton from "../elements/DialPadBackspaceButton";
|
||||||
import SpaceStore from "../../../stores/spaces/SpaceStore";
|
import SpaceStore from "../../../stores/spaces/SpaceStore";
|
||||||
import CallHandler from "../../../CallHandler";
|
import CallHandler from "../../../CallHandler";
|
||||||
import UserIdentifierCustomisations from '../../../customisations/UserIdentifier';
|
import UserIdentifierCustomisations from '../../../customisations/UserIdentifier';
|
||||||
|
import CopyableText from "../elements/CopyableText";
|
||||||
|
|
||||||
// we have a number of types defined from the Matrix spec which can't reasonably be altered here.
|
// we have a number of types defined from the Matrix spec which can't reasonably be altered here.
|
||||||
/* eslint-disable camelcase */
|
/* eslint-disable camelcase */
|
||||||
|
@ -1310,20 +1307,6 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
|
||||||
selectText(e.target);
|
selectText(e.target);
|
||||||
}
|
}
|
||||||
|
|
||||||
private onCopyClick = async e => {
|
|
||||||
e.preventDefault();
|
|
||||||
const target = e.target; // copy target before we go async and React throws it away
|
|
||||||
|
|
||||||
const successful = await copyPlaintext(makeUserPermalink(MatrixClientPeg.get().getUserId()));
|
|
||||||
const buttonRect = target.getBoundingClientRect();
|
|
||||||
const { close } = ContextMenu.createMenu(GenericTextContextMenu, {
|
|
||||||
...toRightOf(buttonRect, 2),
|
|
||||||
message: successful ? _t("Copied!") : _t("Failed to copy"),
|
|
||||||
});
|
|
||||||
// Drop a reference to this close handler for componentWillUnmount
|
|
||||||
this.closeCopiedTooltip = target.onmouseleave = close;
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let spinner = null;
|
let spinner = null;
|
||||||
if (this.state.busy) {
|
if (this.state.busy) {
|
||||||
|
@ -1409,18 +1392,11 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
|
||||||
const link = makeUserPermalink(MatrixClientPeg.get().getUserId());
|
const link = makeUserPermalink(MatrixClientPeg.get().getUserId());
|
||||||
footer = <div className="mx_InviteDialog_footer">
|
footer = <div className="mx_InviteDialog_footer">
|
||||||
<h3>{ _t("Or send invite link") }</h3>
|
<h3>{ _t("Or send invite link") }</h3>
|
||||||
<div className="mx_InviteDialog_footer_link">
|
<CopyableText getTextToCopy={() => makeUserPermalink(MatrixClientPeg.get().getUserId())}>
|
||||||
<a href={link} onClick={this.onLinkClick}>
|
<a href={link} onClick={this.onLinkClick}>
|
||||||
{ link }
|
{ link }
|
||||||
</a>
|
</a>
|
||||||
<AccessibleTooltipButton
|
</CopyableText>
|
||||||
title={_t("Copy")}
|
|
||||||
onClick={this.onCopyClick}
|
|
||||||
className="mx_InviteDialog_footer_link_copy"
|
|
||||||
>
|
|
||||||
<div />
|
|
||||||
</AccessibleTooltipButton>
|
|
||||||
</div>
|
|
||||||
</div>;
|
</div>;
|
||||||
} else if (this.props.kind === KIND_INVITE) {
|
} else if (this.props.kind === KIND_INVITE) {
|
||||||
const room = MatrixClientPeg.get()?.getRoom(this.props.roomId);
|
const room = MatrixClientPeg.get()?.getRoom(this.props.roomId);
|
||||||
|
|
|
@ -16,7 +16,6 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import * as PropTypes from 'prop-types';
|
|
||||||
import { Room } from "matrix-js-sdk/src/models/room";
|
import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
import { User } from "matrix-js-sdk/src/models/user";
|
import { User } from "matrix-js-sdk/src/models/user";
|
||||||
import { Group } from "matrix-js-sdk/src/models/group";
|
import { Group } from "matrix-js-sdk/src/models/group";
|
||||||
|
@ -26,17 +25,14 @@ import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
import QRCode from "../elements/QRCode";
|
import QRCode from "../elements/QRCode";
|
||||||
import { RoomPermalinkCreator, makeGroupPermalink, makeUserPermalink } from "../../../utils/permalinks/Permalinks";
|
import { RoomPermalinkCreator, makeGroupPermalink, makeUserPermalink } from "../../../utils/permalinks/Permalinks";
|
||||||
import * as ContextMenu from "../../structures/ContextMenu";
|
import { selectText } from "../../../utils/strings";
|
||||||
import { toRightOf } from "../../structures/ContextMenu";
|
|
||||||
import { copyPlaintext, selectText } from "../../../utils/strings";
|
|
||||||
import StyledCheckbox from '../elements/StyledCheckbox';
|
import StyledCheckbox from '../elements/StyledCheckbox';
|
||||||
import AccessibleTooltipButton from '../elements/AccessibleTooltipButton';
|
|
||||||
import { IDialogProps } from "./IDialogProps";
|
import { IDialogProps } from "./IDialogProps";
|
||||||
import SettingsStore from "../../../settings/SettingsStore";
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
import { UIFeature } from "../../../settings/UIFeature";
|
import { UIFeature } from "../../../settings/UIFeature";
|
||||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||||
import BaseDialog from "./BaseDialog";
|
import BaseDialog from "./BaseDialog";
|
||||||
import GenericTextContextMenu from "../context_menus/GenericTextContextMenu";
|
import CopyableText from "../elements/CopyableText";
|
||||||
|
|
||||||
const socials = [
|
const socials = [
|
||||||
{
|
{
|
||||||
|
@ -78,25 +74,11 @@ interface IState {
|
||||||
|
|
||||||
@replaceableComponent("views.dialogs.ShareDialog")
|
@replaceableComponent("views.dialogs.ShareDialog")
|
||||||
export default class ShareDialog extends React.PureComponent<IProps, IState> {
|
export default class ShareDialog extends React.PureComponent<IProps, IState> {
|
||||||
static propTypes = {
|
|
||||||
onFinished: PropTypes.func.isRequired,
|
|
||||||
target: PropTypes.oneOfType([
|
|
||||||
PropTypes.instanceOf(Room),
|
|
||||||
PropTypes.instanceOf(User),
|
|
||||||
PropTypes.instanceOf(Group),
|
|
||||||
PropTypes.instanceOf(RoomMember),
|
|
||||||
PropTypes.instanceOf(MatrixEvent),
|
|
||||||
]).isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
protected closeCopiedTooltip: () => void;
|
protected closeCopiedTooltip: () => void;
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.onCopyClick = this.onCopyClick.bind(this);
|
|
||||||
this.onLinkSpecificEventCheckboxClick = this.onLinkSpecificEventCheckboxClick.bind(this);
|
|
||||||
|
|
||||||
let permalinkCreator: RoomPermalinkCreator = null;
|
let permalinkCreator: RoomPermalinkCreator = null;
|
||||||
if (props.target instanceof Room) {
|
if (props.target instanceof Room) {
|
||||||
permalinkCreator = new RoomPermalinkCreator(props.target);
|
permalinkCreator = new RoomPermalinkCreator(props.target);
|
||||||
|
@ -115,25 +97,11 @@ export default class ShareDialog extends React.PureComponent<IProps, IState> {
|
||||||
selectText(e.target);
|
selectText(e.target);
|
||||||
}
|
}
|
||||||
|
|
||||||
async onCopyClick(e) {
|
private onLinkSpecificEventCheckboxClick = () => {
|
||||||
e.preventDefault();
|
|
||||||
const target = e.target; // copy target before we go async and React throws it away
|
|
||||||
|
|
||||||
const successful = await copyPlaintext(this.getUrl());
|
|
||||||
const buttonRect = target.getBoundingClientRect();
|
|
||||||
const { close } = ContextMenu.createMenu(GenericTextContextMenu, {
|
|
||||||
...toRightOf(buttonRect, 2),
|
|
||||||
message: successful ? _t('Copied!') : _t('Failed to copy'),
|
|
||||||
});
|
|
||||||
// Drop a reference to this close handler for componentWillUnmount
|
|
||||||
this.closeCopiedTooltip = target.onmouseleave = close;
|
|
||||||
}
|
|
||||||
|
|
||||||
onLinkSpecificEventCheckboxClick() {
|
|
||||||
this.setState({
|
this.setState({
|
||||||
linkSpecificEvent: !this.state.linkSpecificEvent,
|
linkSpecificEvent: !this.state.linkSpecificEvent,
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
// if the Copied tooltip is open then get rid of it, there are ways to close the modal which wouldn't close
|
// if the Copied tooltip is open then get rid of it, there are ways to close the modal which wouldn't close
|
||||||
|
@ -141,7 +109,7 @@ export default class ShareDialog extends React.PureComponent<IProps, IState> {
|
||||||
if (this.closeCopiedTooltip) this.closeCopiedTooltip();
|
if (this.closeCopiedTooltip) this.closeCopiedTooltip();
|
||||||
}
|
}
|
||||||
|
|
||||||
getUrl() {
|
private getUrl() {
|
||||||
let matrixToUrl;
|
let matrixToUrl;
|
||||||
|
|
||||||
if (this.props.target instanceof Room) {
|
if (this.props.target instanceof Room) {
|
||||||
|
@ -238,21 +206,11 @@ export default class ShareDialog extends React.PureComponent<IProps, IState> {
|
||||||
onFinished={this.props.onFinished}
|
onFinished={this.props.onFinished}
|
||||||
>
|
>
|
||||||
<div className="mx_ShareDialog_content">
|
<div className="mx_ShareDialog_content">
|
||||||
<div className="mx_ShareDialog_matrixto">
|
<CopyableText getTextToCopy={() => matrixToUrl}>
|
||||||
<a
|
<a title={_t('Link to room')} href={matrixToUrl} onClick={ShareDialog.onLinkClick}>
|
||||||
title={_t('Link to room')}
|
|
||||||
href={matrixToUrl}
|
|
||||||
onClick={ShareDialog.onLinkClick}
|
|
||||||
className="mx_ShareDialog_matrixto_link"
|
|
||||||
>
|
|
||||||
{ matrixToUrl }
|
{ matrixToUrl }
|
||||||
</a>
|
</a>
|
||||||
<AccessibleTooltipButton
|
</CopyableText>
|
||||||
title={_t("Copy")}
|
|
||||||
onClick={this.onCopyClick}
|
|
||||||
className="mx_ShareDialog_matrixto_copy"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{ checkbox }
|
{ checkbox }
|
||||||
{ qrSocialSection }
|
{ qrSocialSection }
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue