Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit 75b03ca

Browse files
authored
Reuse CopyableText component in all places it can be (#7701)
1 parent 292971d commit 75b03ca

File tree

5 files changed

+27
-136
lines changed

5 files changed

+27
-136
lines changed

res/css/views/dialogs/_InviteDialog.scss

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -130,12 +130,8 @@ limitations under the License.
130130
text-transform: uppercase;
131131
}
132132

133-
.mx_InviteDialog_footer_link {
134-
display: flex;
135-
justify-content: space-between;
136-
border-radius: 4px;
137-
border: solid 1px $light-fg-color;
138-
padding: 8px;
133+
.mx_CopyableText {
134+
width: unset; // full width
139135

140136
> a {
141137
text-decoration: none;
@@ -144,22 +140,6 @@ limitations under the License.
144140
text-overflow: ellipsis;
145141
}
146142
}
147-
148-
.mx_InviteDialog_footer_link_copy {
149-
flex-shrink: 0;
150-
cursor: pointer;
151-
margin-left: 20px;
152-
display: inherit;
153-
154-
> div {
155-
mask-image: url($copy-button-url);
156-
background-color: $message-action-bar-fg-color;
157-
margin-left: 5px;
158-
width: 20px;
159-
height: 20px;
160-
background-repeat: no-repeat;
161-
}
162-
}
163143
}
164144

165145
.mx_InviteDialog_roomTile {

res/css/views/dialogs/_ShareDialog.scss

Lines changed: 12 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -20,44 +20,20 @@ limitations under the License.
2020
border-color: $light-fg-color;
2121
}
2222

23-
.mx_ShareDialog_content {
23+
.mx_ShareDialog .mx_ShareDialog_content {
2424
margin: 10px 0;
25-
}
26-
27-
.mx_ShareDialog_matrixto {
28-
display: flex;
29-
justify-content: space-between;
30-
border-radius: 5px;
31-
border: solid 1px $light-fg-color;
32-
margin-bottom: 10px;
33-
margin-top: 30px;
34-
padding: 10px;
35-
}
3625

37-
.mx_ShareDialog_matrixto a {
38-
text-decoration: none;
39-
}
40-
41-
.mx_ShareDialog_matrixto_link {
42-
flex-shrink: 1;
43-
overflow: hidden;
44-
text-overflow: ellipsis;
45-
}
46-
47-
.mx_ShareDialog_matrixto_copy {
48-
flex-shrink: 0;
49-
cursor: pointer;
50-
margin-left: 20px;
51-
display: inherit;
52-
}
53-
.mx_ShareDialog_matrixto_copy::after {
54-
content: "";
55-
mask-image: url($copy-button-url);
56-
background-color: $message-action-bar-fg-color;
57-
margin-left: 5px;
58-
width: 20px;
59-
height: 20px;
60-
background-repeat: no-repeat;
26+
.mx_CopyableText {
27+
width: unset; // full width
28+
29+
> a {
30+
text-decoration: none;
31+
flex-shrink: 1;
32+
overflow: hidden;
33+
text-overflow: ellipsis;
34+
white-space: nowrap;
35+
}
36+
}
6137
}
6238

6339
.mx_ShareDialog_split {

res/css/views/elements/_CopyableText.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717

1818
.mx_CopyableText {
1919
display: flex;
20+
justify-content: space-between;
2021
border-radius: 5px;
2122
border: solid 1px $light-fg-color;
2223
margin-bottom: 10px;

src/components/views/dialogs/InviteDialog.tsx

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,7 @@ import { mediaFromMxc } from "../../../customisations/Media";
5858
import { getAddressType } from "../../../UserAddress";
5959
import BaseAvatar from '../avatars/BaseAvatar';
6060
import AccessibleButton, { ButtonEvent } from '../elements/AccessibleButton';
61-
import { compare, copyPlaintext, selectText } from '../../../utils/strings';
62-
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
63-
import * as ContextMenu from "../../structures/ContextMenu";
64-
import { toRightOf } from "../../structures/ContextMenu";
65-
import GenericTextContextMenu from "../context_menus/GenericTextContextMenu";
61+
import { compare, selectText } from '../../../utils/strings';
6662
import Field from '../elements/Field';
6763
import TabbedView, { Tab, TabLocation } from '../../structures/TabbedView';
6864
import Dialpad from '../voip/DialPad';
@@ -73,6 +69,7 @@ import DialPadBackspaceButton from "../elements/DialPadBackspaceButton";
7369
import SpaceStore from "../../../stores/spaces/SpaceStore";
7470
import CallHandler from "../../../CallHandler";
7571
import UserIdentifierCustomisations from '../../../customisations/UserIdentifier';
72+
import CopyableText from "../elements/CopyableText";
7673

7774
// we have a number of types defined from the Matrix spec which can't reasonably be altered here.
7875
/* eslint-disable camelcase */
@@ -1310,20 +1307,6 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
13101307
selectText(e.target);
13111308
}
13121309

1313-
private onCopyClick = async e => {
1314-
e.preventDefault();
1315-
const target = e.target; // copy target before we go async and React throws it away
1316-
1317-
const successful = await copyPlaintext(makeUserPermalink(MatrixClientPeg.get().getUserId()));
1318-
const buttonRect = target.getBoundingClientRect();
1319-
const { close } = ContextMenu.createMenu(GenericTextContextMenu, {
1320-
...toRightOf(buttonRect, 2),
1321-
message: successful ? _t("Copied!") : _t("Failed to copy"),
1322-
});
1323-
// Drop a reference to this close handler for componentWillUnmount
1324-
this.closeCopiedTooltip = target.onmouseleave = close;
1325-
};
1326-
13271310
render() {
13281311
let spinner = null;
13291312
if (this.state.busy) {
@@ -1409,18 +1392,11 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
14091392
const link = makeUserPermalink(MatrixClientPeg.get().getUserId());
14101393
footer = <div className="mx_InviteDialog_footer">
14111394
<h3>{ _t("Or send invite link") }</h3>
1412-
<div className="mx_InviteDialog_footer_link">
1395+
<CopyableText getTextToCopy={() => makeUserPermalink(MatrixClientPeg.get().getUserId())}>
14131396
<a href={link} onClick={this.onLinkClick}>
14141397
{ link }
14151398
</a>
1416-
<AccessibleTooltipButton
1417-
title={_t("Copy")}
1418-
onClick={this.onCopyClick}
1419-
className="mx_InviteDialog_footer_link_copy"
1420-
>
1421-
<div />
1422-
</AccessibleTooltipButton>
1423-
</div>
1399+
</CopyableText>
14241400
</div>;
14251401
} else if (this.props.kind === KIND_INVITE) {
14261402
const room = MatrixClientPeg.get()?.getRoom(this.props.roomId);

src/components/views/dialogs/ShareDialog.tsx

Lines changed: 8 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ limitations under the License.
1616
*/
1717

1818
import * as React from 'react';
19-
import * as PropTypes from 'prop-types';
2019
import { Room } from "matrix-js-sdk/src/models/room";
2120
import { User } from "matrix-js-sdk/src/models/user";
2221
import { Group } from "matrix-js-sdk/src/models/group";
@@ -26,17 +25,14 @@ import { MatrixEvent } from "matrix-js-sdk/src/models/event";
2625
import { _t } from '../../../languageHandler';
2726
import QRCode from "../elements/QRCode";
2827
import { RoomPermalinkCreator, makeGroupPermalink, makeUserPermalink } from "../../../utils/permalinks/Permalinks";
29-
import * as ContextMenu from "../../structures/ContextMenu";
30-
import { toRightOf } from "../../structures/ContextMenu";
31-
import { copyPlaintext, selectText } from "../../../utils/strings";
28+
import { selectText } from "../../../utils/strings";
3229
import StyledCheckbox from '../elements/StyledCheckbox';
33-
import AccessibleTooltipButton from '../elements/AccessibleTooltipButton';
3430
import { IDialogProps } from "./IDialogProps";
3531
import SettingsStore from "../../../settings/SettingsStore";
3632
import { UIFeature } from "../../../settings/UIFeature";
3733
import { replaceableComponent } from "../../../utils/replaceableComponent";
3834
import BaseDialog from "./BaseDialog";
39-
import GenericTextContextMenu from "../context_menus/GenericTextContextMenu";
35+
import CopyableText from "../elements/CopyableText";
4036

4137
const socials = [
4238
{
@@ -78,25 +74,11 @@ interface IState {
7874

7975
@replaceableComponent("views.dialogs.ShareDialog")
8076
export default class ShareDialog extends React.PureComponent<IProps, IState> {
81-
static propTypes = {
82-
onFinished: PropTypes.func.isRequired,
83-
target: PropTypes.oneOfType([
84-
PropTypes.instanceOf(Room),
85-
PropTypes.instanceOf(User),
86-
PropTypes.instanceOf(Group),
87-
PropTypes.instanceOf(RoomMember),
88-
PropTypes.instanceOf(MatrixEvent),
89-
]).isRequired,
90-
};
91-
9277
protected closeCopiedTooltip: () => void;
9378

9479
constructor(props) {
9580
super(props);
9681

97-
this.onCopyClick = this.onCopyClick.bind(this);
98-
this.onLinkSpecificEventCheckboxClick = this.onLinkSpecificEventCheckboxClick.bind(this);
99-
10082
let permalinkCreator: RoomPermalinkCreator = null;
10183
if (props.target instanceof Room) {
10284
permalinkCreator = new RoomPermalinkCreator(props.target);
@@ -115,33 +97,19 @@ export default class ShareDialog extends React.PureComponent<IProps, IState> {
11597
selectText(e.target);
11698
}
11799

118-
async onCopyClick(e) {
119-
e.preventDefault();
120-
const target = e.target; // copy target before we go async and React throws it away
121-
122-
const successful = await copyPlaintext(this.getUrl());
123-
const buttonRect = target.getBoundingClientRect();
124-
const { close } = ContextMenu.createMenu(GenericTextContextMenu, {
125-
...toRightOf(buttonRect, 2),
126-
message: successful ? _t('Copied!') : _t('Failed to copy'),
127-
});
128-
// Drop a reference to this close handler for componentWillUnmount
129-
this.closeCopiedTooltip = target.onmouseleave = close;
130-
}
131-
132-
onLinkSpecificEventCheckboxClick() {
100+
private onLinkSpecificEventCheckboxClick = () => {
133101
this.setState({
134102
linkSpecificEvent: !this.state.linkSpecificEvent,
135103
});
136-
}
104+
};
137105

138106
componentWillUnmount() {
139107
// if the Copied tooltip is open then get rid of it, there are ways to close the modal which wouldn't close
140108
// the tooltip otherwise, such as pressing Escape or clicking X really quickly
141109
if (this.closeCopiedTooltip) this.closeCopiedTooltip();
142110
}
143111

144-
getUrl() {
112+
private getUrl() {
145113
let matrixToUrl;
146114

147115
if (this.props.target instanceof Room) {
@@ -238,21 +206,11 @@ export default class ShareDialog extends React.PureComponent<IProps, IState> {
238206
onFinished={this.props.onFinished}
239207
>
240208
<div className="mx_ShareDialog_content">
241-
<div className="mx_ShareDialog_matrixto">
242-
<a
243-
title={_t('Link to room')}
244-
href={matrixToUrl}
245-
onClick={ShareDialog.onLinkClick}
246-
className="mx_ShareDialog_matrixto_link"
247-
>
209+
<CopyableText getTextToCopy={() => matrixToUrl}>
210+
<a title={_t('Link to room')} href={matrixToUrl} onClick={ShareDialog.onLinkClick}>
248211
{ matrixToUrl }
249212
</a>
250-
<AccessibleTooltipButton
251-
title={_t("Copy")}
252-
onClick={this.onCopyClick}
253-
className="mx_ShareDialog_matrixto_copy"
254-
/>
255-
</div>
213+
</CopyableText>
256214
{ checkbox }
257215
{ qrSocialSection }
258216
</div>

0 commit comments

Comments
 (0)