Merge branch 'develop' into gsouquet/dialogs-ts-migration
This commit is contained in:
commit
d3101b5ce4
13 changed files with 222 additions and 96 deletions
|
@ -328,7 +328,8 @@ $SpaceRoomViewInnerWidth: 428px;
|
||||||
font-size: $font-15px;
|
font-size: $font-15px;
|
||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
white-space: pre;
|
white-space: pre-wrap;
|
||||||
|
word-wrap: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
> hr {
|
> hr {
|
||||||
|
|
|
@ -17,6 +17,9 @@ limitations under the License.
|
||||||
.mx_InviteDialog_addressBar {
|
.mx_InviteDialog_addressBar {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
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 {
|
.mx_InviteDialog_editor {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
@ -73,7 +76,7 @@ limitations under the License.
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_InviteDialog_section {
|
.mx_InviteDialog_section {
|
||||||
padding-bottom: 10px;
|
padding-bottom: 4px;
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
font-size: $font-12px;
|
font-size: $font-12px;
|
||||||
|
@ -82,6 +85,14 @@ limitations under the License.
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
> p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
> span {
|
||||||
|
color: $primary-fg-color;
|
||||||
|
}
|
||||||
|
|
||||||
.mx_InviteDialog_subname {
|
.mx_InviteDialog_subname {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
margin-top: -10px; // HACK: Positioning with margins is bad
|
margin-top: -10px; // HACK: Positioning with margins is bad
|
||||||
|
@ -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 {
|
.mx_InviteDialog_roomTile {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
|
@ -142,6 +210,7 @@ limitations under the License.
|
||||||
|
|
||||||
.mx_InviteDialog_roomTile_nameStack {
|
.mx_InviteDialog_roomTile_nameStack {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_InviteDialog_roomTile_name {
|
.mx_InviteDialog_roomTile_name {
|
||||||
|
@ -157,6 +226,13 @@ limitations under the License.
|
||||||
margin-left: 7px;
|
margin-left: 7px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx_InviteDialog_roomTile_name,
|
||||||
|
.mx_InviteDialog_roomTile_userId {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
.mx_InviteDialog_roomTile_time {
|
.mx_InviteDialog_roomTile_time {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
font-size: $font-12px;
|
font-size: $font-12px;
|
||||||
|
@ -212,22 +288,29 @@ limitations under the License.
|
||||||
|
|
||||||
.mx_InviteDialog {
|
.mx_InviteDialog {
|
||||||
// Prevent the dialog from jumping around randomly when elements change.
|
// 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
|
padding-left: 20px; // the design wants some padding on the left
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.mx_InviteDialog_content {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_InviteDialog_userSections {
|
.mx_InviteDialog_userSections {
|
||||||
margin-top: 10px;
|
margin-top: 4px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding-right: 45px;
|
padding: 0 45px 4px 0;
|
||||||
height: 455px; // mx_InviteDialog's height minus some for the upper elements
|
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
|
.mx_InviteDialog_hasFooter .mx_InviteDialog_userSections {
|
||||||
// for the user section gets weird.
|
height: calc(100% - 175px);
|
||||||
.mx_InviteDialog_helpText,
|
}
|
||||||
.mx_InviteDialog_addressBar {
|
|
||||||
margin-right: 45px;
|
.mx_InviteDialog_helpText {
|
||||||
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_InviteDialog_helpText .mx_AccessibleButton_kind_link {
|
.mx_InviteDialog_helpText .mx_AccessibleButton_kind_link {
|
||||||
|
|
|
@ -14,7 +14,13 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.mx_SenderProfile_name {
|
.mx_SenderProfile_displayName {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx_SenderProfile_mxid {
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
margin-left: 5px;
|
||||||
|
opacity: 0.5; // Match mx_TextualEvent
|
||||||
|
}
|
||||||
|
|
|
@ -520,6 +520,7 @@ export const SpaceHierarchy: React.FC<IHierarchyProps> = ({
|
||||||
setError("Failed to update some suggestions. Try again later");
|
setError("Failed to update some suggestions. Try again later");
|
||||||
}
|
}
|
||||||
setSaving(false);
|
setSaving(false);
|
||||||
|
setSelected(new Map());
|
||||||
}}
|
}}
|
||||||
kind="primary_outline"
|
kind="primary_outline"
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
|
|
@ -28,7 +28,7 @@ import RoomTopic from "../views/elements/RoomTopic";
|
||||||
import InlineSpinner from "../views/elements/InlineSpinner";
|
import InlineSpinner from "../views/elements/InlineSpinner";
|
||||||
import {inviteMultipleToRoom, showRoomInviteDialog} from "../../RoomInvite";
|
import {inviteMultipleToRoom, showRoomInviteDialog} from "../../RoomInvite";
|
||||||
import {useRoomMembers} from "../../hooks/useRoomMembers";
|
import {useRoomMembers} from "../../hooks/useRoomMembers";
|
||||||
import createRoom, {IOpts, Preset} from "../../createRoom";
|
import createRoom, {IOpts} from "../../createRoom";
|
||||||
import Field from "../views/elements/Field";
|
import Field from "../views/elements/Field";
|
||||||
import {useEventEmitter} from "../../hooks/useEventEmitter";
|
import {useEventEmitter} from "../../hooks/useEventEmitter";
|
||||||
import withValidation from "../views/elements/Validation";
|
import withValidation from "../views/elements/Validation";
|
||||||
|
@ -65,6 +65,7 @@ import dis from "../../dispatcher/dispatcher";
|
||||||
import Modal from "../../Modal";
|
import Modal from "../../Modal";
|
||||||
import BetaFeedbackDialog from "../views/dialogs/BetaFeedbackDialog";
|
import BetaFeedbackDialog from "../views/dialogs/BetaFeedbackDialog";
|
||||||
import SdkConfig from "../../SdkConfig";
|
import SdkConfig from "../../SdkConfig";
|
||||||
|
import { Preset } from "matrix-js-sdk/src/@types/partials";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
space: Room;
|
space: Room;
|
||||||
|
|
|
@ -15,22 +15,23 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, {ChangeEvent, createRef, KeyboardEvent, SyntheticEvent} from "react";
|
import React, { ChangeEvent, createRef, KeyboardEvent, SyntheticEvent } from "react";
|
||||||
import {Room} from "matrix-js-sdk/src/models/room";
|
import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
|
|
||||||
import SdkConfig from '../../../SdkConfig';
|
import SdkConfig from '../../../SdkConfig';
|
||||||
import withValidation, {IFieldState} from '../elements/Validation';
|
import withValidation, { IFieldState } from '../elements/Validation';
|
||||||
import {_t} from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
import { MatrixClientPeg } from '../../../MatrixClientPeg';
|
||||||
import {Key} from "../../../Keyboard";
|
import { Key } from "../../../Keyboard";
|
||||||
import {IOpts, Preset, privateShouldBeEncrypted, Visibility} from "../../../createRoom";
|
import { IOpts, privateShouldBeEncrypted } from "../../../createRoom";
|
||||||
import {CommunityPrototypeStore} from "../../../stores/CommunityPrototypeStore";
|
import { CommunityPrototypeStore } from "../../../stores/CommunityPrototypeStore";
|
||||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||||
import Field from "../elements/Field";
|
import Field from "../elements/Field";
|
||||||
import RoomAliasField from "../elements/RoomAliasField";
|
import RoomAliasField from "../elements/RoomAliasField";
|
||||||
import LabelledToggleSwitch from "../elements/LabelledToggleSwitch";
|
import LabelledToggleSwitch from "../elements/LabelledToggleSwitch";
|
||||||
import DialogButtons from "../elements/DialogButtons";
|
import DialogButtons from "../elements/DialogButtons";
|
||||||
import BaseDialog from "../dialogs/BaseDialog";
|
import BaseDialog from "../dialogs/BaseDialog";
|
||||||
|
import { Preset, Visibility } from "matrix-js-sdk/src/@types/partials";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
defaultPublic?: boolean;
|
defaultPublic?: boolean;
|
||||||
|
|
|
@ -14,7 +14,9 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, {createRef} from 'react';
|
import React, { createRef } from 'react';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import {_t, _td} from "../../../languageHandler";
|
import {_t, _td} from "../../../languageHandler";
|
||||||
import * as sdk from "../../../index";
|
import * as sdk from "../../../index";
|
||||||
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
||||||
|
@ -31,7 +33,6 @@ import Modal from "../../../Modal";
|
||||||
import {humanizeTime} from "../../../utils/humanize";
|
import {humanizeTime} from "../../../utils/humanize";
|
||||||
import createRoom, {
|
import createRoom, {
|
||||||
canEncryptToAllUsers, ensureDMExists, findDMForUser, privateShouldBeEncrypted,
|
canEncryptToAllUsers, ensureDMExists, findDMForUser, privateShouldBeEncrypted,
|
||||||
IInvite3PID,
|
|
||||||
} from "../../../createRoom";
|
} from "../../../createRoom";
|
||||||
import {inviteMultipleToRoom, showCommunityInviteDialog} from "../../../RoomInvite";
|
import {inviteMultipleToRoom, showCommunityInviteDialog} from "../../../RoomInvite";
|
||||||
import {Key} from "../../../Keyboard";
|
import {Key} from "../../../Keyboard";
|
||||||
|
@ -50,6 +51,12 @@ import {getAddressType} from "../../../UserAddress";
|
||||||
import BaseAvatar from '../avatars/BaseAvatar';
|
import BaseAvatar from '../avatars/BaseAvatar';
|
||||||
import AccessibleButton from '../elements/AccessibleButton';
|
import AccessibleButton from '../elements/AccessibleButton';
|
||||||
import { compare } from '../../../utils/strings';
|
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.
|
// we have a number of types defined from the Matrix spec which can't reasonably be altered here.
|
||||||
/* eslint-disable camelcase */
|
/* eslint-disable camelcase */
|
||||||
|
@ -351,6 +358,7 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
|
||||||
initialText: "",
|
initialText: "",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private closeCopiedTooltip: () => void;
|
||||||
private debounceTimer: NodeJS.Timeout = null; // actually number because we're in the browser
|
private debounceTimer: NodeJS.Timeout = null; // actually number because we're in the browser
|
||||||
private editorRef = createRef<HTMLInputElement>();
|
private editorRef = createRef<HTMLInputElement>();
|
||||||
private unmounted = false;
|
private unmounted = false;
|
||||||
|
@ -403,6 +411,9 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
this.unmounted = true;
|
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) => {
|
private onConsultFirstChange = (ev) => {
|
||||||
|
@ -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() {
|
render() {
|
||||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||||
const AccessibleButton = sdk.getComponent("elements.AccessibleButton");
|
const AccessibleButton = sdk.getComponent("elements.AccessibleButton");
|
||||||
|
@ -1248,12 +1278,12 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
|
||||||
spinner = <Spinner w={20} h={20} />;
|
spinner = <Spinner w={20} h={20} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let title;
|
let title;
|
||||||
let helpText;
|
let helpText;
|
||||||
let buttonText;
|
let buttonText;
|
||||||
let goButtonFn;
|
let goButtonFn;
|
||||||
let consultSection;
|
let extraSection;
|
||||||
|
let footer;
|
||||||
let keySharingWarning = <span />;
|
let keySharingWarning = <span />;
|
||||||
|
|
||||||
const identityServersEnabled = SettingsStore.getValue(UIFeature.IdentityServer);
|
const identityServersEnabled = SettingsStore.getValue(UIFeature.IdentityServer);
|
||||||
|
@ -1316,6 +1346,26 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
|
||||||
}
|
}
|
||||||
buttonText = _t("Go");
|
buttonText = _t("Go");
|
||||||
goButtonFn = this.startDm;
|
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) {
|
} else if (this.props.kind === KIND_INVITE) {
|
||||||
const room = MatrixClientPeg.get()?.getRoom(this.props.roomId);
|
const room = MatrixClientPeg.get()?.getRoom(this.props.roomId);
|
||||||
const isSpace = SettingsStore.getValue("feature_spaces") && room?.isSpaceRoom();
|
const isSpace = SettingsStore.getValue("feature_spaces") && room?.isSpaceRoom();
|
||||||
|
@ -1377,7 +1427,7 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
|
||||||
title = _t("Transfer");
|
title = _t("Transfer");
|
||||||
buttonText = _t("Transfer");
|
buttonText = _t("Transfer");
|
||||||
goButtonFn = this.transferCall;
|
goButtonFn = this.transferCall;
|
||||||
consultSection = <div>
|
footer = <div>
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" checked={this.state.consultFirst} onChange={this.onConsultFirstChange} />
|
<input type="checkbox" checked={this.state.consultFirst} onChange={this.onConsultFirstChange} />
|
||||||
{_t("Consult first")}
|
{_t("Consult first")}
|
||||||
|
@ -1391,7 +1441,9 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
|
||||||
|| (this.state.filterText && this.state.filterText.includes('@'));
|
|| (this.state.filterText && this.state.filterText.includes('@'));
|
||||||
return (
|
return (
|
||||||
<BaseDialog
|
<BaseDialog
|
||||||
className='mx_InviteDialog'
|
className={classNames("mx_InviteDialog", {
|
||||||
|
mx_InviteDialog_hasFooter: !!footer,
|
||||||
|
})}
|
||||||
hasCancel={true}
|
hasCancel={true}
|
||||||
onFinished={this.props.onFinished}
|
onFinished={this.props.onFinished}
|
||||||
title={title}
|
title={title}
|
||||||
|
@ -1418,8 +1470,9 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
|
||||||
<div className='mx_InviteDialog_userSections'>
|
<div className='mx_InviteDialog_userSections'>
|
||||||
{this.renderSection('recents')}
|
{this.renderSection('recents')}
|
||||||
{this.renderSection('suggestions')}
|
{this.renderSection('suggestions')}
|
||||||
|
{extraSection}
|
||||||
</div>
|
</div>
|
||||||
{consultSection}
|
{footer}
|
||||||
</div>
|
</div>
|
||||||
</BaseDialog>
|
</BaseDialog>
|
||||||
);
|
);
|
||||||
|
|
|
@ -15,24 +15,31 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import Flair from '../elements/Flair.js';
|
import Flair from '../elements/Flair.js';
|
||||||
import FlairStore from '../../../stores/FlairStore';
|
import FlairStore from '../../../stores/FlairStore';
|
||||||
import {getUserNameColorClass} from '../../../utils/FormattingUtils';
|
import {getUserNameColorClass} from '../../../utils/FormattingUtils';
|
||||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||||
|
import MatrixEvent from "matrix-js-sdk/src/models/event";
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
mxEvent: MatrixEvent;
|
||||||
|
onClick(): void;
|
||||||
|
enableFlair: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IState {
|
||||||
|
userGroups;
|
||||||
|
relatedGroups;
|
||||||
|
}
|
||||||
|
|
||||||
@replaceableComponent("views.messages.SenderProfile")
|
@replaceableComponent("views.messages.SenderProfile")
|
||||||
export default class SenderProfile extends React.Component {
|
export default class SenderProfile extends React.Component<IProps, IState> {
|
||||||
static propTypes = {
|
|
||||||
mxEvent: PropTypes.object.isRequired, // event whose sender we're showing
|
|
||||||
onClick: PropTypes.func,
|
|
||||||
};
|
|
||||||
|
|
||||||
static contextType = MatrixClientContext;
|
static contextType = MatrixClientContext;
|
||||||
|
private unmounted: boolean;
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props: IProps) {
|
||||||
super(props);
|
super(props)
|
||||||
const senderId = this.props.mxEvent.getSender();
|
const senderId = this.props.mxEvent.getSender();
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
|
@ -40,6 +47,7 @@ export default class SenderProfile extends React.Component {
|
||||||
relatedGroups: [],
|
relatedGroups: [],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.unmounted = false;
|
this.unmounted = false;
|
||||||
this._updateRelatedGroups();
|
this._updateRelatedGroups();
|
||||||
|
@ -100,14 +108,26 @@ export default class SenderProfile extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
const {mxEvent} = this.props;
|
const {mxEvent} = this.props;
|
||||||
const colorClass = getUserNameColorClass(mxEvent.getSender());
|
const colorClass = getUserNameColorClass(mxEvent.getSender());
|
||||||
const name = mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender();
|
|
||||||
const {msgtype} = mxEvent.getContent();
|
const {msgtype} = mxEvent.getContent();
|
||||||
|
|
||||||
|
const disambiguate = mxEvent.sender?.disambiguate;
|
||||||
|
const displayName = mxEvent.sender?.rawDisplayName || mxEvent.getSender() || "";
|
||||||
|
const mxid = mxEvent.sender?.userId || mxEvent.getSender() || "";
|
||||||
|
|
||||||
if (msgtype === 'm.emote') {
|
if (msgtype === 'm.emote') {
|
||||||
return null; // emote message must include the name so don't duplicate it
|
return null; // emote message must include the name so don't duplicate it
|
||||||
}
|
}
|
||||||
|
|
||||||
let flair = null;
|
let mxidElement;
|
||||||
|
if (disambiguate) {
|
||||||
|
mxidElement = (
|
||||||
|
<span className="mx_SenderProfile_mxid">
|
||||||
|
{ mxid }
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let flair;
|
||||||
if (this.props.enableFlair) {
|
if (this.props.enableFlair) {
|
||||||
const displayedGroups = this._getDisplayedGroups(
|
const displayedGroups = this._getDisplayedGroups(
|
||||||
this.state.userGroups, this.state.relatedGroups,
|
this.state.userGroups, this.state.relatedGroups,
|
||||||
|
@ -119,13 +139,12 @@ export default class SenderProfile extends React.Component {
|
||||||
/>;
|
/>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const nameElem = name || '';
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx_SenderProfile mx_SenderProfile_hover" dir="auto" onClick={this.props.onClick}>
|
<div className="mx_SenderProfile mx_SenderProfile_hover" dir="auto" onClick={this.props.onClick}>
|
||||||
<span className={`mx_SenderProfile_name ${colorClass}`}>
|
<span className={`mx_SenderProfile_displayName ${colorClass}`}>
|
||||||
{ nameElem }
|
{ displayName }
|
||||||
</span>
|
</span>
|
||||||
|
{ mxidElement }
|
||||||
{ flair }
|
{ flair }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
|
@ -22,7 +22,7 @@ import FocusLock from "react-focus-lock";
|
||||||
import {_t} from "../../../languageHandler";
|
import {_t} from "../../../languageHandler";
|
||||||
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
|
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
|
||||||
import {ChevronFace, ContextMenu} from "../../structures/ContextMenu";
|
import {ChevronFace, ContextMenu} from "../../structures/ContextMenu";
|
||||||
import createRoom, {IStateEvent, Preset} from "../../../createRoom";
|
import createRoom from "../../../createRoom";
|
||||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||||
import {SpaceAvatar} from "./SpaceBasicSettings";
|
import {SpaceAvatar} from "./SpaceBasicSettings";
|
||||||
import AccessibleButton from "../elements/AccessibleButton";
|
import AccessibleButton from "../elements/AccessibleButton";
|
||||||
|
@ -33,6 +33,8 @@ import { USER_TAB } from "../dialogs/UserSettingsDialog";
|
||||||
import Field from "../elements/Field";
|
import Field from "../elements/Field";
|
||||||
import withValidation from "../elements/Validation";
|
import withValidation from "../elements/Validation";
|
||||||
import {SpaceFeedbackPrompt} from "../../structures/SpaceRoomView";
|
import {SpaceFeedbackPrompt} from "../../structures/SpaceRoomView";
|
||||||
|
import { Preset } from "matrix-js-sdk/src/@types/partials";
|
||||||
|
import { ICreateRoomStateEvent } from "matrix-js-sdk/src/@types/requests";
|
||||||
|
|
||||||
const SpaceCreateMenuType = ({ title, description, className, onClick }) => {
|
const SpaceCreateMenuType = ({ title, description, className, onClick }) => {
|
||||||
return (
|
return (
|
||||||
|
@ -81,7 +83,7 @@ const SpaceCreateMenu = ({ onFinished }) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialState: IStateEvent[] = [
|
const initialState: ICreateRoomStateEvent[] = [
|
||||||
{
|
{
|
||||||
type: EventType.RoomHistoryVisibility,
|
type: EventType.RoomHistoryVisibility,
|
||||||
content: {
|
content: {
|
||||||
|
|
|
@ -35,53 +35,15 @@ import { VIRTUAL_ROOM_EVENT_TYPE } from "./CallHandler";
|
||||||
import SpaceStore from "./stores/SpaceStore";
|
import SpaceStore from "./stores/SpaceStore";
|
||||||
import { makeSpaceParentEvent } from "./utils/space";
|
import { makeSpaceParentEvent } from "./utils/space";
|
||||||
import { Action } from "./dispatcher/actions"
|
import { Action } from "./dispatcher/actions"
|
||||||
|
import { ICreateRoomOpts } from "matrix-js-sdk/src/@types/requests";
|
||||||
|
import { Preset, Visibility } from "matrix-js-sdk/src/@types/partials";
|
||||||
|
|
||||||
// we define a number of interfaces which take their names from the js-sdk
|
// we define a number of interfaces which take their names from the js-sdk
|
||||||
/* eslint-disable camelcase */
|
/* eslint-disable camelcase */
|
||||||
|
|
||||||
// TODO move these interfaces over to js-sdk once it has been typescripted enough to accept them
|
|
||||||
export enum Visibility {
|
|
||||||
Public = "public",
|
|
||||||
Private = "private",
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum Preset {
|
|
||||||
PrivateChat = "private_chat",
|
|
||||||
TrustedPrivateChat = "trusted_private_chat",
|
|
||||||
PublicChat = "public_chat",
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Invite3PID {
|
|
||||||
id_server: string;
|
|
||||||
id_access_token?: string; // this gets injected by the js-sdk
|
|
||||||
medium: string;
|
|
||||||
address: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IStateEvent {
|
|
||||||
type: string;
|
|
||||||
state_key?: string; // defaults to an empty string
|
|
||||||
content: object;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ICreateOpts {
|
|
||||||
visibility?: Visibility;
|
|
||||||
room_alias_name?: string;
|
|
||||||
name?: string;
|
|
||||||
topic?: string;
|
|
||||||
invite?: string[];
|
|
||||||
invite_3pid?: Invite3PID[];
|
|
||||||
room_version?: string;
|
|
||||||
creation_content?: object;
|
|
||||||
initial_state?: IStateEvent[];
|
|
||||||
preset?: Preset;
|
|
||||||
is_direct?: boolean;
|
|
||||||
power_level_content_override?: object;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IOpts {
|
export interface IOpts {
|
||||||
dmUserId?: string;
|
dmUserId?: string;
|
||||||
createOpts?: ICreateOpts;
|
createOpts?: ICreateRoomOpts;
|
||||||
spinner?: boolean;
|
spinner?: boolean;
|
||||||
guestAccess?: boolean;
|
guestAccess?: boolean;
|
||||||
encryption?: boolean;
|
encryption?: boolean;
|
||||||
|
@ -91,12 +53,6 @@ export interface IOpts {
|
||||||
parentSpace?: Room;
|
parentSpace?: Room;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IInvite3PID {
|
|
||||||
id_server: string,
|
|
||||||
medium: 'email',
|
|
||||||
address: string,
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new room, and switch to it.
|
* Create a new room, and switch to it.
|
||||||
*
|
*
|
||||||
|
@ -136,7 +92,7 @@ export default function createRoom(opts: IOpts): Promise<string | null> {
|
||||||
const defaultPreset = opts.dmUserId ? Preset.TrustedPrivateChat : Preset.PrivateChat;
|
const defaultPreset = opts.dmUserId ? Preset.TrustedPrivateChat : Preset.PrivateChat;
|
||||||
|
|
||||||
// set some defaults for the creation
|
// set some defaults for the creation
|
||||||
const createOpts = opts.createOpts || {};
|
const createOpts: ICreateRoomOpts = opts.createOpts || {};
|
||||||
createOpts.preset = createOpts.preset || defaultPreset;
|
createOpts.preset = createOpts.preset || defaultPreset;
|
||||||
createOpts.visibility = createOpts.visibility || Visibility.Private;
|
createOpts.visibility = createOpts.visibility || Visibility.Private;
|
||||||
if (opts.dmUserId && createOpts.invite === undefined) {
|
if (opts.dmUserId && createOpts.invite === undefined) {
|
||||||
|
|
|
@ -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/>).",
|
"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>",
|
"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",
|
"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",
|
"Unnamed Space": "Unnamed Space",
|
||||||
"Invite to %(roomName)s": "Invite to %(roomName)s",
|
"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>.",
|
"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>.",
|
||||||
|
|
|
@ -20,7 +20,7 @@ import SettingsStore from "../settings/SettingsStore";
|
||||||
import {_t} from "../languageHandler";
|
import {_t} from "../languageHandler";
|
||||||
import dis from "../dispatcher/dispatcher";
|
import dis from "../dispatcher/dispatcher";
|
||||||
import {SettingLevel} from "../settings/SettingLevel";
|
import {SettingLevel} from "../settings/SettingLevel";
|
||||||
import { Preset } from "../createRoom";
|
import { Preset } from "matrix-js-sdk/src/@types/partials";
|
||||||
|
|
||||||
// TODO: Move this and related files to the js-sdk or something once finalized.
|
// TODO: Move this and related files to the js-sdk or something once finalized.
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,7 @@ function getAllEventTiles(session) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getMessageFromEventTile(eventTile) {
|
async function getMessageFromEventTile(eventTile) {
|
||||||
const senderElement = await eventTile.$(".mx_SenderProfile_name");
|
const senderElement = await eventTile.$(".mx_SenderProfile_displayName");
|
||||||
const className = await (await eventTile.getProperty("className")).jsonValue();
|
const className = await (await eventTile.getProperty("className")).jsonValue();
|
||||||
const classNames = className.split(" ");
|
const classNames = className.split(" ");
|
||||||
const bodyElement = await eventTile.$(".mx_EventTile_body");
|
const bodyElement = await eventTile.$(".mx_EventTile_body");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue