Merge branch 'develop' into Discovery

This commit is contained in:
Travis Ralston 2021-03-22 23:04:41 -06:00
commit edcd7c4426
86 changed files with 1340 additions and 941 deletions

View file

@ -20,7 +20,7 @@ import PropTypes from 'prop-types';
import * as sdk from '../../../index';
import { _t } from '../../../languageHandler';
import Modal from '../../../Modal';
import {Group} from 'matrix-js-sdk';
import {Group} from 'matrix-js-sdk/src/models/group';
import GroupStore from "../../../stores/GroupStore";
import {MenuItem} from "../../structures/ContextMenu";
import {replaceableComponent} from "../../../utils/replaceableComponent";

View file

@ -19,7 +19,7 @@ limitations under the License.
import React from 'react';
import PropTypes from 'prop-types';
import {EventStatus} from 'matrix-js-sdk';
import {EventStatus} from 'matrix-js-sdk/src/models/event';
import {MatrixClientPeg} from '../../../MatrixClientPeg';
import dis from '../../../dispatcher/dispatcher';

View file

@ -69,6 +69,7 @@ const AddExistingToSpaceDialog: React.FC<IProps> = ({ matrixClient: cli, space,
const existingRoomsSet = new Set(existingRooms);
const rooms = cli.getVisibleRooms().filter(room => {
return !existingRoomsSet.has(room) // not already in space
&& !room.isSpaceRoom() // not a space itself
&& room.name.toLowerCase().includes(lcQuery) // contains query
&& !DMRoomMap.shared().getUserIdForRoomId(room.roomId); // not a DM
});

View file

@ -16,7 +16,7 @@ limitations under the License.
import React from 'react';
import PropTypes from 'prop-types';
import { MatrixClient } from 'matrix-js-sdk';
import { MatrixClient } from 'matrix-js-sdk/src/client';
import * as sdk from '../../../index';
import { _t } from '../../../languageHandler';
import { GroupMemberType } from '../../../groups';

View file

@ -19,7 +19,6 @@ import PropTypes from 'prop-types';
import * as sdk from '../../../index';
import SyntaxHighlight from '../elements/SyntaxHighlight';
import { _t } from '../../../languageHandler';
import { Room, MatrixEvent } from "matrix-js-sdk";
import Field from "../elements/Field";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
import {useEventEmitter} from "../../../hooks/useEventEmitter";
@ -39,6 +38,8 @@ import SettingsStore, {LEVEL_ORDER} from "../../../settings/SettingsStore";
import Modal from "../../../Modal";
import ErrorDialog from "./ErrorDialog";
import {replaceableComponent} from "../../../utils/replaceableComponent";
import {Room} from "matrix-js-sdk/src/models/room";
import {MatrixEvent} from "matrix-js-sdk/src/models/event";
class GenericEditor extends React.PureComponent {
// static propTypes = {onBack: PropTypes.func.isRequired};

View file

@ -100,6 +100,20 @@ export default (props) => {
);
}
let bugReports = null;
if (SdkConfig.get().bug_report_endpoint_url) {
bugReports = (
<p>{
_t("PRO TIP: If you start a bug, please submit <debugLogsLink>debug logs</debugLogsLink> " +
"to help us track down the problem.", {}, {
debugLogsLink: sub => (
<AccessibleButton kind="link" onClick={onDebugLogsLinkClick}>{sub}</AccessibleButton>
),
})
}</p>
);
}
return (<QuestionDialog
className="mx_FeedbackDialog"
hasCancelButton={!!hasFeedback}
@ -120,14 +134,7 @@ export default (props) => {
},
})
}</p>
<p>{
_t("PRO TIP: If you start a bug, please submit <debugLogsLink>debug logs</debugLogsLink> " +
"to help us track down the problem.", {}, {
debugLogsLink: sub => (
<AccessibleButton kind="link" onClick={onDebugLogsLinkClick}>{sub}</AccessibleButton>
),
})
}</p>
{bugReports}
</div>
{ countlyFeedbackSection }
</React.Fragment>}

View file

@ -1256,7 +1256,9 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
? _t("Invite to %(spaceName)s", {
spaceName: room.name || _t("Unnamed Space"),
})
: _t("Invite to this room");
: _t("Invite to %(roomName)s", {
roomName: room.name || _t("Unnamed Room"),
});
let helpTextUntranslated;
if (isSpace) {

View file

@ -18,7 +18,7 @@ import React, {PureComponent} from 'react';
import * as sdk from '../../../index';
import { _t } from '../../../languageHandler';
import PropTypes from "prop-types";
import {MatrixEvent} from "matrix-js-sdk";
import {MatrixEvent} from "matrix-js-sdk/src/models/event";
import {MatrixClientPeg} from "../../../MatrixClientPeg";
import SdkConfig from '../../../SdkConfig';
import Markdown from '../../../Markdown';

View file

@ -82,6 +82,33 @@ export default class RoomUpgradeWarningDialog extends React.Component {
const title = this.state.isPrivate ? _t("Upgrade private room") : _t("Upgrade public room");
let bugReports = (
<p>
{_t(
"This usually only affects how the room is processed on the server. If you're " +
"having problems with your %(brand)s, please report a bug.", {brand},
)}
</p>
);
if (SdkConfig.get().bug_report_endpoint_url) {
bugReports = (
<p>
{_t(
"This usually only affects how the room is processed on the server. If you're " +
"having problems with your %(brand)s, please <a>report a bug</a>.",
{
brand,
},
{
"a": (sub) => {
return <a href='#' onClick={this._openBugReportDialog}>{sub}</a>;
},
},
)}
</p>
);
}
return (
<BaseDialog
className='mx_RoomUpgradeWarningDialog'
@ -97,20 +124,7 @@ export default class RoomUpgradeWarningDialog extends React.Component {
"is unstable due to bugs, missing features or security vulnerabilities.",
)}
</p>
<p>
{_t(
"This usually only affects how the room is processed on the server. If you're " +
"having problems with your %(brand)s, please <a>report a bug</a>.",
{
brand,
},
{
"a": (sub) => {
return <a href='#' onClick={this._openBugReportDialog}>{sub}</a>;
},
},
)}
</p>
{bugReports}
<p>
{_t(
"You'll upgrade this room from <oldVersion /> to <newVersion />.",

View file

@ -17,7 +17,7 @@ limitations under the License.
import React from 'react';
import PropTypes from 'prop-types';
import {IntegrationManagers} from "../../../integrations/IntegrationManagers";
import {Room} from "matrix-js-sdk";
import {Room} from "matrix-js-sdk/src/models/room";
import * as sdk from '../../../index';
import {dialogTermsInteractionCallback, TermsNotSignedError} from "../../../Terms";
import classNames from 'classnames';

View file

@ -20,8 +20,8 @@ import PropTypes from 'prop-types';
import * as sdk from '../../../index';
import { _t, pickBestLanguage } from '../../../languageHandler';
import Matrix from 'matrix-js-sdk';
import {replaceableComponent} from "../../../utils/replaceableComponent";
import {SERVICE_TYPES} from "matrix-js-sdk/src/service-types";
class TermsCheckbox extends React.PureComponent {
static propTypes = {
@ -85,22 +85,22 @@ export default class TermsDialog extends React.PureComponent {
_nameForServiceType(serviceType, host) {
switch (serviceType) {
case Matrix.SERVICE_TYPES.IS:
case SERVICE_TYPES.IS:
return <div>{_t("Identity Server")}<br />({host})</div>;
case Matrix.SERVICE_TYPES.IM:
case SERVICE_TYPES.IM:
return <div>{_t("Integration Manager")}<br />({host})</div>;
}
}
_summaryForServiceType(serviceType) {
switch (serviceType) {
case Matrix.SERVICE_TYPES.IS:
case SERVICE_TYPES.IS:
return <div>
{_t("Find others by phone or email")}
<br />
{_t("Be found by phone or email")}
</div>;
case Matrix.SERVICE_TYPES.IM:
case SERVICE_TYPES.IM:
return <div>
{_t("Use bots, bridges, widgets and sticker packs")}
</div>;

View file

@ -19,7 +19,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import * as sdk from '../../../../index';
import {MatrixClientPeg} from '../../../../MatrixClientPeg';
import { MatrixClient } from 'matrix-js-sdk';
import { MatrixClient } from 'matrix-js-sdk/src/client';
import { _t } from '../../../../languageHandler';
import { accessSecretStorage } from '../../../../SecurityManager';

View file

@ -17,7 +17,8 @@ import React from 'react';
import * as sdk from '../../../index';
import dis from '../../../dispatcher/dispatcher';
import classNames from 'classnames';
import { Room, RoomMember } from 'matrix-js-sdk';
import { Room } from 'matrix-js-sdk/src/models/room';
import { RoomMember } from 'matrix-js-sdk/src/models/room-member';
import PropTypes from 'prop-types';
import {MatrixClientPeg} from '../../../MatrixClientPeg';
import FlairStore from "../../../stores/FlairStore";

View file

@ -21,7 +21,7 @@ import {_t} from '../../../languageHandler';
import PropTypes from 'prop-types';
import dis from '../../../dispatcher/dispatcher';
import {wantsDateSeparator} from '../../../DateUtils';
import {MatrixEvent} from 'matrix-js-sdk';
import {MatrixEvent} from 'matrix-js-sdk/src/models/event';
import {makeUserPermalink, RoomPermalinkCreator} from "../../../utils/permalinks/Permalinks";
import SettingsStore from "../../../settings/SettingsStore";
import {LayoutPropType} from "../../../settings/Layout";

View file

@ -46,12 +46,14 @@ export default class TextWithTooltip extends React.Component {
render() {
const Tooltip = sdk.getComponent("elements.Tooltip");
const {class: className, children, tooltip, tooltipClass, ...props} = this.props;
return (
<span onMouseOver={this.onMouseOver} onMouseLeave={this.onMouseLeave} className={this.props.class}>
{this.props.children}
<span {...props} onMouseOver={this.onMouseOver} onMouseLeave={this.onMouseLeave} className={className}>
{children}
{this.state.hover && <Tooltip
label={this.props.tooltip}
tooltipClassName={this.props.tooltipClass}
label={tooltip}
tooltipClassName={tooltipClass}
className={"mx_TextWithTooltip_tooltip"} /> }
</span>
);

View file

@ -19,7 +19,7 @@ import PropTypes from 'prop-types';
import * as HtmlUtils from '../../../HtmlUtils';
import { editBodyDiffToHtml } from '../../../utils/MessageDiffUtils';
import {formatTime} from '../../../DateUtils';
import {MatrixEvent} from 'matrix-js-sdk';
import {MatrixEvent} from 'matrix-js-sdk/src/models/event';
import {pillifyLinks, unmountPills} from '../../../utils/pillify';
import { _t } from '../../../languageHandler';
import * as sdk from '../../../index';

View file

@ -18,7 +18,7 @@ limitations under the License.
import React, {useEffect} from 'react';
import PropTypes from 'prop-types';
import { EventStatus } from 'matrix-js-sdk';
import { EventStatus } from 'matrix-js-sdk/src/models/event';
import { _t } from '../../../languageHandler';
import * as sdk from '../../../index';

View file

@ -16,7 +16,7 @@ limitations under the License.
import React from 'react';
import PropTypes from 'prop-types';
import {MatrixEvent} from 'matrix-js-sdk';
import {MatrixEvent} from 'matrix-js-sdk/src/models/event';
import * as sdk from '../../../index';
import { _t } from '../../../languageHandler';
import Modal from '../../../Modal';

View file

@ -27,7 +27,7 @@ import {parseEvent} from '../../../editor/deserialize';
import {PartCreator} from '../../../editor/parts';
import EditorStateTransfer from '../../../utils/EditorStateTransfer';
import classNames from 'classnames';
import {EventStatus} from 'matrix-js-sdk';
import {EventStatus} from 'matrix-js-sdk/src/models/event';
import BasicMessageComposer from "./BasicMessageComposer";
import {Key, isOnlyCtrlOrCmdKeyEvent} from "../../../Keyboard";
import MatrixClientContext from "../../../contexts/MatrixClientContext";

View file

@ -28,7 +28,7 @@ import * as sdk from "../../../index";
import dis from '../../../dispatcher/dispatcher';
import SettingsStore from "../../../settings/SettingsStore";
import {Layout, LayoutPropType} from "../../../settings/Layout";
import {EventStatus} from 'matrix-js-sdk';
import {EventStatus} from 'matrix-js-sdk/src/models/event';
import {formatTime} from "../../../DateUtils";
import {MatrixClientPeg} from '../../../MatrixClientPeg';
import {ALL_RULE_TYPES} from "../../../mjolnir/BanList";

View file

@ -85,8 +85,8 @@ class FormatButton extends React.PureComponent {
return (
<AccessibleTooltipButton
as="span"
role="button"
element="button"
type="button"
onClick={this.props.onClick}
title={this.props.label}
tooltip={tooltip}

View file

@ -333,6 +333,17 @@ export default class RoomTile extends React.PureComponent<IProps, IState> {
this.setState({generalMenuPosition: null}); // hide the menu
};
private onInviteClick = (ev: ButtonEvent) => {
ev.preventDefault();
ev.stopPropagation();
dis.dispatch({
action: 'view_invite',
roomId: this.props.room.roomId,
});
this.setState({generalMenuPosition: null}); // hide the menu
};
private async saveNotifState(ev: ButtonEvent, newState: Volume) {
ev.preventDefault();
ev.stopPropagation();
@ -453,6 +464,8 @@ export default class RoomTile extends React.PureComponent<IProps, IState> {
const isLowPriority = roomTags.includes(DefaultTagID.LowPriority);
const lowPriorityLabel = _t("Low Priority");
const userId = MatrixClientPeg.get().getUserId();
const canInvite = this.props.room.canInvite(userId);
contextMenu = <IconizedContextMenu
{...contextMenuBelow(this.state.generalMenuPosition)}
onFinished={this.onCloseGeneralMenu}
@ -472,7 +485,13 @@ export default class RoomTile extends React.PureComponent<IProps, IState> {
label={lowPriorityLabel}
iconClassName="mx_RoomTile_iconArrowDown"
/>
{canInvite ? (
<IconizedContextMenuOption
onClick={this.onInviteClick}
label={_t("Invite People")}
iconClassName="mx_RoomTile_iconInvite"
/>
) : null}
<IconizedContextMenuOption
onClick={this.onOpenRoomSettings}
label={_t("Settings")}

View file

@ -17,7 +17,7 @@ limitations under the License.
import React from 'react';
import PropTypes from 'prop-types';
import {MatrixClientPeg} from "../../../MatrixClientPeg";
import {MatrixEvent} from "matrix-js-sdk";
import {MatrixEvent} from "matrix-js-sdk/src/models/event";
import {_t} from "../../../languageHandler";
import dis from "../../../dispatcher/dispatcher";
import * as sdk from "../../../index";

View file

@ -32,7 +32,7 @@ import * as sdk from "../../../../..";
import Modal from "../../../../../Modal";
import dis from "../../../../../dispatcher/dispatcher";
import {Service, startTermsFlow} from "../../../../../Terms";
import {SERVICE_TYPES} from "matrix-js-sdk";
import {SERVICE_TYPES} from "matrix-js-sdk/src/service-types";
import IdentityAuthClient from "../../../../../IdentityAuthClient";
import {abbreviateUrl} from "../../../../../utils/UrlUtils";
import { getThreepidsWithBindStatus } from '../../../../../boundThreepids';

View file

@ -84,6 +84,7 @@ export default class VoiceUserSettingsTab extends React.Component {
}
}
if (error) {
console.log("Failed to list userMedia devices", error);
const brand = SdkConfig.get().brand;
const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog');
Modal.createTrackedDialog('No media permissions', '', ErrorDialog, {

View file

@ -108,7 +108,7 @@ const SpaceCreateMenu = ({ onFinished }) => {
body = <React.Fragment>
<h2>{ _t("Create a space") }</h2>
<p>{ _t("Spaces are new ways to group rooms and people. " +
"To join an existing space youll need an invite") }</p>
"To join an existing space you'll need an invite.") }</p>
<SpaceCreateMenuType
title={_t("Public")}
@ -140,9 +140,9 @@ const SpaceCreateMenu = ({ onFinished }) => {
</h2>
<p>
{
_t("Give it a photo, name and description to help you identify it.")
_t("Add some details to help people recognise it.")
} {
_t("You can change these at any point.")
_t("You can change these anytime.")
}
</p>

View file

@ -220,13 +220,19 @@ const SpacePanel = () => {
<SpaceButton
className={newClasses}
tooltip={menuDisplayed ? _t("Cancel") : _t("Create a space")}
onClick={menuDisplayed ? closeMenu : openMenu}
onClick={menuDisplayed ? closeMenu : () => {
openMenu();
if (!isPanelCollapsed) setPanelCollapsed(true);
}}
isNarrow={isPanelCollapsed}
/>
</AutoHideScrollbar>
<AccessibleTooltipButton
className={classNames("mx_SpacePanel_toggleCollapse", {expanded: !isPanelCollapsed})}
onClick={evt => setPanelCollapsed(!isPanelCollapsed)}
onClick={() => {
setPanelCollapsed(!isPanelCollapsed);
if (menuDisplayed) closeMenu();
}}
title={expandCollapseButtonTitle}
/>
{ contextMenu }

View file

@ -41,13 +41,13 @@ const SpacePublicShare = ({ space, onFinished }: IProps) => {
const success = await copyPlaintext(permalinkCreator.forRoom());
const text = success ? _t("Copied!") : _t("Failed to copy");
setCopiedText(text);
await sleep(10);
await sleep(5000);
if (copiedText === text) { // if the text hasn't changed by another click then clear it after some time
setCopiedText(_t("Click to copy"));
}
}}
>
{ _t("Share invite link") }
<h3>{ _t("Share invite link") }</h3>
<span>{ copiedText }</span>
</AccessibleButton>
<AccessibleButton
@ -57,7 +57,8 @@ const SpacePublicShare = ({ space, onFinished }: IProps) => {
onFinished();
}}
>
{ _t("Invite by email or username") }
<h3>{ _t("Invite people") }</h3>
<span>{ _t("Invite with email or username") }</span>
</AccessibleButton>
</div>;
};

View file

@ -51,6 +51,7 @@ interface IItemProps {
isNested?: boolean;
isPanelCollapsed?: boolean;
onExpand?: Function;
parents?: Set<string>;
}
interface IItemState {
@ -299,7 +300,8 @@ export class SpaceItem extends React.PureComponent<IItemProps, IItemState> {
const isNarrow = this.props.isPanelCollapsed;
const collapsed = this.state.collapsed || forceCollapsed;
const childSpaces = SpaceStore.instance.getChildSpaces(space.roomId);
const childSpaces = SpaceStore.instance.getChildSpaces(space.roomId)
.filter(s => !this.props.parents?.has(s.roomId));
const isActive = activeSpaces.includes(space);
const itemClasses = classNames({
"mx_SpaceItem": true,
@ -312,11 +314,17 @@ export class SpaceItem extends React.PureComponent<IItemProps, IItemState> {
mx_SpaceButton_narrow: isNarrow,
});
const notificationState = SpaceStore.instance.getNotificationState(space.roomId);
const childItems = childSpaces && !collapsed ? <SpaceTreeLevel
spaces={childSpaces}
activeSpaces={activeSpaces}
isNested={true}
/> : null;
let childItems;
if (childSpaces && !collapsed) {
childItems = <SpaceTreeLevel
spaces={childSpaces}
activeSpaces={activeSpaces}
isNested={true}
parents={new Set(this.props.parents).add(this.props.space.roomId)}
/>;
}
let notifBadge;
if (notificationState) {
notifBadge = <div className="mx_SpacePanel_badgeContainer">
@ -383,12 +391,14 @@ interface ITreeLevelProps {
spaces: Room[];
activeSpaces: Room[];
isNested?: boolean;
parents: Set<string>;
}
const SpaceTreeLevel: React.FC<ITreeLevelProps> = ({
spaces,
activeSpaces,
isNested,
parents,
}) => {
return <ul className="mx_SpaceTreeLevel">
{spaces.map(s => {
@ -397,6 +407,7 @@ const SpaceTreeLevel: React.FC<ITreeLevelProps> = ({
activeSpaces={activeSpaces}
space={s}
isNested={isNested}
parents={parents}
/>);
})}
</ul>;