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

Add footer and privacy note to the start dm dialog #6111

Merged
merged 14 commits into from
Jun 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 93 additions & 10 deletions res/css/views/dialogs/_InviteDialog.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ limitations under the License.
.mx_InviteDialog_addressBar {
display: flex;
flex-direction: row;
// Right margin for the design. We could apply this to the whole dialog, but then the scrollbar
// for the user section gets weird.
margin: 8px 45px 0 0;

.mx_InviteDialog_editor {
flex: 1;
Expand Down Expand Up @@ -73,7 +76,7 @@ limitations under the License.
}

.mx_InviteDialog_section {
padding-bottom: 10px;
padding-bottom: 4px;

h3 {
font-size: $font-12px;
Expand All @@ -82,6 +85,14 @@ limitations under the License.
text-transform: uppercase;
}

> p {
margin: 0;
}

> span {
color: $primary-fg-color;
}

.mx_InviteDialog_subname {
margin-bottom: 10px;
margin-top: -10px; // HACK: Positioning with margins is bad
Expand All @@ -90,6 +101,63 @@ limitations under the License.
}
}

.mx_InviteDialog_section_hidden_suggestions_disclaimer {
padding: 8px 0 16px 0;
font-size: $font-14px;

> span {
color: $primary-fg-color;
font-weight: 600;
}

> p {
margin: 0;
}
}

.mx_InviteDialog_footer {
border-top: 1px solid $input-border-color;

> h3 {
margin: 12px 0;
font-size: $font-12px;
color: $muted-fg-color;
font-weight: bold;
text-transform: uppercase;
}

.mx_InviteDialog_footer_link {
display: flex;
justify-content: space-between;
border-radius: 4px;
border: solid 1px $light-fg-color;
padding: 8px;

> a {
text-decoration: none;
flex-shrink: 1;
overflow: hidden;
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 {
cursor: pointer;
padding: 5px 10px;
Expand Down Expand Up @@ -142,6 +210,7 @@ limitations under the License.

.mx_InviteDialog_roomTile_nameStack {
display: inline-block;
overflow: hidden;
}

.mx_InviteDialog_roomTile_name {
Expand All @@ -157,6 +226,13 @@ limitations under the License.
margin-left: 7px;
}

.mx_InviteDialog_roomTile_name,
.mx_InviteDialog_roomTile_userId {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}

.mx_InviteDialog_roomTile_time {
text-align: right;
font-size: $font-12px;
Expand Down Expand Up @@ -212,22 +288,29 @@ limitations under the License.

.mx_InviteDialog {
// Prevent the dialog from jumping around randomly when elements change.
height: 590px;
height: 600px;
padding-left: 20px; // the design wants some padding on the left
display: flex;
flex-direction: column;

.mx_InviteDialog_content {
overflow: hidden;
}
}

.mx_InviteDialog_userSections {
margin-top: 10px;
margin-top: 4px;
overflow-y: auto;
padding-right: 45px;
height: 455px; // mx_InviteDialog's height minus some for the upper elements
padding: 0 45px 4px 0;
height: calc(100% - 115px); // mx_InviteDialog's height minus some for the upper and lower elements
}

// Right margin for the design. We could apply this to the whole dialog, but then the scrollbar
// for the user section gets weird.
.mx_InviteDialog_helpText,
.mx_InviteDialog_addressBar {
margin-right: 45px;
.mx_InviteDialog_hasFooter .mx_InviteDialog_userSections {
height: calc(100% - 175px);
}

.mx_InviteDialog_helpText {
margin: 0;
}

.mx_InviteDialog_helpText .mx_AccessibleButton_kind_link {
Expand Down
65 changes: 59 additions & 6 deletions src/components/views/dialogs/InviteDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import React, {createRef} from 'react';
import React, { createRef } from 'react';
import classNames from 'classnames';

import {_t, _td} from "../../../languageHandler";
import * as sdk from "../../../index";
import {MatrixClientPeg} from "../../../MatrixClientPeg";
Expand Down Expand Up @@ -50,6 +52,11 @@ import BaseAvatar from '../avatars/BaseAvatar';
import AccessibleButton from '../elements/AccessibleButton';
import { compare } from '../../../utils/strings';
import { IInvite3PID } from "matrix-js-sdk/src/@types/requests";
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
import { copyPlaintext, selectText } from "../../../utils/strings";
import * as ContextMenu from "../../structures/ContextMenu";
import { toRightOf } from "../../structures/ContextMenu";
import GenericTextContextMenu from "../context_menus/GenericTextContextMenu";

// we have a number of types defined from the Matrix spec which can't reasonably be altered here.
/* eslint-disable camelcase */
Expand Down Expand Up @@ -351,6 +358,7 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
initialText: "",
};

private closeCopiedTooltip: () => void;
private debounceTimer: NodeJS.Timeout = null; // actually number because we're in the browser
private editorRef = createRef<HTMLInputElement>();
private unmounted = false;
Expand Down Expand Up @@ -403,6 +411,9 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps

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

private onConsultFirstChange = (ev) => {
Expand Down Expand Up @@ -1238,6 +1249,25 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
}
}

private async onLinkClick(e) {
e.preventDefault();
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() {
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
const AccessibleButton = sdk.getComponent("elements.AccessibleButton");
Expand All @@ -1248,12 +1278,12 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
spinner = <Spinner w={20} h={20} />;
}


let title;
let helpText;
let buttonText;
let goButtonFn;
let consultSection;
let extraSection;
let footer;
let keySharingWarning = <span />;

const identityServersEnabled = SettingsStore.getValue(UIFeature.IdentityServer);
Expand Down Expand Up @@ -1316,6 +1346,26 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
}
buttonText = _t("Go");
goButtonFn = this.startDm;
extraSection = <div className="mx_InviteDialog_section_hidden_suggestions_disclaimer">
<span>{ _t("Some suggestions may be hidden for privacy.") }</span>
<p>{ _t("If you can't see who you’re looking for, send them your invite link below.") }</p>
</div>;
const link = makeUserPermalink(MatrixClientPeg.get().getUserId());
footer = <div className="mx_InviteDialog_footer">
<h3>{ _t("Or send invite link") }</h3>
<div className="mx_InviteDialog_footer_link">
<a href={link} onClick={this.onLinkClick}>
{ link }
</a>
<AccessibleTooltipButton
title={_t("Copy")}
onClick={this.onCopyClick}
className="mx_InviteDialog_footer_link_copy"
>
<div />
</AccessibleTooltipButton>
</div>
</div>
} else if (this.props.kind === KIND_INVITE) {
const room = MatrixClientPeg.get()?.getRoom(this.props.roomId);
const isSpace = SettingsStore.getValue("feature_spaces") && room?.isSpaceRoom();
Expand Down Expand Up @@ -1377,7 +1427,7 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
title = _t("Transfer");
buttonText = _t("Transfer");
goButtonFn = this.transferCall;
consultSection = <div>
footer = <div>
<label>
<input type="checkbox" checked={this.state.consultFirst} onChange={this.onConsultFirstChange} />
{_t("Consult first")}
Expand All @@ -1391,7 +1441,9 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
|| (this.state.filterText && this.state.filterText.includes('@'));
return (
<BaseDialog
className='mx_InviteDialog'
className={classNames("mx_InviteDialog", {
mx_InviteDialog_hasFooter: !!footer,
})}
hasCancel={true}
onFinished={this.props.onFinished}
title={title}
Expand All @@ -1418,8 +1470,9 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
<div className='mx_InviteDialog_userSections'>
{this.renderSection('recents')}
{this.renderSection('suggestions')}
{extraSection}
</div>
{consultSection}
{footer}
</div>
</BaseDialog>
);
Expand Down
3 changes: 3 additions & 0 deletions src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -2257,6 +2257,9 @@
"Start a conversation with someone using their name or username (like <userId/>).": "Start a conversation with someone using their name or username (like <userId/>).",
"This won't invite them to %(communityName)s. To invite someone to %(communityName)s, click <a>here</a>": "This won't invite them to %(communityName)s. To invite someone to %(communityName)s, click <a>here</a>",
"Go": "Go",
"Some suggestions may be hidden for privacy.": "Some suggestions may be hidden for privacy.",
"If you can't see who you’re looking for, send them your invite link below.": "If you can't see who you’re looking for, send them your invite link below.",
"Or send invite link": "Or send invite link",
"Unnamed Space": "Unnamed Space",
"Invite to %(roomName)s": "Invite to %(roomName)s",
"Invite someone using their name, email address, username (like <userId/>) or <a>share this space</a>.": "Invite someone using their name, email address, username (like <userId/>) or <a>share this space</a>.",
Expand Down