Enable indent rule and fix indent
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
This commit is contained in:
parent
33617b0375
commit
46bfbbadf9
87 changed files with 693 additions and 537 deletions
|
@ -15,7 +15,6 @@ module.exports = {
|
||||||
"prefer-promise-reject-errors": "off",
|
"prefer-promise-reject-errors": "off",
|
||||||
"no-async-promise-executor": "off",
|
"no-async-promise-executor": "off",
|
||||||
"quotes": "off",
|
"quotes": "off",
|
||||||
"indent": "off",
|
|
||||||
},
|
},
|
||||||
|
|
||||||
overrides: [{
|
overrides: [{
|
||||||
|
|
|
@ -149,12 +149,12 @@ function _onGroupAddRoomFinished(groupId, addrs, addRoomsPublicly) {
|
||||||
Modal.createTrackedDialog(
|
Modal.createTrackedDialog(
|
||||||
'Failed to add the following room to the group',
|
'Failed to add the following room to the group',
|
||||||
'', ErrorDialog,
|
'', ErrorDialog,
|
||||||
{
|
{
|
||||||
title: _t(
|
title: _t(
|
||||||
"Failed to add the following rooms to %(groupId)s:",
|
"Failed to add the following rooms to %(groupId)s:",
|
||||||
{groupId},
|
{groupId},
|
||||||
),
|
),
|
||||||
description: errorList.join(", "),
|
description: errorList.join(", "),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,7 +163,7 @@ export default class IdentityAuthClient {
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
button: _t("Trust"),
|
button: _t("Trust"),
|
||||||
});
|
});
|
||||||
const [confirmed] = await finished;
|
const [confirmed] = await finished;
|
||||||
if (confirmed) {
|
if (confirmed) {
|
||||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||||
|
|
|
@ -54,7 +54,7 @@ export default class PasswordReset {
|
||||||
return res;
|
return res;
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
if (err.errcode === 'M_THREEPID_NOT_FOUND') {
|
if (err.errcode === 'M_THREEPID_NOT_FOUND') {
|
||||||
err.message = _t('This email address was not found');
|
err.message = _t('This email address was not found');
|
||||||
} else if (err.httpStatus) {
|
} else if (err.httpStatus) {
|
||||||
err.message = err.message + ` (Status ${err.httpStatus})`;
|
err.message = err.message + ` (Status ${err.httpStatus})`;
|
||||||
}
|
}
|
||||||
|
|
|
@ -549,15 +549,15 @@ function textForMjolnirEvent(event) {
|
||||||
if (USER_RULE_TYPES.includes(event.getType())) {
|
if (USER_RULE_TYPES.includes(event.getType())) {
|
||||||
return _t("%(senderName)s changed a rule that was banning users matching %(oldGlob)s to matching " +
|
return _t("%(senderName)s changed a rule that was banning users matching %(oldGlob)s to matching " +
|
||||||
"%(newGlob)s for %(reason)s",
|
"%(newGlob)s for %(reason)s",
|
||||||
{senderName, oldGlob: prevEntity, newGlob: entity, reason});
|
{senderName, oldGlob: prevEntity, newGlob: entity, reason});
|
||||||
} else if (ROOM_RULE_TYPES.includes(event.getType())) {
|
} else if (ROOM_RULE_TYPES.includes(event.getType())) {
|
||||||
return _t("%(senderName)s changed a rule that was banning rooms matching %(oldGlob)s to matching " +
|
return _t("%(senderName)s changed a rule that was banning rooms matching %(oldGlob)s to matching " +
|
||||||
"%(newGlob)s for %(reason)s",
|
"%(newGlob)s for %(reason)s",
|
||||||
{senderName, oldGlob: prevEntity, newGlob: entity, reason});
|
{senderName, oldGlob: prevEntity, newGlob: entity, reason});
|
||||||
} else if (SERVER_RULE_TYPES.includes(event.getType())) {
|
} else if (SERVER_RULE_TYPES.includes(event.getType())) {
|
||||||
return _t("%(senderName)s changed a rule that was banning servers matching %(oldGlob)s to matching " +
|
return _t("%(senderName)s changed a rule that was banning servers matching %(oldGlob)s to matching " +
|
||||||
"%(newGlob)s for %(reason)s",
|
"%(newGlob)s for %(reason)s",
|
||||||
{senderName, oldGlob: prevEntity, newGlob: entity, reason});
|
{senderName, oldGlob: prevEntity, newGlob: entity, reason});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unknown type. We'll say something but we shouldn't end up here.
|
// Unknown type. We'll say something but we shouldn't end up here.
|
||||||
|
|
|
@ -498,9 +498,9 @@ export default class CreateKeyBackupDialog extends React.PureComponent {
|
||||||
title={this._titleForPhase(this.state.phase)}
|
title={this._titleForPhase(this.state.phase)}
|
||||||
hasCancel={[PHASE_PASSPHRASE, PHASE_DONE].includes(this.state.phase)}
|
hasCancel={[PHASE_PASSPHRASE, PHASE_DONE].includes(this.state.phase)}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
{content}
|
{content}
|
||||||
</div>
|
</div>
|
||||||
</BaseDialog>
|
</BaseDialog>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -856,9 +856,9 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
|
||||||
hasCancel={this.props.hasCancel && [PHASE_PASSPHRASE].includes(this.state.phase)}
|
hasCancel={this.props.hasCancel && [PHASE_PASSPHRASE].includes(this.state.phase)}
|
||||||
fixedWidth={false}
|
fixedWidth={false}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
{content}
|
{content}
|
||||||
</div>
|
</div>
|
||||||
</BaseDialog>
|
</BaseDialog>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,8 +170,11 @@ export default class ExportE2eKeysDialog extends React.Component {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='mx_Dialog_buttons'>
|
<div className='mx_Dialog_buttons'>
|
||||||
<input className='mx_Dialog_primary' type='submit' value={_t('Export')}
|
<input
|
||||||
disabled={disableForm}
|
className='mx_Dialog_primary'
|
||||||
|
type='submit'
|
||||||
|
value={_t('Export')}
|
||||||
|
disabled={disableForm}
|
||||||
/>
|
/>
|
||||||
<button onClick={this._onCancelClick} disabled={disableForm}>
|
<button onClick={this._onCancelClick} disabled={disableForm}>
|
||||||
{ _t("Cancel") }
|
{ _t("Cancel") }
|
||||||
|
|
|
@ -140,36 +140,36 @@ export default class ImportE2eKeysDialog extends React.Component {
|
||||||
</div>
|
</div>
|
||||||
<div className='mx_E2eKeysDialog_inputTable'>
|
<div className='mx_E2eKeysDialog_inputTable'>
|
||||||
<div className='mx_E2eKeysDialog_inputRow'>
|
<div className='mx_E2eKeysDialog_inputRow'>
|
||||||
<div className='mx_E2eKeysDialog_inputLabel'>
|
<div className='mx_E2eKeysDialog_inputLabel'>
|
||||||
<label htmlFor='importFile'>
|
<label htmlFor='importFile'>
|
||||||
{ _t("File to import") }
|
{ _t("File to import") }
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div className='mx_E2eKeysDialog_inputCell'>
|
<div className='mx_E2eKeysDialog_inputCell'>
|
||||||
<input
|
<input
|
||||||
ref={this._file}
|
ref={this._file}
|
||||||
id='importFile'
|
id='importFile'
|
||||||
type='file'
|
type='file'
|
||||||
autoFocus={true}
|
autoFocus={true}
|
||||||
onChange={this._onFormChange}
|
onChange={this._onFormChange}
|
||||||
disabled={disableForm} />
|
disabled={disableForm} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='mx_E2eKeysDialog_inputRow'>
|
<div className='mx_E2eKeysDialog_inputRow'>
|
||||||
<div className='mx_E2eKeysDialog_inputLabel'>
|
<div className='mx_E2eKeysDialog_inputLabel'>
|
||||||
<label htmlFor='passphrase'>
|
<label htmlFor='passphrase'>
|
||||||
{ _t("Enter passphrase") }
|
{ _t("Enter passphrase") }
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div className='mx_E2eKeysDialog_inputCell'>
|
<div className='mx_E2eKeysDialog_inputCell'>
|
||||||
<input
|
<input
|
||||||
ref={this._passphrase}
|
ref={this._passphrase}
|
||||||
id='passphrase'
|
id='passphrase'
|
||||||
size='64'
|
size='64'
|
||||||
type='password'
|
type='password'
|
||||||
onChange={this._onFormChange}
|
onChange={this._onFormChange}
|
||||||
disabled={disableForm} />
|
disabled={disableForm} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -200,10 +200,10 @@ class FilePanel extends React.Component {
|
||||||
previousPhase={RightPanelPhases.RoomSummary}
|
previousPhase={RightPanelPhases.RoomSummary}
|
||||||
>
|
>
|
||||||
<div className="mx_RoomView_empty">
|
<div className="mx_RoomView_empty">
|
||||||
{ _t("You must <a>register</a> to use this functionality",
|
{ _t("You must <a>register</a> to use this functionality",
|
||||||
{},
|
{},
|
||||||
{ 'a': (sub) => <a href="#/register" key="sub">{ sub }</a> })
|
{ 'a': (sub) => <a href="#/register" key="sub">{ sub }</a> })
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</BaseCard>;
|
</BaseCard>;
|
||||||
} else if (this.noRoom) {
|
} else if (this.noRoom) {
|
||||||
|
|
|
@ -153,17 +153,17 @@ class GroupFilterPanel extends React.Component {
|
||||||
type="draggable-TagTile"
|
type="draggable-TagTile"
|
||||||
>
|
>
|
||||||
{ (provided, snapshot) => (
|
{ (provided, snapshot) => (
|
||||||
<div
|
<div
|
||||||
className="mx_GroupFilterPanel_tagTileContainer"
|
className="mx_GroupFilterPanel_tagTileContainer"
|
||||||
ref={provided.innerRef}
|
ref={provided.innerRef}
|
||||||
>
|
>
|
||||||
{ this.renderGlobalIcon() }
|
{ this.renderGlobalIcon() }
|
||||||
{ tags }
|
{ tags }
|
||||||
<div>
|
<div>
|
||||||
{createButton}
|
{createButton}
|
||||||
</div>
|
|
||||||
{ provided.placeholder }
|
|
||||||
</div>
|
</div>
|
||||||
|
{ provided.placeholder }
|
||||||
|
</div>
|
||||||
) }
|
) }
|
||||||
</Droppable>
|
</Droppable>
|
||||||
</AutoHideScrollbar>
|
</AutoHideScrollbar>
|
||||||
|
|
|
@ -43,7 +43,7 @@ import {mediaFromMxc} from "../../customisations/Media";
|
||||||
import {replaceableComponent} from "../../utils/replaceableComponent";
|
import {replaceableComponent} from "../../utils/replaceableComponent";
|
||||||
|
|
||||||
const LONG_DESC_PLACEHOLDER = _td(
|
const LONG_DESC_PLACEHOLDER = _td(
|
||||||
`<h1>HTML for your community's page</h1>
|
`<h1>HTML for your community's page</h1>
|
||||||
<p>
|
<p>
|
||||||
Use the long description to introduce new members to the community, or distribute
|
Use the long description to introduce new members to the community, or distribute
|
||||||
some important <a href="foo">links</a>
|
some important <a href="foo">links</a>
|
||||||
|
@ -111,13 +111,14 @@ class CategoryRoomList extends React.Component {
|
||||||
Modal.createTrackedDialog(
|
Modal.createTrackedDialog(
|
||||||
'Failed to add the following room to the group summary',
|
'Failed to add the following room to the group summary',
|
||||||
'', ErrorDialog,
|
'', ErrorDialog,
|
||||||
{
|
{
|
||||||
title: _t(
|
title: _t(
|
||||||
"Failed to add the following rooms to the summary of %(groupId)s:",
|
"Failed to add the following rooms to the summary of %(groupId)s:",
|
||||||
{groupId: this.props.groupId},
|
{groupId: this.props.groupId},
|
||||||
),
|
),
|
||||||
description: errorList.join(", "),
|
description: errorList.join(", "),
|
||||||
});
|
},
|
||||||
|
);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}, /*className=*/null, /*isPriority=*/false, /*isStatic=*/true);
|
}, /*className=*/null, /*isPriority=*/false, /*isStatic=*/true);
|
||||||
|
@ -145,9 +146,10 @@ class CategoryRoomList extends React.Component {
|
||||||
|
|
||||||
let catHeader = <div />;
|
let catHeader = <div />;
|
||||||
if (this.props.category && this.props.category.profile) {
|
if (this.props.category && this.props.category.profile) {
|
||||||
catHeader = <div className="mx_GroupView_featuredThings_category">
|
catHeader = <div
|
||||||
{ this.props.category.profile.name }
|
className="mx_GroupView_featuredThings_category">
|
||||||
</div>;
|
{ this.props.category.profile.name }
|
||||||
|
</div>;
|
||||||
}
|
}
|
||||||
return <div className="mx_GroupView_featuredThings_container">
|
return <div className="mx_GroupView_featuredThings_container">
|
||||||
{ catHeader }
|
{ catHeader }
|
||||||
|
@ -190,13 +192,14 @@ class FeaturedRoom extends React.Component {
|
||||||
Modal.createTrackedDialog(
|
Modal.createTrackedDialog(
|
||||||
'Failed to remove room from group summary',
|
'Failed to remove room from group summary',
|
||||||
'', ErrorDialog,
|
'', ErrorDialog,
|
||||||
{
|
{
|
||||||
title: _t(
|
title: _t(
|
||||||
"Failed to remove the room from the summary of %(groupId)s",
|
"Failed to remove the room from the summary of %(groupId)s",
|
||||||
{groupId: this.props.groupId},
|
{groupId: this.props.groupId},
|
||||||
),
|
),
|
||||||
description: _t("The room '%(roomName)s' could not be removed from the summary.", {roomName}),
|
description: _t("The room '%(roomName)s' could not be removed from the summary.", {roomName}),
|
||||||
});
|
},
|
||||||
|
);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -283,13 +286,13 @@ class RoleUserList extends React.Component {
|
||||||
Modal.createTrackedDialog(
|
Modal.createTrackedDialog(
|
||||||
'Failed to add the following users to the community summary',
|
'Failed to add the following users to the community summary',
|
||||||
'', ErrorDialog,
|
'', ErrorDialog,
|
||||||
{
|
{
|
||||||
title: _t(
|
title: _t(
|
||||||
"Failed to add the following users to the summary of %(groupId)s:",
|
"Failed to add the following users to the summary of %(groupId)s:",
|
||||||
{groupId: this.props.groupId},
|
{groupId: this.props.groupId},
|
||||||
),
|
),
|
||||||
description: errorList.join(", "),
|
description: errorList.join(", "),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}, /*className=*/null, /*isPriority=*/false, /*isStatic=*/true);
|
}, /*className=*/null, /*isPriority=*/false, /*isStatic=*/true);
|
||||||
|
@ -299,11 +302,11 @@ class RoleUserList extends React.Component {
|
||||||
const TintableSvg = sdk.getComponent("elements.TintableSvg");
|
const TintableSvg = sdk.getComponent("elements.TintableSvg");
|
||||||
const addButton = this.props.editing ?
|
const addButton = this.props.editing ?
|
||||||
(<AccessibleButton className="mx_GroupView_featuredThings_addButton" onClick={this.onAddUsersClicked}>
|
(<AccessibleButton className="mx_GroupView_featuredThings_addButton" onClick={this.onAddUsersClicked}>
|
||||||
<TintableSvg src={require("../../../res/img/icons-create-room.svg")} width="64" height="64" />
|
<TintableSvg src={require("../../../res/img/icons-create-room.svg")} width="64" height="64" />
|
||||||
<div className="mx_GroupView_featuredThings_addButton_label">
|
<div className="mx_GroupView_featuredThings_addButton_label">
|
||||||
{ _t('Add a User') }
|
{ _t('Add a User') }
|
||||||
</div>
|
</div>
|
||||||
</AccessibleButton>) : <div />;
|
</AccessibleButton>) : <div />;
|
||||||
const userNodes = this.props.users.map((u) => {
|
const userNodes = this.props.users.map((u) => {
|
||||||
return <FeaturedUser
|
return <FeaturedUser
|
||||||
key={u.user_id}
|
key={u.user_id}
|
||||||
|
@ -353,13 +356,14 @@ class FeaturedUser extends React.Component {
|
||||||
Modal.createTrackedDialog(
|
Modal.createTrackedDialog(
|
||||||
'Failed to remove user from community summary',
|
'Failed to remove user from community summary',
|
||||||
'', ErrorDialog,
|
'', ErrorDialog,
|
||||||
{
|
{
|
||||||
title: _t(
|
title: _t(
|
||||||
"Failed to remove a user from the summary of %(groupId)s",
|
"Failed to remove a user from the summary of %(groupId)s",
|
||||||
{groupId: this.props.groupId},
|
{groupId: this.props.groupId},
|
||||||
),
|
),
|
||||||
description: _t("The user '%(displayName)s' could not be removed from the summary.", {displayName}),
|
description: _t("The user '%(displayName)s' could not be removed from the summary.", {displayName}),
|
||||||
});
|
},
|
||||||
|
);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -767,8 +771,8 @@ export default class GroupView extends React.Component {
|
||||||
title: _t("Leave Community"),
|
title: _t("Leave Community"),
|
||||||
description: (
|
description: (
|
||||||
<span>
|
<span>
|
||||||
{ _t("Leave %(groupName)s?", {groupName: this.props.groupId}) }
|
{ _t("Leave %(groupName)s?", {groupName: this.props.groupId}) }
|
||||||
{ warnings }
|
{ warnings }
|
||||||
</span>
|
</span>
|
||||||
),
|
),
|
||||||
button: _t("Leave"),
|
button: _t("Leave"),
|
||||||
|
@ -1059,7 +1063,7 @@ export default class GroupView extends React.Component {
|
||||||
'mx_RoomHeader_textButton',
|
'mx_RoomHeader_textButton',
|
||||||
'mx_GroupView_textButton',
|
'mx_GroupView_textButton',
|
||||||
],
|
],
|
||||||
membershipButtonExtraClasses,
|
membershipButtonExtraClasses,
|
||||||
);
|
);
|
||||||
|
|
||||||
const membershipContainerClasses = classnames(
|
const membershipContainerClasses = classnames(
|
||||||
|
|
|
@ -427,8 +427,10 @@ export default class MessagePanel extends React.Component {
|
||||||
// we get a new DOM node (restarting the animation) when the ghost
|
// we get a new DOM node (restarting the animation) when the ghost
|
||||||
// moves to a different event.
|
// moves to a different event.
|
||||||
return (
|
return (
|
||||||
<li key={"_readuptoghost_"+eventId}
|
<li
|
||||||
className="mx_RoomView_myReadMarker_container">
|
key={"_readuptoghost_"+eventId}
|
||||||
|
className="mx_RoomView_myReadMarker_container"
|
||||||
|
>
|
||||||
{ hr }
|
{ hr }
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
|
@ -1014,13 +1016,13 @@ class CreationGrouper {
|
||||||
|
|
||||||
ret.push(
|
ret.push(
|
||||||
<EventListSummary
|
<EventListSummary
|
||||||
key="roomcreationsummary"
|
key="roomcreationsummary"
|
||||||
events={this.events}
|
events={this.events}
|
||||||
onToggle={panel._onHeightChanged} // Update scroll state
|
onToggle={panel._onHeightChanged} // Update scroll state
|
||||||
summaryMembers={[ev.sender]}
|
summaryMembers={[ev.sender]}
|
||||||
summaryText={summaryText}
|
summaryText={summaryText}
|
||||||
>
|
>
|
||||||
{ eventTiles }
|
{ eventTiles }
|
||||||
</EventListSummary>,
|
</EventListSummary>,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1222,11 +1224,11 @@ class MemberGrouper {
|
||||||
|
|
||||||
ret.push(
|
ret.push(
|
||||||
<MemberEventListSummary key={key}
|
<MemberEventListSummary key={key}
|
||||||
events={this.events}
|
events={this.events}
|
||||||
onToggle={panel._onHeightChanged} // Update scroll state
|
onToggle={panel._onHeightChanged} // Update scroll state
|
||||||
startExpanded={highlightInMels}
|
startExpanded={highlightInMels}
|
||||||
>
|
>
|
||||||
{ eventTiles }
|
{ eventTiles }
|
||||||
</MemberEventListSummary>,
|
</MemberEventListSummary>,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -196,20 +196,22 @@ export default class RoomStatusBar extends React.Component {
|
||||||
} else if (resourceLimitError) {
|
} else if (resourceLimitError) {
|
||||||
title = messageForResourceLimitError(
|
title = messageForResourceLimitError(
|
||||||
resourceLimitError.data.limit_type,
|
resourceLimitError.data.limit_type,
|
||||||
resourceLimitError.data.admin_contact, {
|
resourceLimitError.data.admin_contact,
|
||||||
'monthly_active_user': _td(
|
{
|
||||||
"Your message wasn't sent because this homeserver has hit its Monthly Active User Limit. " +
|
'monthly_active_user': _td(
|
||||||
"Please <a>contact your service administrator</a> to continue using the service.",
|
"Your message wasn't sent because this homeserver has hit its Monthly Active User Limit. " +
|
||||||
),
|
"Please <a>contact your service administrator</a> to continue using the service.",
|
||||||
'hs_disabled': _td(
|
),
|
||||||
"Your message wasn't sent because this homeserver has been blocked by it's administrator. " +
|
'hs_disabled': _td(
|
||||||
"Please <a>contact your service administrator</a> to continue using the service.",
|
"Your message wasn't sent because this homeserver has been blocked by it's administrator. " +
|
||||||
),
|
"Please <a>contact your service administrator</a> to continue using the service.",
|
||||||
'': _td(
|
),
|
||||||
"Your message wasn't sent because this homeserver has exceeded a resource limit. " +
|
'': _td(
|
||||||
"Please <a>contact your service administrator</a> to continue using the service.",
|
"Your message wasn't sent because this homeserver has exceeded a resource limit. " +
|
||||||
),
|
"Please <a>contact your service administrator</a> to continue using the service.",
|
||||||
});
|
),
|
||||||
|
},
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
title = _t('Some of your messages have not been sent');
|
title = _t('Some of your messages have not been sent');
|
||||||
}
|
}
|
||||||
|
@ -261,7 +263,7 @@ export default class RoomStatusBar extends React.Component {
|
||||||
<div role="alert">
|
<div role="alert">
|
||||||
<div className="mx_RoomStatusBar_connectionLostBar">
|
<div className="mx_RoomStatusBar_connectionLostBar">
|
||||||
<img src={require("../../../res/img/feather-customised/warning-triangle.svg")} width="24"
|
<img src={require("../../../res/img/feather-customised/warning-triangle.svg")} width="24"
|
||||||
height="24" title="/!\ " alt="/!\ " />
|
height="24" title="/!\ " alt="/!\ " />
|
||||||
<div>
|
<div>
|
||||||
<div className="mx_RoomStatusBar_connectionLostBar_title">
|
<div className="mx_RoomStatusBar_connectionLostBar_title">
|
||||||
{_t('Connectivity to the server has been lost.')}
|
{_t('Connectivity to the server has been lost.')}
|
||||||
|
|
|
@ -884,16 +884,19 @@ export default class ScrollPanel extends React.Component {
|
||||||
|
|
||||||
// give the <ol> an explicit role=list because Safari+VoiceOver seems to think an ordered-list with
|
// give the <ol> an explicit role=list because Safari+VoiceOver seems to think an ordered-list with
|
||||||
// list-style-type: none; is no longer a list
|
// list-style-type: none; is no longer a list
|
||||||
return (<AutoHideScrollbar wrappedRef={this._collectScroll}
|
return (<AutoHideScrollbar
|
||||||
onScroll={this.onScroll}
|
wrappedRef={this._collectScroll}
|
||||||
className={`mx_ScrollPanel ${this.props.className}`} style={this.props.style}>
|
onScroll={this.onScroll}
|
||||||
{ this.props.fixedChildren }
|
className={`mx_ScrollPanel ${this.props.className}`}
|
||||||
<div className="mx_RoomView_messageListWrapper">
|
style={this.props.style}
|
||||||
<ol ref={this._itemlist} className="mx_RoomView_MessageList" aria-live="polite" role="list">
|
>
|
||||||
{ this.props.children }
|
{ this.props.fixedChildren }
|
||||||
</ol>
|
<div className="mx_RoomView_messageListWrapper">
|
||||||
</div>
|
<ol ref={this._itemlist} className="mx_RoomView_MessageList" aria-live="polite" role="list">
|
||||||
</AutoHideScrollbar>
|
{ this.props.children }
|
||||||
);
|
</ol>
|
||||||
|
</div>
|
||||||
|
</AutoHideScrollbar>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -785,8 +785,10 @@ class TimelinePanel extends React.Component {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const lastDisplayedEvent = this.state.events[lastDisplayedIndex];
|
const lastDisplayedEvent = this.state.events[lastDisplayedIndex];
|
||||||
this._setReadMarker(lastDisplayedEvent.getId(),
|
this._setReadMarker(
|
||||||
lastDisplayedEvent.getTs());
|
lastDisplayedEvent.getId(),
|
||||||
|
lastDisplayedEvent.getTs(),
|
||||||
|
);
|
||||||
|
|
||||||
// the read-marker should become invisible, so that if the user scrolls
|
// the read-marker should become invisible, so that if the user scrolls
|
||||||
// down, they don't see it.
|
// down, they don't see it.
|
||||||
|
@ -872,7 +874,7 @@ class TimelinePanel extends React.Component {
|
||||||
// The messagepanel knows where the RM is, so we must have loaded
|
// The messagepanel knows where the RM is, so we must have loaded
|
||||||
// the relevant event.
|
// the relevant event.
|
||||||
this._messagePanel.current.scrollToEvent(this.state.readMarkerEventId,
|
this._messagePanel.current.scrollToEvent(this.state.readMarkerEventId,
|
||||||
0, 1/3);
|
0, 1/3);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1044,7 +1046,7 @@ class TimelinePanel extends React.Component {
|
||||||
}
|
}
|
||||||
if (eventId) {
|
if (eventId) {
|
||||||
this._messagePanel.current.scrollToEvent(eventId, pixelOffset,
|
this._messagePanel.current.scrollToEvent(eventId, pixelOffset,
|
||||||
offsetBase);
|
offsetBase);
|
||||||
} else {
|
} else {
|
||||||
this._messagePanel.current.scrollToBottom();
|
this._messagePanel.current.scrollToBottom();
|
||||||
}
|
}
|
||||||
|
@ -1418,8 +1420,8 @@ class TimelinePanel extends React.Component {
|
||||||
['PREPARED', 'CATCHUP'].includes(this.state.clientSyncState)
|
['PREPARED', 'CATCHUP'].includes(this.state.clientSyncState)
|
||||||
);
|
);
|
||||||
const events = this.state.firstVisibleEventIndex
|
const events = this.state.firstVisibleEventIndex
|
||||||
? this.state.events.slice(this.state.firstVisibleEventIndex)
|
? this.state.events.slice(this.state.firstVisibleEventIndex)
|
||||||
: this.state.events;
|
: this.state.events;
|
||||||
return (
|
return (
|
||||||
<MessagePanel
|
<MessagePanel
|
||||||
ref={this._messagePanel}
|
ref={this._messagePanel}
|
||||||
|
|
|
@ -169,7 +169,7 @@ export class PasswordAuthEntry extends React.Component {
|
||||||
{ submitButtonOrSpinner }
|
{ submitButtonOrSpinner }
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
{ errorSection }
|
{ errorSection }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -375,7 +375,7 @@ export class TermsAuthEntry extends React.Component {
|
||||||
if (this.props.showContinue !== false) {
|
if (this.props.showContinue !== false) {
|
||||||
// XXX: button classes
|
// XXX: button classes
|
||||||
submitButton = <button className="mx_InteractiveAuthEntryComponents_termsSubmit mx_GeneralButton"
|
submitButton = <button className="mx_InteractiveAuthEntryComponents_termsSubmit mx_GeneralButton"
|
||||||
onClick={this._trySubmit} disabled={!allChecked}>{_t("Accept")}</button>;
|
onClick={this._trySubmit} disabled={!allChecked}>{_t("Accept")}</button>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -350,7 +350,7 @@ export default class MessageContextMenu extends React.Component {
|
||||||
>
|
>
|
||||||
{ _t('Source URL') }
|
{ _t('Source URL') }
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.props.collapseReplyThread) {
|
if (this.props.collapseReplyThread) {
|
||||||
|
|
|
@ -184,7 +184,7 @@ export default class BugReportDialog extends React.Component {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseDialog className="mx_BugReportDialog" onFinished={this._onCancel}
|
<BaseDialog className="mx_BugReportDialog" onFinished={this._onCancel}
|
||||||
title={_t('Submit debug logs')}
|
title={_t('Submit debug logs')}
|
||||||
contentId='mx_Dialog_content'
|
contentId='mx_Dialog_content'
|
||||||
>
|
>
|
||||||
<div className="mx_Dialog_content" id='mx_Dialog_content'>
|
<div className="mx_Dialog_content" id='mx_Dialog_content'>
|
||||||
|
|
|
@ -95,7 +95,7 @@ export default class ChangelogDialog extends React.Component {
|
||||||
description={content}
|
description={content}
|
||||||
button={_t("Update")}
|
button={_t("Update")}
|
||||||
onFinished={this.props.onFinished}
|
onFinished={this.props.onFinished}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,9 +39,12 @@ export default class ConfirmWipeDeviceDialog extends React.Component {
|
||||||
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseDialog className='mx_ConfirmWipeDeviceDialog' hasCancel={true}
|
<BaseDialog
|
||||||
onFinished={this.props.onFinished}
|
className='mx_ConfirmWipeDeviceDialog'
|
||||||
title={_t("Clear all data in this session?")}>
|
hasCancel={true}
|
||||||
|
onFinished={this.props.onFinished}
|
||||||
|
title={_t("Clear all data in this session?")}
|
||||||
|
>
|
||||||
<div className='mx_ConfirmWipeDeviceDialog_content'>
|
<div className='mx_ConfirmWipeDeviceDialog_content'>
|
||||||
<p>
|
<p>
|
||||||
{_t(
|
{_t(
|
||||||
|
|
|
@ -70,8 +70,16 @@ class GenericEditor extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
textInput(id, label) {
|
textInput(id, label) {
|
||||||
return <Field id={id} label={label} size="42" autoFocus={true} type="text" autoComplete="on"
|
return <Field
|
||||||
value={this.state[id]} onChange={this._onChange} />;
|
id={id}
|
||||||
|
label={label}
|
||||||
|
size="42"
|
||||||
|
autoFocus={true}
|
||||||
|
type="text"
|
||||||
|
autoComplete="on"
|
||||||
|
value={this.state[id]}
|
||||||
|
onChange={this._onChange}
|
||||||
|
/>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,7 +163,7 @@ export class SendCustomEvent extends GenericEditor {
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<Field id="evContent" label={_t("Event Content")} type="text" className="mx_DevTools_textarea"
|
<Field id="evContent" label={_t("Event Content")} type="text" className="mx_DevTools_textarea"
|
||||||
autoComplete="off" value={this.state.evContent} onChange={this._onChange} element="textarea" />
|
autoComplete="off" value={this.state.evContent} onChange={this._onChange} element="textarea" />
|
||||||
</div>
|
</div>
|
||||||
<div className="mx_Dialog_buttons">
|
<div className="mx_Dialog_buttons">
|
||||||
<button onClick={this.onBack}>{ _t('Back') }</button>
|
<button onClick={this.onBack}>{ _t('Back') }</button>
|
||||||
|
@ -239,7 +247,7 @@ class SendAccountData extends GenericEditor {
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<Field id="evContent" label={_t("Event Content")} type="text" className="mx_DevTools_textarea"
|
<Field id="evContent" label={_t("Event Content")} type="text" className="mx_DevTools_textarea"
|
||||||
autoComplete="off" value={this.state.evContent} onChange={this._onChange} element="textarea" />
|
autoComplete="off" value={this.state.evContent} onChange={this._onChange} element="textarea" />
|
||||||
</div>
|
</div>
|
||||||
<div className="mx_Dialog_buttons">
|
<div className="mx_Dialog_buttons">
|
||||||
<button onClick={this.onBack}>{ _t('Back') }</button>
|
<button onClick={this.onBack}>{ _t('Back') }</button>
|
||||||
|
@ -315,15 +323,15 @@ class FilteredList extends React.PureComponent {
|
||||||
const TruncatedList = sdk.getComponent("elements.TruncatedList");
|
const TruncatedList = sdk.getComponent("elements.TruncatedList");
|
||||||
return <div>
|
return <div>
|
||||||
<Field label={_t('Filter results')} autoFocus={true} size={64}
|
<Field label={_t('Filter results')} autoFocus={true} size={64}
|
||||||
type="text" autoComplete="off" value={this.props.query} onChange={this.onQuery}
|
type="text" autoComplete="off" value={this.props.query} onChange={this.onQuery}
|
||||||
className="mx_TextInputDialog_input mx_DevTools_RoomStateExplorer_query"
|
className="mx_TextInputDialog_input mx_DevTools_RoomStateExplorer_query"
|
||||||
// force re-render so that autoFocus is applied when this component is re-used
|
// force re-render so that autoFocus is applied when this component is re-used
|
||||||
key={this.props.children[0] ? this.props.children[0].key : ''} />
|
key={this.props.children[0] ? this.props.children[0].key : ''} />
|
||||||
|
|
||||||
<TruncatedList getChildren={this.getChildren}
|
<TruncatedList getChildren={this.getChildren}
|
||||||
getChildCount={this.getChildCount}
|
getChildCount={this.getChildCount}
|
||||||
truncateAt={this.state.truncateAt}
|
truncateAt={this.state.truncateAt}
|
||||||
createOverflowElement={this.createOverflowElement} />
|
createOverflowElement={this.createOverflowElement} />
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -647,7 +655,7 @@ function VerificationRequest({txnId, request}) {
|
||||||
|
|
||||||
/* Note that request.timeout is a getter, so its value changes */
|
/* Note that request.timeout is a getter, so its value changes */
|
||||||
const id = setInterval(() => {
|
const id = setInterval(() => {
|
||||||
setRequestTimeout(request.timeout);
|
setRequestTimeout(request.timeout);
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
return () => { clearInterval(id); };
|
return () => { clearInterval(id); };
|
||||||
|
@ -941,35 +949,35 @@ class SettingsExplorer extends React.Component {
|
||||||
/>
|
/>
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{_t("Setting ID")}</th>
|
<th>{_t("Setting ID")}</th>
|
||||||
<th>{_t("Value")}</th>
|
<th>{_t("Value")}</th>
|
||||||
<th>{_t("Value in this room")}</th>
|
<th>{_t("Value in this room")}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{allSettings.map(i => (
|
{allSettings.map(i => (
|
||||||
<tr key={i}>
|
<tr key={i}>
|
||||||
<td>
|
<td>
|
||||||
<a href="" onClick={(e) => this.onViewClick(e, i)}>
|
<a href="" onClick={(e) => this.onViewClick(e, i)}>
|
||||||
<code>{i}</code>
|
<code>{i}</code>
|
||||||
</a>
|
</a>
|
||||||
<a href="" onClick={(e) => this.onEditClick(e, i)}
|
<a href="" onClick={(e) => this.onEditClick(e, i)}
|
||||||
className='mx_DevTools_SettingsExplorer_edit'
|
className='mx_DevTools_SettingsExplorer_edit'
|
||||||
>
|
>
|
||||||
✏
|
✏
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<code>{this.renderSettingValue(SettingsStore.getValue(i))}</code>
|
<code>{this.renderSettingValue(SettingsStore.getValue(i))}</code>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<code>
|
<code>
|
||||||
{this.renderSettingValue(SettingsStore.getValue(i, room.roomId))}
|
{this.renderSettingValue(SettingsStore.getValue(i, room.roomId))}
|
||||||
</code>
|
</code>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
@ -998,11 +1006,11 @@ class SettingsExplorer extends React.Component {
|
||||||
<div>
|
<div>
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{_t("Level")}</th>
|
<th>{_t("Level")}</th>
|
||||||
<th>{_t("Settable at global")}</th>
|
<th>{_t("Settable at global")}</th>
|
||||||
<th>{_t("Settable at room")}</th>
|
<th>{_t("Settable at room")}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{LEVEL_ORDER.map(lvl => (
|
{LEVEL_ORDER.map(lvl => (
|
||||||
|
|
|
@ -42,9 +42,12 @@ export default class IntegrationsDisabledDialog extends React.Component {
|
||||||
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseDialog className='mx_IntegrationsDisabledDialog' hasCancel={true}
|
<BaseDialog
|
||||||
onFinished={this.props.onFinished}
|
className='mx_IntegrationsDisabledDialog'
|
||||||
title={_t("Integrations are disabled")}>
|
hasCancel={true}
|
||||||
|
onFinished={this.props.onFinished}
|
||||||
|
title={_t("Integrations are disabled")}
|
||||||
|
>
|
||||||
<div className='mx_IntegrationsDisabledDialog_content'>
|
<div className='mx_IntegrationsDisabledDialog_content'>
|
||||||
<p>{_t("Enable 'Manage Integrations' in Settings to do this.")}</p>
|
<p>{_t("Enable 'Manage Integrations' in Settings to do this.")}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -37,9 +37,12 @@ export default class IntegrationsImpossibleDialog extends React.Component {
|
||||||
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseDialog className='mx_IntegrationsImpossibleDialog' hasCancel={false}
|
<BaseDialog
|
||||||
onFinished={this.props.onFinished}
|
className='mx_IntegrationsImpossibleDialog'
|
||||||
title={_t("Integrations not allowed")}>
|
hasCancel={false}
|
||||||
|
onFinished={this.props.onFinished}
|
||||||
|
title={_t("Integrations not allowed")}
|
||||||
|
>
|
||||||
<div className='mx_IntegrationsImpossibleDialog_content'>
|
<div className='mx_IntegrationsImpossibleDialog_content'>
|
||||||
<p>
|
<p>
|
||||||
{_t(
|
{_t(
|
||||||
|
|
|
@ -24,7 +24,7 @@ export default function KeySignatureUploadFailedDialog({
|
||||||
source,
|
source,
|
||||||
continuation,
|
continuation,
|
||||||
onFinished,
|
onFinished,
|
||||||
}) {
|
}) {
|
||||||
const RETRIES = 2;
|
const RETRIES = 2;
|
||||||
const BaseDialog = sdk.getComponent('dialogs.BaseDialog');
|
const BaseDialog = sdk.getComponent('dialogs.BaseDialog');
|
||||||
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
||||||
|
@ -84,10 +84,10 @@ export default function KeySignatureUploadFailedDialog({
|
||||||
} else {
|
} else {
|
||||||
body = (<div>
|
body = (<div>
|
||||||
{success ?
|
{success ?
|
||||||
<span>{_t("Upload completed")}</span> :
|
<span>{_t("Upload completed")}</span> :
|
||||||
cancelled ?
|
cancelled ?
|
||||||
<span>{_t("Cancelled signature upload")}</span> :
|
<span>{_t("Cancelled signature upload")}</span> :
|
||||||
<span>{_t("Unable to upload")}</span>}
|
<span>{_t("Unable to upload")}</span>}
|
||||||
<DialogButtons
|
<DialogButtons
|
||||||
primaryButton={_t("OK")}
|
primaryButton={_t("OK")}
|
||||||
hasCancel={false}
|
hasCancel={false}
|
||||||
|
|
|
@ -164,8 +164,12 @@ export default class MessageEditHistoryDialog extends React.PureComponent {
|
||||||
}
|
}
|
||||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||||
return (
|
return (
|
||||||
<BaseDialog className='mx_MessageEditHistoryDialog' hasCancel={true}
|
<BaseDialog
|
||||||
onFinished={this.props.onFinished} title={_t("Message edits")}>
|
className='mx_MessageEditHistoryDialog'
|
||||||
|
hasCancel={true}
|
||||||
|
onFinished={this.props.onFinished}
|
||||||
|
title={_t("Message edits")}
|
||||||
|
>
|
||||||
{content}
|
{content}
|
||||||
</BaseDialog>
|
</BaseDialog>
|
||||||
);
|
);
|
||||||
|
|
|
@ -117,7 +117,7 @@ export default class RoomSettingsDialog extends React.Component {
|
||||||
const roomName = MatrixClientPeg.get().getRoom(this.props.roomId).name;
|
const roomName = MatrixClientPeg.get().getRoom(this.props.roomId).name;
|
||||||
return (
|
return (
|
||||||
<BaseDialog className='mx_RoomSettingsDialog' hasCancel={true}
|
<BaseDialog className='mx_RoomSettingsDialog' hasCancel={true}
|
||||||
onFinished={this.props.onFinished} title={_t("Room Settings - %(roomName)s", {roomName})}>
|
onFinished={this.props.onFinished} title={_t("Room Settings - %(roomName)s", {roomName})}>
|
||||||
<div className='mx_SettingsDialog_content'>
|
<div className='mx_SettingsDialog_content'>
|
||||||
<TabbedView tabs={this._getTabs()} />
|
<TabbedView tabs={this._getTabs()} />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -98,7 +98,7 @@ export default class SessionRestoreErrorDialog extends React.Component {
|
||||||
"may be incompatible with this version. Close this window and return " +
|
"may be incompatible with this version. Close this window and return " +
|
||||||
"to the more recent version.",
|
"to the more recent version.",
|
||||||
{ brand },
|
{ brand },
|
||||||
) }</p>
|
) }</p>
|
||||||
|
|
||||||
<p>{ _t(
|
<p>{ _t(
|
||||||
"Clearing your browser's storage may fix the problem, but will sign you " +
|
"Clearing your browser's storage may fix the problem, but will sign you " +
|
||||||
|
|
|
@ -46,9 +46,10 @@ export default class StorageEvictedDialog extends React.Component {
|
||||||
if (SdkConfig.get().bug_report_endpoint_url) {
|
if (SdkConfig.get().bug_report_endpoint_url) {
|
||||||
logRequest = _t(
|
logRequest = _t(
|
||||||
"To help us prevent this in future, please <a>send us logs</a>.", {},
|
"To help us prevent this in future, please <a>send us logs</a>.", {},
|
||||||
{
|
{
|
||||||
a: text => <a href="#" onClick={this._sendBugReport}>{text}</a>,
|
a: text => <a href="#" onClick={this._sendBugReport}>{text}</a>,
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -156,7 +156,7 @@ export default class UserSettingsDialog extends React.Component {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseDialog className='mx_UserSettingsDialog' hasCancel={true}
|
<BaseDialog className='mx_UserSettingsDialog' hasCancel={true}
|
||||||
onFinished={this.props.onFinished} title={_t("Settings")}>
|
onFinished={this.props.onFinished} title={_t("Settings")}>
|
||||||
<div className='mx_SettingsDialog_content'>
|
<div className='mx_SettingsDialog_content'>
|
||||||
<TabbedView tabs={this._getTabs()} initialTabId={this.props.initialTabId} />
|
<TabbedView tabs={this._getTabs()} initialTabId={this.props.initialTabId} />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -52,11 +52,13 @@ export default class VerificationRequestDialog extends React.Component {
|
||||||
const title = request && request.isSelfVerification ?
|
const title = request && request.isSelfVerification ?
|
||||||
_t("Verify other login") : _t("Verification Request");
|
_t("Verify other login") : _t("Verification Request");
|
||||||
|
|
||||||
return <BaseDialog className="mx_InfoDialog" onFinished={this.props.onFinished}
|
return <BaseDialog
|
||||||
contentId="mx_Dialog_content"
|
className="mx_InfoDialog"
|
||||||
title={title}
|
onFinished={this.props.onFinished}
|
||||||
hasCancel={true}
|
contentId="mx_Dialog_content"
|
||||||
>
|
title={title}
|
||||||
|
hasCancel={true}
|
||||||
|
>
|
||||||
<EncryptionPanel
|
<EncryptionPanel
|
||||||
layout="dialog"
|
layout="dialog"
|
||||||
verificationRequest={this.props.verificationRequest}
|
verificationRequest={this.props.verificationRequest}
|
||||||
|
|
|
@ -71,8 +71,8 @@ export default class WidgetOpenIDPermissionsDialog extends React.Component {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseDialog className='mx_WidgetOpenIDPermissionsDialog' hasCancel={true}
|
<BaseDialog className='mx_WidgetOpenIDPermissionsDialog' hasCancel={true}
|
||||||
onFinished={this.props.onFinished}
|
onFinished={this.props.onFinished}
|
||||||
title={_t("Allow this widget to verify your identity")}>
|
title={_t("Allow this widget to verify your identity")}>
|
||||||
<div className='mx_WidgetOpenIDPermissionsDialog_content'>
|
<div className='mx_WidgetOpenIDPermissionsDialog_content'>
|
||||||
<p>
|
<p>
|
||||||
{_t("The widget will verify your user ID, but won't be able to perform actions for you:")}
|
{_t("The widget will verify your user ID, but won't be able to perform actions for you:")}
|
||||||
|
|
|
@ -40,10 +40,10 @@ export default class ConfirmDestroyCrossSigningDialog extends React.Component {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseDialog
|
<BaseDialog
|
||||||
className='mx_ConfirmDestroyCrossSigningDialog'
|
className='mx_ConfirmDestroyCrossSigningDialog'
|
||||||
hasCancel={true}
|
hasCancel={true}
|
||||||
onFinished={this.props.onFinished}
|
onFinished={this.props.onFinished}
|
||||||
title={_t("Destroy cross-signing keys?")}>
|
title={_t("Destroy cross-signing keys?")}>
|
||||||
<div className='mx_ConfirmDestroyCrossSigningDialog_content'>
|
<div className='mx_ConfirmDestroyCrossSigningDialog_content'>
|
||||||
<p>
|
<p>
|
||||||
{_t(
|
{_t(
|
||||||
|
|
|
@ -374,7 +374,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
|
||||||
"If you've forgotten your Security Phrase you can "+
|
"If you've forgotten your Security Phrase you can "+
|
||||||
"<button1>use your Security Key</button1> or " +
|
"<button1>use your Security Key</button1> or " +
|
||||||
"<button2>set up new recovery options</button2>"
|
"<button2>set up new recovery options</button2>"
|
||||||
, {}, {
|
, {}, {
|
||||||
button1: s => <AccessibleButton className="mx_linkButton"
|
button1: s => <AccessibleButton className="mx_linkButton"
|
||||||
element="span"
|
element="span"
|
||||||
onClick={this._onUseRecoveryKeyClick}
|
onClick={this._onUseRecoveryKeyClick}
|
||||||
|
@ -387,7 +387,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
|
||||||
>
|
>
|
||||||
{s}
|
{s}
|
||||||
</AccessibleButton>,
|
</AccessibleButton>,
|
||||||
})}
|
})}
|
||||||
</div>;
|
</div>;
|
||||||
} else {
|
} else {
|
||||||
title = _t("Enter Security Key");
|
title = _t("Enter Security Key");
|
||||||
|
@ -436,14 +436,14 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
|
||||||
{_t(
|
{_t(
|
||||||
"If you've forgotten your Security Key you can "+
|
"If you've forgotten your Security Key you can "+
|
||||||
"<button>set up new recovery options</button>"
|
"<button>set up new recovery options</button>"
|
||||||
, {}, {
|
, {}, {
|
||||||
button: s => <AccessibleButton className="mx_linkButton"
|
button: s => <AccessibleButton className="mx_linkButton"
|
||||||
element="span"
|
element="span"
|
||||||
onClick={this._onResetRecoveryClick}
|
onClick={this._onResetRecoveryClick}
|
||||||
>
|
>
|
||||||
{s}
|
{s}
|
||||||
</AccessibleButton>,
|
</AccessibleButton>,
|
||||||
})}
|
})}
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -452,9 +452,9 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
|
||||||
onFinished={this.props.onFinished}
|
onFinished={this.props.onFinished}
|
||||||
title={title}
|
title={title}
|
||||||
>
|
>
|
||||||
<div className='mx_RestoreKeyBackupDialog_content'>
|
<div className='mx_RestoreKeyBackupDialog_content'>
|
||||||
{content}
|
{content}
|
||||||
</div>
|
</div>
|
||||||
</BaseDialog>
|
</BaseDialog>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,8 +70,8 @@ export default class ActionButton extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
const icon = this.props.iconPath ?
|
const icon = this.props.iconPath ?
|
||||||
(<TintableSvg src={this.props.iconPath} width={this.props.size} height={this.props.size} />) :
|
(<TintableSvg src={this.props.iconPath} width={this.props.size} height={this.props.size} />) :
|
||||||
undefined;
|
undefined;
|
||||||
|
|
||||||
const classNames = ["mx_RoleButton"];
|
const classNames = ["mx_RoleButton"];
|
||||||
if (this.props.className) {
|
if (this.props.className) {
|
||||||
|
|
|
@ -109,7 +109,7 @@ export default class AppTile extends React.Component {
|
||||||
const childContentProtocol = u.protocol;
|
const childContentProtocol = u.protocol;
|
||||||
if (parentContentProtocol === 'https:' && childContentProtocol !== 'https:') {
|
if (parentContentProtocol === 'https:' && childContentProtocol !== 'https:') {
|
||||||
console.warn("Refusing to load mixed-content app:",
|
console.warn("Refusing to load mixed-content app:",
|
||||||
parentContentProtocol, childContentProtocol, window.location, this.props.app.url);
|
parentContentProtocol, childContentProtocol, window.location, this.props.app.url);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -65,12 +65,18 @@ export class EditableItem extends React.Component {
|
||||||
<span className="mx_EditableItem_promptText">
|
<span className="mx_EditableItem_promptText">
|
||||||
{_t("Are you sure?")}
|
{_t("Are you sure?")}
|
||||||
</span>
|
</span>
|
||||||
<AccessibleButton onClick={this._onActuallyRemove} kind="primary_sm"
|
<AccessibleButton
|
||||||
className="mx_EditableItem_confirmBtn">
|
onClick={this._onActuallyRemove}
|
||||||
|
kind="primary_sm"
|
||||||
|
className="mx_EditableItem_confirmBtn"
|
||||||
|
>
|
||||||
{_t("Yes")}
|
{_t("Yes")}
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
<AccessibleButton onClick={this._onDontRemove} kind="danger_sm"
|
<AccessibleButton
|
||||||
className="mx_EditableItem_confirmBtn">
|
onClick={this._onDontRemove}
|
||||||
|
kind="danger_sm"
|
||||||
|
className="mx_EditableItem_confirmBtn"
|
||||||
|
>
|
||||||
{_t("No")}
|
{_t("No")}
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
</div>
|
</div>
|
||||||
|
@ -122,10 +128,10 @@ export default class EditableItemList extends React.Component {
|
||||||
_renderNewItemField() {
|
_renderNewItemField() {
|
||||||
return (
|
return (
|
||||||
<form onSubmit={this._onItemAdded} autoComplete="off"
|
<form onSubmit={this._onItemAdded} autoComplete="off"
|
||||||
noValidate={true} className="mx_EditableItemList_newItem">
|
noValidate={true} className="mx_EditableItemList_newItem">
|
||||||
<Field label={this.props.placeholder} type="text"
|
<Field label={this.props.placeholder} type="text"
|
||||||
autoComplete="off" value={this.props.newItem || ""} onChange={this._onNewItemChanged}
|
autoComplete="off" value={this.props.newItem || ""} onChange={this._onNewItemChanged}
|
||||||
list={this.props.suggestionsListId} />
|
list={this.props.suggestionsListId} />
|
||||||
<AccessibleButton onClick={this._onItemAdded} kind="primary" type="submit" disabled={!this.props.newItem}>
|
<AccessibleButton onClick={this._onItemAdded} kind="primary" type="submit" disabled={!this.props.newItem}>
|
||||||
{_t("Add")}
|
{_t("Add")}
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
|
|
|
@ -221,13 +221,15 @@ export default class EditableText extends React.Component {
|
||||||
</div>;
|
</div>;
|
||||||
} else {
|
} else {
|
||||||
// show the content editable div, but manually manage its contents as react and contentEditable don't play nice together
|
// show the content editable div, but manually manage its contents as react and contentEditable don't play nice together
|
||||||
editableEl = <div ref={this._editable_div}
|
editableEl = <div
|
||||||
contentEditable={true}
|
ref={this._editable_div}
|
||||||
className={className}
|
contentEditable={true}
|
||||||
onKeyDown={this.onKeyDown}
|
className={className}
|
||||||
onKeyUp={this.onKeyUp}
|
onKeyDown={this.onKeyDown}
|
||||||
onFocus={this.onFocus}
|
onKeyUp={this.onKeyUp}
|
||||||
onBlur={this.onBlur} />;
|
onFocus={this.onFocus}
|
||||||
|
onBlur={this.onBlur}
|
||||||
|
/>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return editableEl;
|
return editableEl;
|
||||||
|
|
|
@ -46,8 +46,12 @@ export default class LabelledToggleSwitch extends React.Component {
|
||||||
// This is a minimal version of a SettingsFlag
|
// This is a minimal version of a SettingsFlag
|
||||||
|
|
||||||
let firstPart = <span className="mx_SettingsFlag_label">{this.props.label}</span>;
|
let firstPart = <span className="mx_SettingsFlag_label">{this.props.label}</span>;
|
||||||
let secondPart = <ToggleSwitch checked={this.props.value} disabled={this.props.disabled}
|
let secondPart = <ToggleSwitch
|
||||||
onChange={this.props.onChange} aria-label={this.props.label} />;
|
checked={this.props.value}
|
||||||
|
disabled={this.props.disabled}
|
||||||
|
onChange={this.props.onChange}
|
||||||
|
aria-label={this.props.label}
|
||||||
|
/>;
|
||||||
|
|
||||||
if (this.props.toggleInFront) {
|
if (this.props.toggleInFront) {
|
||||||
const temp = firstPart;
|
const temp = firstPart;
|
||||||
|
|
|
@ -60,10 +60,10 @@ export default class LanguageDropdown extends React.Component {
|
||||||
// doesn't know this, therefore we do this.
|
// doesn't know this, therefore we do this.
|
||||||
const language = SettingsStore.getValue("language", null, /*excludeDefault:*/true);
|
const language = SettingsStore.getValue("language", null, /*excludeDefault:*/true);
|
||||||
if (language) {
|
if (language) {
|
||||||
this.props.onOptionChange(language);
|
this.props.onOptionChange(language);
|
||||||
} else {
|
} else {
|
||||||
const language = languageHandler.normalizeLanguageKey(languageHandler.getLanguageFromBrowser());
|
const language = languageHandler.normalizeLanguageKey(languageHandler.getLanguageFromBrowser());
|
||||||
this.props.onOptionChange(language);
|
this.props.onOptionChange(language);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -225,19 +225,19 @@ class Pill extends React.Component {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Pill.TYPE_USER_MENTION: {
|
case Pill.TYPE_USER_MENTION: {
|
||||||
// If this user is not a member of this room, default to the empty member
|
// If this user is not a member of this room, default to the empty member
|
||||||
const member = this.state.member;
|
const member = this.state.member;
|
||||||
if (member) {
|
if (member) {
|
||||||
userId = member.userId;
|
userId = member.userId;
|
||||||
member.rawDisplayName = member.rawDisplayName || '';
|
member.rawDisplayName = member.rawDisplayName || '';
|
||||||
linkText = member.rawDisplayName;
|
linkText = member.rawDisplayName;
|
||||||
if (this.props.shouldShowPillAvatar) {
|
if (this.props.shouldShowPillAvatar) {
|
||||||
avatar = <MemberAvatar member={member} width={16} height={16} aria-hidden="true" />;
|
avatar = <MemberAvatar member={member} width={16} height={16} aria-hidden="true" />;
|
||||||
}
|
|
||||||
pillClass = 'mx_UserPill';
|
|
||||||
href = null;
|
|
||||||
onClick = this.onUserPillClicked;
|
|
||||||
}
|
}
|
||||||
|
pillClass = 'mx_UserPill';
|
||||||
|
href = null;
|
||||||
|
onClick = this.onUserPillClicked;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Pill.TYPE_ROOM_MENTION: {
|
case Pill.TYPE_ROOM_MENTION: {
|
||||||
|
|
|
@ -135,9 +135,13 @@ export default class PowerSelector extends React.Component {
|
||||||
if (this.state.custom) {
|
if (this.state.custom) {
|
||||||
picker = (
|
picker = (
|
||||||
<Field type="number"
|
<Field type="number"
|
||||||
label={label} max={this.props.maxValue}
|
label={label} max={this.props.maxValue}
|
||||||
onBlur={this.onCustomBlur} onKeyDown={this.onCustomKeyDown} onChange={this.onCustomChange}
|
onBlur={this.onCustomBlur}
|
||||||
value={String(this.state.customValue)} disabled={this.props.disabled} />
|
onKeyDown={this.onCustomKeyDown}
|
||||||
|
onChange={this.onCustomChange}
|
||||||
|
value={String(this.state.customValue)}
|
||||||
|
disabled={this.props.disabled}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// Each level must have a definition in this.state.levelRoleMap
|
// Each level must have a definition in this.state.levelRoleMap
|
||||||
|
@ -154,8 +158,9 @@ export default class PowerSelector extends React.Component {
|
||||||
|
|
||||||
picker = (
|
picker = (
|
||||||
<Field element="select"
|
<Field element="select"
|
||||||
label={label} onChange={this.onSelectChange}
|
label={label} onChange={this.onSelectChange}
|
||||||
value={String(this.state.selectValue)} disabled={this.props.disabled}>
|
value={String(this.state.selectValue)} disabled={this.props.disabled}
|
||||||
|
>
|
||||||
{options}
|
{options}
|
||||||
</Field>
|
</Field>
|
||||||
);
|
);
|
||||||
|
|
|
@ -46,17 +46,18 @@ export default class RoomAliasField extends React.PureComponent {
|
||||||
const domain = (<span title={aliasPostfix}>{aliasPostfix}</span>);
|
const domain = (<span title={aliasPostfix}>{aliasPostfix}</span>);
|
||||||
const maxlength = 255 - this.props.domain.length - 2; // 2 for # and :
|
const maxlength = 255 - this.props.domain.length - 2; // 2 for # and :
|
||||||
return (
|
return (
|
||||||
<Field
|
<Field
|
||||||
label={_t("Room address")}
|
label={_t("Room address")}
|
||||||
className="mx_RoomAliasField"
|
className="mx_RoomAliasField"
|
||||||
prefixComponent={poundSign}
|
prefixComponent={poundSign}
|
||||||
postfixComponent={domain}
|
postfixComponent={domain}
|
||||||
ref={ref => this._fieldRef = ref}
|
ref={ref => this._fieldRef = ref}
|
||||||
onValidate={this._onValidate}
|
onValidate={this._onValidate}
|
||||||
placeholder={_t("e.g. my-room")}
|
placeholder={_t("e.g. my-room")}
|
||||||
onChange={this._onChange}
|
onChange={this._onChange}
|
||||||
value={this.props.value.substring(1, this.props.value.length - this.props.domain.length - 1)}
|
value={this.props.value.substring(1, this.props.value.length - this.props.domain.length - 1)}
|
||||||
maxLength={maxlength} />
|
maxLength={maxlength}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,13 +59,13 @@ class TintableSvg extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<object className={"mx_TintableSvg " + (this.props.className ? this.props.className : "")}
|
<object className={"mx_TintableSvg " + (this.props.className ? this.props.className : "")}
|
||||||
type="image/svg+xml"
|
type="image/svg+xml"
|
||||||
data={this.props.src}
|
data={this.props.src}
|
||||||
width={this.props.width}
|
width={this.props.width}
|
||||||
height={this.props.height}
|
height={this.props.height}
|
||||||
onLoad={this.onLoad}
|
onLoad={this.onLoad}
|
||||||
tabIndex="-1"
|
tabIndex="-1"
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -178,9 +178,15 @@ export default class GroupMemberList extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
const inputBox = (
|
const inputBox = (
|
||||||
<input className="mx_GroupMemberList_query mx_textinput" id="mx_GroupMemberList_query" type="text"
|
<input
|
||||||
onChange={this.onSearchQueryChanged} value={this.state.searchQuery}
|
className="mx_GroupMemberList_query mx_textinput"
|
||||||
placeholder={_t('Filter community members')} autoComplete="off" />
|
id="mx_GroupMemberList_query"
|
||||||
|
type="text"
|
||||||
|
onChange={this.onSearchQueryChanged}
|
||||||
|
value={this.state.searchQuery}
|
||||||
|
placeholder={_t('Filter community members')}
|
||||||
|
autoComplete="off"
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
const joined = this.state.members ? <div className="mx_MemberList_joined">
|
const joined = this.state.members ? <div className="mx_MemberList_joined">
|
||||||
|
|
|
@ -67,11 +67,11 @@ export default class GroupPublicityToggle extends React.Component {
|
||||||
const GroupTile = sdk.getComponent('groups.GroupTile');
|
const GroupTile = sdk.getComponent('groups.GroupTile');
|
||||||
return <div className="mx_GroupPublicity_toggle">
|
return <div className="mx_GroupPublicity_toggle">
|
||||||
<GroupTile groupId={this.props.groupId} showDescription={false}
|
<GroupTile groupId={this.props.groupId} showDescription={false}
|
||||||
avatarHeight={40} draggable={false}
|
avatarHeight={40} draggable={false}
|
||||||
/>
|
/>
|
||||||
<ToggleSwitch checked={this.state.isGroupPublicised}
|
<ToggleSwitch checked={this.state.isGroupPublicised}
|
||||||
disabled={!this.state.ready || this.state.busy}
|
disabled={!this.state.ready || this.state.busy}
|
||||||
onChange={this._onPublicityToggle} />
|
onChange={this._onPublicityToggle} />
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,9 +141,14 @@ export default class GroupRoomList extends React.Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const inputBox = (
|
const inputBox = (
|
||||||
<input className="mx_GroupRoomList_query mx_textinput" id="mx_GroupRoomList_query" type="text"
|
<input
|
||||||
onChange={this.onSearchQueryChanged} value={this.state.searchQuery}
|
className="mx_GroupRoomList_query mx_textinput" id="mx_GroupRoomList_query"
|
||||||
placeholder={_t('Filter community rooms')} autoComplete="off" />
|
type="text"
|
||||||
|
onChange={this.onSearchQueryChanged}
|
||||||
|
value={this.state.searchQuery}
|
||||||
|
placeholder={_t('Filter community rooms')}
|
||||||
|
autoComplete="off"
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
const TruncatedList = sdk.getComponent("elements.TruncatedList");
|
const TruncatedList = sdk.getComponent("elements.TruncatedList");
|
||||||
|
@ -152,7 +157,7 @@ export default class GroupRoomList extends React.Component {
|
||||||
{ inviteButton }
|
{ inviteButton }
|
||||||
<AutoHideScrollbar className="mx_GroupRoomList_joined mx_GroupRoomList_outerWrapper">
|
<AutoHideScrollbar className="mx_GroupRoomList_joined mx_GroupRoomList_outerWrapper">
|
||||||
<TruncatedList className="mx_GroupRoomList_wrapper" truncateAt={this.state.truncateAt}
|
<TruncatedList className="mx_GroupRoomList_wrapper" truncateAt={this.state.truncateAt}
|
||||||
createOverflowElement={this._createOverflowTile}>
|
createOverflowElement={this._createOverflowTile}>
|
||||||
{ this.makeGroupRoomTiles(this.state.searchQuery) }
|
{ this.makeGroupRoomTiles(this.state.searchQuery) }
|
||||||
</TruncatedList>
|
</TruncatedList>
|
||||||
</AutoHideScrollbar>
|
</AutoHideScrollbar>
|
||||||
|
|
|
@ -125,9 +125,9 @@ export default class MImageBody extends React.Component {
|
||||||
_isGif() {
|
_isGif() {
|
||||||
const content = this.props.mxEvent.getContent();
|
const content = this.props.mxEvent.getContent();
|
||||||
return (
|
return (
|
||||||
content &&
|
content &&
|
||||||
content.info &&
|
content.info &&
|
||||||
content.info.mimetype === "image/gif"
|
content.info.mimetype === "image/gif"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,9 +346,9 @@ export default class MImageBody extends React.Component {
|
||||||
} else {
|
} else {
|
||||||
imageElement = (
|
imageElement = (
|
||||||
<img style={{display: 'none'}} src={thumbUrl} ref={this._image}
|
<img style={{display: 'none'}} src={thumbUrl} ref={this._image}
|
||||||
alt={content.body}
|
alt={content.body}
|
||||||
onError={this.onImageError}
|
onError={this.onImageError}
|
||||||
onLoad={this.onImageLoad}
|
onLoad={this.onImageLoad}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -384,12 +384,12 @@ export default class MImageBody extends React.Component {
|
||||||
// mx_MImageBody_thumbnail resizes img to exactly container size
|
// mx_MImageBody_thumbnail resizes img to exactly container size
|
||||||
img = (
|
img = (
|
||||||
<img className="mx_MImageBody_thumbnail" src={thumbUrl} ref={this._image}
|
<img className="mx_MImageBody_thumbnail" src={thumbUrl} ref={this._image}
|
||||||
style={{ maxWidth: maxWidth + "px" }}
|
style={{ maxWidth: maxWidth + "px" }}
|
||||||
alt={content.body}
|
alt={content.body}
|
||||||
onError={this.onImageError}
|
onError={this.onImageError}
|
||||||
onLoad={this.onImageLoad}
|
onLoad={this.onImageLoad}
|
||||||
onMouseEnter={this.onImageEnter}
|
onMouseEnter={this.onImageEnter}
|
||||||
onMouseLeave={this.onImageLeave} />
|
onMouseLeave={this.onImageLeave} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -467,9 +467,9 @@ export default class MImageBody extends React.Component {
|
||||||
const contentUrl = this._getContentUrl();
|
const contentUrl = this._getContentUrl();
|
||||||
let thumbUrl;
|
let thumbUrl;
|
||||||
if (this._isGif() && SettingsStore.getValue("autoplayGifsAndVideos")) {
|
if (this._isGif() && SettingsStore.getValue("autoplayGifsAndVideos")) {
|
||||||
thumbUrl = contentUrl;
|
thumbUrl = contentUrl;
|
||||||
} else {
|
} else {
|
||||||
thumbUrl = this._getThumbUrl();
|
thumbUrl = this._getThumbUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
const thumbnail = this._messageContent(contentUrl, thumbUrl, content);
|
const thumbnail = this._messageContent(contentUrl, thumbUrl, content);
|
||||||
|
|
|
@ -83,8 +83,8 @@ export default class MKeyVerificationConclusion extends React.Component {
|
||||||
|
|
||||||
// User isn't actually verified
|
// User isn't actually verified
|
||||||
if (!MatrixClientPeg.get()
|
if (!MatrixClientPeg.get()
|
||||||
.checkUserTrust(request.otherUserId)
|
.checkUserTrust(request.otherUserId)
|
||||||
.isCrossSigningVerified()) {
|
.isCrossSigningVerified()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -521,11 +521,12 @@ export default class TextualBody extends React.Component {
|
||||||
const LinkPreviewWidget = sdk.getComponent('rooms.LinkPreviewWidget');
|
const LinkPreviewWidget = sdk.getComponent('rooms.LinkPreviewWidget');
|
||||||
widgets = this.state.links.map((link)=>{
|
widgets = this.state.links.map((link)=>{
|
||||||
return <LinkPreviewWidget
|
return <LinkPreviewWidget
|
||||||
key={link}
|
key={link}
|
||||||
link={link}
|
link={link}
|
||||||
mxEvent={this.props.mxEvent}
|
mxEvent={this.props.mxEvent}
|
||||||
onCancelClick={this.onCancelClick}
|
onCancelClick={this.onCancelClick}
|
||||||
onHeightChanged={this.props.onHeightChanged} />;
|
onHeightChanged={this.props.onHeightChanged}
|
||||||
|
/>;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -310,9 +310,14 @@ export default class AliasSettings extends React.Component {
|
||||||
let found = false;
|
let found = false;
|
||||||
const canonicalValue = this.state.canonicalAlias || "";
|
const canonicalValue = this.state.canonicalAlias || "";
|
||||||
const canonicalAliasSection = (
|
const canonicalAliasSection = (
|
||||||
<Field onChange={this.onCanonicalAliasChange} value={canonicalValue}
|
<Field
|
||||||
disabled={this.state.updatingCanonicalAlias || !this.props.canSetCanonicalAlias}
|
onChange={this.onCanonicalAliasChange}
|
||||||
element='select' id='canonicalAlias' label={_t('Main address')}>
|
value={canonicalValue}
|
||||||
|
disabled={this.state.updatingCanonicalAlias || !this.props.canSetCanonicalAlias}
|
||||||
|
element='select'
|
||||||
|
id='canonicalAlias'
|
||||||
|
label={_t('Main address')}
|
||||||
|
>
|
||||||
<option value="" key="unset">{ _t('not specified') }</option>
|
<option value="" key="unset">{ _t('not specified') }</option>
|
||||||
{
|
{
|
||||||
this._getAliases().map((alias, i) => {
|
this._getAliases().map((alias, i) => {
|
||||||
|
@ -326,9 +331,9 @@ export default class AliasSettings extends React.Component {
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
found || !this.state.canonicalAlias ? '' :
|
found || !this.state.canonicalAlias ? '' :
|
||||||
<option value={ this.state.canonicalAlias } key='arbitrary'>
|
<option value={ this.state.canonicalAlias } key='arbitrary'>
|
||||||
{ this.state.canonicalAlias }
|
{ this.state.canonicalAlias }
|
||||||
</option>
|
</option>
|
||||||
}
|
}
|
||||||
</Field>
|
</Field>
|
||||||
);
|
);
|
||||||
|
|
|
@ -205,16 +205,34 @@ export default class RoomProfileSettings extends React.Component {
|
||||||
noValidate={true}
|
noValidate={true}
|
||||||
className="mx_ProfileSettings_profileForm"
|
className="mx_ProfileSettings_profileForm"
|
||||||
>
|
>
|
||||||
<input type="file" ref={this._avatarUpload} className="mx_ProfileSettings_avatarUpload"
|
<input
|
||||||
onChange={this._onAvatarChanged} accept="image/*" />
|
type="file"
|
||||||
|
ref={this._avatarUpload}
|
||||||
|
className="mx_ProfileSettings_avatarUpload"
|
||||||
|
onChange={this._onAvatarChanged}
|
||||||
|
accept="image/*"
|
||||||
|
/>
|
||||||
<div className="mx_ProfileSettings_profile">
|
<div className="mx_ProfileSettings_profile">
|
||||||
<div className="mx_ProfileSettings_controls">
|
<div className="mx_ProfileSettings_controls">
|
||||||
<Field label={_t("Room Name")}
|
<Field
|
||||||
type="text" value={this.state.displayName} autoComplete="off"
|
label={_t("Room Name")}
|
||||||
onChange={this._onDisplayNameChanged} disabled={!this.state.canSetName} />
|
type="text"
|
||||||
<Field className="mx_ProfileSettings_controls_topic" id="profileTopic" label={_t("Room Topic")} disabled={!this.state.canSetTopic}
|
value={this.state.displayName}
|
||||||
type="text" value={this.state.topic} autoComplete="off"
|
autoComplete="off"
|
||||||
onChange={this._onTopicChanged} element="textarea" />
|
onChange={this._onDisplayNameChanged}
|
||||||
|
disabled={!this.state.canSetName}
|
||||||
|
/>
|
||||||
|
<Field
|
||||||
|
className="mx_ProfileSettings_controls_topic"
|
||||||
|
id="profileTopic"
|
||||||
|
label={_t("Room Topic")}
|
||||||
|
disabled={!this.state.canSetTopic}
|
||||||
|
type="text"
|
||||||
|
value={this.state.topic}
|
||||||
|
autoComplete="off"
|
||||||
|
onChange={this._onTopicChanged}
|
||||||
|
element="textarea"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<AvatarSetting
|
<AvatarSetting
|
||||||
avatarUrl={this.state.avatarUrl}
|
avatarUrl={this.state.avatarUrl}
|
||||||
|
|
|
@ -68,10 +68,12 @@ export default class UrlPreviewSettings extends React.Component {
|
||||||
if (SettingsStore.canSetValue("urlPreviewsEnabled", roomId, "room")) {
|
if (SettingsStore.canSetValue("urlPreviewsEnabled", roomId, "room")) {
|
||||||
previewsForRoom = (
|
previewsForRoom = (
|
||||||
<label>
|
<label>
|
||||||
<SettingsFlag name="urlPreviewsEnabled"
|
<SettingsFlag
|
||||||
level={SettingLevel.ROOM}
|
name="urlPreviewsEnabled"
|
||||||
roomId={roomId}
|
level={SettingLevel.ROOM}
|
||||||
isExplicit={true} />
|
roomId={roomId}
|
||||||
|
isExplicit={true}
|
||||||
|
/>
|
||||||
</label>
|
</label>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -91,8 +93,8 @@ export default class UrlPreviewSettings extends React.Component {
|
||||||
|
|
||||||
const previewsForRoomAccount = ( // in an e2ee room we use a special key to enforce per-room opt-in
|
const previewsForRoomAccount = ( // in an e2ee room we use a special key to enforce per-room opt-in
|
||||||
<SettingsFlag name={isEncrypted ? 'urlPreviewsEnabled_e2ee' : 'urlPreviewsEnabled'}
|
<SettingsFlag name={isEncrypted ? 'urlPreviewsEnabled_e2ee' : 'urlPreviewsEnabled'}
|
||||||
level={SettingLevel.ROOM_ACCOUNT}
|
level={SettingLevel.ROOM_ACCOUNT}
|
||||||
roomId={roomId} />
|
roomId={roomId} />
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -176,8 +176,11 @@ class EntityTile extends React.Component {
|
||||||
// The wrapping div is required to make the magic mouse listener work, for some reason.
|
// The wrapping div is required to make the magic mouse listener work, for some reason.
|
||||||
return (
|
return (
|
||||||
<div ref={(c) => this.container = c} >
|
<div ref={(c) => this.container = c} >
|
||||||
<AccessibleButton className={classNames(mainClassNames)} title={this.props.title}
|
<AccessibleButton
|
||||||
onClick={this.props.onClick}>
|
className={classNames(mainClassNames)}
|
||||||
|
title={this.props.title}
|
||||||
|
onClick={this.props.onClick}
|
||||||
|
>
|
||||||
<div className="mx_EntityTile_avatar">
|
<div className="mx_EntityTile_avatar">
|
||||||
{ av }
|
{ av }
|
||||||
{ e2eIcon }
|
{ e2eIcon }
|
||||||
|
|
|
@ -128,8 +128,8 @@ export default class LinkPreviewWidget extends React.Component {
|
||||||
let img;
|
let img;
|
||||||
if (image) {
|
if (image) {
|
||||||
img = <div className="mx_LinkPreviewWidget_image" style={{ height: thumbHeight }}>
|
img = <div className="mx_LinkPreviewWidget_image" style={{ height: thumbHeight }}>
|
||||||
<img style={{ maxWidth: imageMaxWidth, maxHeight: imageMaxHeight }} src={image} onClick={this.onImageClick} />
|
<img style={{ maxWidth: imageMaxWidth, maxHeight: imageMaxHeight }} src={image} onClick={this.onImageClick} />
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The description includes &-encoded HTML entities, we decode those as React treats the thing as an
|
// The description includes &-encoded HTML entities, we decode those as React treats the thing as an
|
||||||
|
|
|
@ -53,9 +53,9 @@ export default class PinnedEventTile extends React.Component {
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
pinned.splice(index, 1);
|
pinned.splice(index, 1);
|
||||||
MatrixClientPeg.get().sendStateEvent(this.props.mxRoom.roomId, 'm.room.pinned_events', {pinned}, '')
|
MatrixClientPeg.get().sendStateEvent(this.props.mxRoom.roomId, 'm.room.pinned_events', {pinned}, '')
|
||||||
.then(() => {
|
.then(() => {
|
||||||
if (this.props.onUnpinned) this.props.onUnpinned();
|
if (this.props.onUnpinned) this.props.onUnpinned();
|
||||||
});
|
});
|
||||||
} else if (this.props.onUnpinned) this.props.onUnpinned();
|
} else if (this.props.onUnpinned) this.props.onUnpinned();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -98,8 +98,11 @@ export default class PinnedEventTile extends React.Component {
|
||||||
{ formatFullDate(new Date(this.props.mxEvent.getTs())) }
|
{ formatFullDate(new Date(this.props.mxEvent.getTs())) }
|
||||||
</span>
|
</span>
|
||||||
<div className="mx_PinnedEventTile_message">
|
<div className="mx_PinnedEventTile_message">
|
||||||
<MessageEvent mxEvent={this.props.mxEvent} className="mx_PinnedEventTile_body" maxImageHeight={150}
|
<MessageEvent
|
||||||
onHeightChanged={() => {}} // we need to give this, apparently
|
mxEvent={this.props.mxEvent}
|
||||||
|
className="mx_PinnedEventTile_body"
|
||||||
|
maxImageHeight={150}
|
||||||
|
onHeightChanged={() => {}} // we need to give this, apparently
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -64,10 +64,10 @@ export default class PinnedEventsPanel extends React.Component {
|
||||||
|
|
||||||
pinnedEvents.getContent().pinned.map((eventId) => {
|
pinnedEvents.getContent().pinned.map((eventId) => {
|
||||||
promises.push(cli.getEventTimeline(this.props.room.getUnfilteredTimelineSet(), eventId, 0).then(
|
promises.push(cli.getEventTimeline(this.props.room.getUnfilteredTimelineSet(), eventId, 0).then(
|
||||||
(timeline) => {
|
(timeline) => {
|
||||||
const event = timeline.getEvents().find((e) => e.getId() === eventId);
|
const event = timeline.getEvents().find((e) => e.getId() === eventId);
|
||||||
return {eventId, timeline, event};
|
return {eventId, timeline, event};
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
console.error("Error looking up pinned event " + eventId + " in room " + this.props.room.roomId);
|
console.error("Error looking up pinned event " + eventId + " in room " + this.props.room.roomId);
|
||||||
console.error(err);
|
console.error(err);
|
||||||
return null; // return lack of context to avoid unhandled errors
|
return null; // return lack of context to avoid unhandled errors
|
||||||
|
@ -113,10 +113,14 @@ export default class PinnedEventsPanel extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.state.pinned.map((context) => {
|
return this.state.pinned.map((context) => {
|
||||||
return (<PinnedEventTile key={context.event.getId()}
|
return (
|
||||||
mxRoom={this.props.room}
|
<PinnedEventTile
|
||||||
mxEvent={context.event}
|
key={context.event.getId()}
|
||||||
onUnpinned={this._updatePinnedMessages} />);
|
mxRoom={this.props.room}
|
||||||
|
mxEvent={context.event}
|
||||||
|
onUnpinned={this._updatePinnedMessages}
|
||||||
|
/>
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -188,7 +188,7 @@ export default class ReadReceiptMarker extends React.PureComponent {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NodeAnimator
|
<NodeAnimator
|
||||||
startStyles={this.state.startStyles} >
|
startStyles={this.state.startStyles} >
|
||||||
<MemberAvatar
|
<MemberAvatar
|
||||||
member={this.props.member}
|
member={this.props.member}
|
||||||
fallbackUserId={this.props.fallbackUserId}
|
fallbackUserId={this.props.fallbackUserId}
|
||||||
|
|
|
@ -79,8 +79,13 @@ export default class ReplyPreview extends React.Component {
|
||||||
{ _t('Replying') }
|
{ _t('Replying') }
|
||||||
</div>
|
</div>
|
||||||
<div className="mx_ReplyPreview_header mx_ReplyPreview_cancel">
|
<div className="mx_ReplyPreview_header mx_ReplyPreview_cancel">
|
||||||
<img className="mx_filterFlipColor" src={require("../../../../res/img/cancel.svg")} width="18" height="18"
|
<img
|
||||||
onClick={cancelQuoting} />
|
className="mx_filterFlipColor"
|
||||||
|
src={require("../../../../res/img/cancel.svg")}
|
||||||
|
width="18"
|
||||||
|
height="18"
|
||||||
|
onClick={cancelQuoting}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mx_ReplyPreview_clear" />
|
<div className="mx_ReplyPreview_clear" />
|
||||||
<EventTile
|
<EventTile
|
||||||
|
|
|
@ -88,11 +88,11 @@ export default class RoomDetailRow extends React.Component {
|
||||||
const name = room.name || getDisplayAliasForRoom(room) || _t('Unnamed room');
|
const name = room.name || getDisplayAliasForRoom(room) || _t('Unnamed room');
|
||||||
|
|
||||||
const guestRead = room.worldReadable ? (
|
const guestRead = room.worldReadable ? (
|
||||||
<div className="mx_RoomDirectory_perm">{ _t('World readable') }</div>
|
<div className="mx_RoomDirectory_perm">{ _t('World readable') }</div>
|
||||||
) : <div />;
|
) : <div />;
|
||||||
const guestJoin = room.guestCanJoin ? (
|
const guestJoin = room.guestCanJoin ? (
|
||||||
<div className="mx_RoomDirectory_perm">{ _t('Guests can join') }</div>
|
<div className="mx_RoomDirectory_perm">{ _t('Guests can join') }</div>
|
||||||
) : <div />;
|
) : <div />;
|
||||||
|
|
||||||
const perms = (guestRead || guestJoin) ? (<div className="mx_RoomDirectory_perms">
|
const perms = (guestRead || guestJoin) ? (<div className="mx_RoomDirectory_perms">
|
||||||
{ guestRead }
|
{ guestRead }
|
||||||
|
|
|
@ -266,25 +266,25 @@ export default class Stickerpicker extends React.Component {
|
||||||
width: this.popoverWidth,
|
width: this.popoverWidth,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<PersistedElement persistKey={PERSISTED_ELEMENT_KEY} zIndex={STICKERPICKER_Z_INDEX}>
|
<PersistedElement persistKey={PERSISTED_ELEMENT_KEY} zIndex={STICKERPICKER_Z_INDEX}>
|
||||||
<AppTile
|
<AppTile
|
||||||
app={stickerApp}
|
app={stickerApp}
|
||||||
room={this.props.room}
|
room={this.props.room}
|
||||||
fullWidth={true}
|
fullWidth={true}
|
||||||
userId={MatrixClientPeg.get().credentials.userId}
|
userId={MatrixClientPeg.get().credentials.userId}
|
||||||
creatorUserId={stickerpickerWidget.sender || MatrixClientPeg.get().credentials.userId}
|
creatorUserId={stickerpickerWidget.sender || MatrixClientPeg.get().credentials.userId}
|
||||||
waitForIframeLoad={true}
|
waitForIframeLoad={true}
|
||||||
showMenubar={true}
|
showMenubar={true}
|
||||||
onEditClick={this._launchManageIntegrations}
|
onEditClick={this._launchManageIntegrations}
|
||||||
onDeleteClick={this._removeStickerpickerWidgets}
|
onDeleteClick={this._removeStickerpickerWidgets}
|
||||||
showTitle={false}
|
showTitle={false}
|
||||||
showCancel={false}
|
showCancel={false}
|
||||||
showPopout={false}
|
showPopout={false}
|
||||||
onMinimiseClick={this._onHideStickersClick}
|
onMinimiseClick={this._onHideStickersClick}
|
||||||
handleMinimisePointerEvents={true}
|
handleMinimisePointerEvents={true}
|
||||||
userWidget={true}
|
userWidget={true}
|
||||||
/>
|
/>
|
||||||
</PersistedElement>
|
</PersistedElement>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -154,7 +154,7 @@ export default class ChangeAvatar extends React.Component {
|
||||||
const BaseAvatar = sdk.getComponent("avatars.BaseAvatar");
|
const BaseAvatar = sdk.getComponent("avatars.BaseAvatar");
|
||||||
// XXX: FIXME: once we track in the JS what our own displayname is(!) then use it here rather than ?
|
// XXX: FIXME: once we track in the JS what our own displayname is(!) then use it here rather than ?
|
||||||
avatarImg = <BaseAvatar width={this.props.width} height={this.props.height} resizeMethod='crop'
|
avatarImg = <BaseAvatar width={this.props.width} height={this.props.height} resizeMethod='crop'
|
||||||
name='?' idName={MatrixClientPeg.get().getUserIdLocalpart()} url={this.state.avatarUrl} />;
|
name='?' idName={MatrixClientPeg.get().getUserIdLocalpart()} url={this.state.avatarUrl} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
let uploadSection;
|
let uploadSection;
|
||||||
|
|
|
@ -206,7 +206,7 @@ export default class ChangePassword extends React.Component {
|
||||||
test: ({ value, allowEmpty }) => allowEmpty || !!value,
|
test: ({ value, allowEmpty }) => allowEmpty || !!value,
|
||||||
invalid: () => _t("Passwords can't be empty"),
|
invalid: () => _t("Passwords can't be empty"),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
onChangeNewPassword = (ev) => {
|
onChangeNewPassword = (ev) => {
|
||||||
|
@ -245,7 +245,7 @@ export default class ChangePassword extends React.Component {
|
||||||
},
|
},
|
||||||
invalid: () => _t("Passwords don't match"),
|
invalid: () => _t("Passwords don't match"),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
onClickChange = async (ev) => {
|
onClickChange = async (ev) => {
|
||||||
|
|
|
@ -259,7 +259,7 @@ export default class CrossSigningPanel extends React.PureComponent {
|
||||||
<td>{_t("Homeserver feature support:")}</td>
|
<td>{_t("Homeserver feature support:")}</td>
|
||||||
<td>{homeserverSupportsCrossSigning ? _t("exists") : _t("not found")}</td>
|
<td>{homeserverSupportsCrossSigning ? _t("exists") : _t("not found")}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody></table>
|
</tbody></table>
|
||||||
</details>
|
</details>
|
||||||
{errorSection}
|
{errorSection}
|
||||||
{actionRow}
|
{actionRow}
|
||||||
|
|
|
@ -214,7 +214,7 @@ export default class DevicesPanel extends React.Component {
|
||||||
const deleteButton = this.state.deleting ?
|
const deleteButton = this.state.deleting ?
|
||||||
<Spinner w={22} h={22} /> :
|
<Spinner w={22} h={22} /> :
|
||||||
<AccessibleButton onClick={this._onDeleteClick} kind="danger_sm">
|
<AccessibleButton onClick={this._onDeleteClick} kind="danger_sm">
|
||||||
{ _t("Delete %(count)s sessions", {count: this.state.selectedDevices.length}) }
|
{ _t("Delete %(count)s sessions", {count: this.state.selectedDevices.length})}
|
||||||
</AccessibleButton>;
|
</AccessibleButton>;
|
||||||
|
|
||||||
const classes = classNames(this.props.className, "mx_DevicesPanel");
|
const classes = classNames(this.props.className, "mx_DevicesPanel");
|
||||||
|
|
|
@ -100,7 +100,7 @@ export default class Notifications extends React.Component {
|
||||||
MatrixClientPeg.get().setPushRuleEnabled(
|
MatrixClientPeg.get().setPushRuleEnabled(
|
||||||
'global', self.state.masterPushRule.kind, self.state.masterPushRule.rule_id, !checked,
|
'global', self.state.masterPushRule.kind, self.state.masterPushRule.rule_id, !checked,
|
||||||
).then(function() {
|
).then(function() {
|
||||||
self._refreshFromServer();
|
self._refreshFromServer();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -580,12 +580,12 @@ export default class Notifications extends React.Component {
|
||||||
"vectorRuleId": "_keywords",
|
"vectorRuleId": "_keywords",
|
||||||
"description": (
|
"description": (
|
||||||
<span>
|
<span>
|
||||||
{ _t('Messages containing <span>keywords</span>',
|
{ _t('Messages containing <span>keywords</span>',
|
||||||
{},
|
{},
|
||||||
{ 'span': (sub) =>
|
{ 'span': (sub) =>
|
||||||
<span className="mx_UserNotifSettings_keywords" onClick={ self.onKeywordsClicked }>{sub}</span>,
|
<span className="mx_UserNotifSettings_keywords" onClick={ self.onKeywordsClicked }>{sub}</span>,
|
||||||
},
|
},
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
),
|
),
|
||||||
"vectorState": self.state.vectorContentRules.vectorState,
|
"vectorState": self.state.vectorContentRules.vectorState,
|
||||||
|
@ -743,8 +743,8 @@ export default class Notifications extends React.Component {
|
||||||
|
|
||||||
emailNotificationsRow(address, label) {
|
emailNotificationsRow(address, label) {
|
||||||
return <LabelledToggleSwitch value={this.hasEmailPusher(this.state.pushers, address)}
|
return <LabelledToggleSwitch value={this.hasEmailPusher(this.state.pushers, address)}
|
||||||
onChange={this.onEnableEmailNotificationsChange.bind(this, address)}
|
onChange={this.onEnableEmailNotificationsChange.bind(this, address)}
|
||||||
label={label} key={`emailNotif_${label}`} />;
|
label={label} key={`emailNotif_${label}`} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -757,8 +757,8 @@ export default class Notifications extends React.Component {
|
||||||
let masterPushRuleDiv;
|
let masterPushRuleDiv;
|
||||||
if (this.state.masterPushRule) {
|
if (this.state.masterPushRule) {
|
||||||
masterPushRuleDiv = <LabelledToggleSwitch value={!this.state.masterPushRule.enabled}
|
masterPushRuleDiv = <LabelledToggleSwitch value={!this.state.masterPushRule.enabled}
|
||||||
onChange={this.onEnableNotificationsChange}
|
onChange={this.onEnableNotificationsChange}
|
||||||
label={_t('Enable notifications for this account')} />;
|
label={_t('Enable notifications for this account')} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
let clearNotificationsButton;
|
let clearNotificationsButton;
|
||||||
|
@ -874,16 +874,16 @@ export default class Notifications extends React.Component {
|
||||||
{ spinner }
|
{ spinner }
|
||||||
|
|
||||||
<LabelledToggleSwitch value={SettingsStore.getValue("notificationsEnabled")}
|
<LabelledToggleSwitch value={SettingsStore.getValue("notificationsEnabled")}
|
||||||
onChange={this.onEnableDesktopNotificationsChange}
|
onChange={this.onEnableDesktopNotificationsChange}
|
||||||
label={_t('Enable desktop notifications for this session')} />
|
label={_t('Enable desktop notifications for this session')} />
|
||||||
|
|
||||||
<LabelledToggleSwitch value={SettingsStore.getValue("notificationBodyEnabled")}
|
<LabelledToggleSwitch value={SettingsStore.getValue("notificationBodyEnabled")}
|
||||||
onChange={this.onEnableDesktopNotificationBodyChange}
|
onChange={this.onEnableDesktopNotificationBodyChange}
|
||||||
label={_t('Show message in desktop notification')} />
|
label={_t('Show message in desktop notification')} />
|
||||||
|
|
||||||
<LabelledToggleSwitch value={SettingsStore.getValue("audioNotificationsEnabled")}
|
<LabelledToggleSwitch value={SettingsStore.getValue("audioNotificationsEnabled")}
|
||||||
onChange={this.onEnableAudioNotificationsChange}
|
onChange={this.onEnableAudioNotificationsChange}
|
||||||
label={_t('Enable audible notifications for this session')} />
|
label={_t('Enable audible notifications for this session')} />
|
||||||
|
|
||||||
{ emailNotificationsRows }
|
{ emailNotificationsRows }
|
||||||
|
|
||||||
|
|
|
@ -170,8 +170,12 @@ export default class ProfileSettings extends React.Component {
|
||||||
noValidate={true}
|
noValidate={true}
|
||||||
className="mx_ProfileSettings_profileForm"
|
className="mx_ProfileSettings_profileForm"
|
||||||
>
|
>
|
||||||
<input type="file" ref={this._avatarUpload} className="mx_ProfileSettings_avatarUpload"
|
<input
|
||||||
onChange={this._onAvatarChanged} accept="image/*" />
|
type="file"
|
||||||
|
ref={this._avatarUpload} className="mx_ProfileSettings_avatarUpload"
|
||||||
|
onChange={this._onAvatarChanged}
|
||||||
|
accept="image/*"
|
||||||
|
/>
|
||||||
<div className="mx_ProfileSettings_profile">
|
<div className="mx_ProfileSettings_profile">
|
||||||
<div className="mx_ProfileSettings_controls">
|
<div className="mx_ProfileSettings_controls">
|
||||||
<span className="mx_SettingsTab_subheading">{_t("Profile")}</span>
|
<span className="mx_SettingsTab_subheading">{_t("Profile")}</span>
|
||||||
|
|
|
@ -90,12 +90,18 @@ export class ExistingEmailAddress extends React.Component {
|
||||||
<span className="mx_ExistingEmailAddress_promptText">
|
<span className="mx_ExistingEmailAddress_promptText">
|
||||||
{_t("Remove %(email)s?", {email: this.props.email.address} )}
|
{_t("Remove %(email)s?", {email: this.props.email.address} )}
|
||||||
</span>
|
</span>
|
||||||
<AccessibleButton onClick={this._onActuallyRemove} kind="danger_sm"
|
<AccessibleButton
|
||||||
className="mx_ExistingEmailAddress_confirmBtn">
|
onClick={this._onActuallyRemove}
|
||||||
|
kind="danger_sm"
|
||||||
|
className="mx_ExistingEmailAddress_confirmBtn"
|
||||||
|
>
|
||||||
{_t("Remove")}
|
{_t("Remove")}
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
<AccessibleButton onClick={this._onDontRemove} kind="link_sm"
|
<AccessibleButton
|
||||||
className="mx_ExistingEmailAddress_confirmBtn">
|
onClick={this._onDontRemove}
|
||||||
|
kind="link_sm"
|
||||||
|
className="mx_ExistingEmailAddress_confirmBtn"
|
||||||
|
>
|
||||||
{_t("Cancel")}
|
{_t("Cancel")}
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
</div>
|
</div>
|
||||||
|
@ -228,21 +234,28 @@ export default class EmailAddresses extends React.Component {
|
||||||
);
|
);
|
||||||
if (this.state.verifying) {
|
if (this.state.verifying) {
|
||||||
addButton = (
|
addButton = (
|
||||||
<div>
|
<div>
|
||||||
<div>{_t("We've sent you an email to verify your address. Please follow the instructions there and then click the button below.")}</div>
|
<div>{_t("We've sent you an email to verify your address. Please follow the instructions there and then click the button below.")}</div>
|
||||||
<AccessibleButton onClick={this._onContinueClick} kind="primary"
|
<AccessibleButton
|
||||||
disabled={this.state.continueDisabled}>
|
onClick={this._onContinueClick}
|
||||||
{_t("Continue")}
|
kind="primary"
|
||||||
</AccessibleButton>
|
disabled={this.state.continueDisabled}
|
||||||
</div>
|
>
|
||||||
|
{_t("Continue")}
|
||||||
|
</AccessibleButton>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx_EmailAddresses">
|
<div className="mx_EmailAddresses">
|
||||||
{existingEmailElements}
|
{existingEmailElements}
|
||||||
<form onSubmit={this._onAddClick} autoComplete="off"
|
<form
|
||||||
noValidate={true} className="mx_EmailAddresses_new">
|
onSubmit={this._onAddClick}
|
||||||
|
autoComplete="off"
|
||||||
|
noValidate={true}
|
||||||
|
className="mx_EmailAddresses_new"
|
||||||
|
>
|
||||||
<Field
|
<Field
|
||||||
type="text"
|
type="text"
|
||||||
label={_t("Email Address")}
|
label={_t("Email Address")}
|
||||||
|
|
|
@ -85,12 +85,18 @@ export class ExistingPhoneNumber extends React.Component {
|
||||||
<span className="mx_ExistingPhoneNumber_promptText">
|
<span className="mx_ExistingPhoneNumber_promptText">
|
||||||
{_t("Remove %(phone)s?", {phone: this.props.msisdn.address})}
|
{_t("Remove %(phone)s?", {phone: this.props.msisdn.address})}
|
||||||
</span>
|
</span>
|
||||||
<AccessibleButton onClick={this._onActuallyRemove} kind="danger_sm"
|
<AccessibleButton
|
||||||
className="mx_ExistingPhoneNumber_confirmBtn">
|
onClick={this._onActuallyRemove}
|
||||||
|
kind="danger_sm"
|
||||||
|
className="mx_ExistingPhoneNumber_confirmBtn"
|
||||||
|
>
|
||||||
{_t("Remove")}
|
{_t("Remove")}
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
<AccessibleButton onClick={this._onDontRemove} kind="link_sm"
|
<AccessibleButton
|
||||||
className="mx_ExistingPhoneNumber_confirmBtn">
|
onClick={this._onDontRemove}
|
||||||
|
kind="link_sm"
|
||||||
|
className="mx_ExistingPhoneNumber_confirmBtn"
|
||||||
|
>
|
||||||
{_t("Cancel")}
|
{_t("Cancel")}
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
</div>
|
</div>
|
||||||
|
@ -246,8 +252,11 @@ export default class PhoneNumbers extends React.Component {
|
||||||
value={this.state.newPhoneNumberCode}
|
value={this.state.newPhoneNumberCode}
|
||||||
onChange={this._onChangeNewPhoneNumberCode}
|
onChange={this._onChangeNewPhoneNumberCode}
|
||||||
/>
|
/>
|
||||||
<AccessibleButton onClick={this._onContinueClick} kind="primary"
|
<AccessibleButton
|
||||||
disabled={this.state.continueDisabled}>
|
onClick={this._onContinueClick}
|
||||||
|
kind="primary"
|
||||||
|
disabled={this.state.continueDisabled}
|
||||||
|
>
|
||||||
{_t("Continue")}
|
{_t("Continue")}
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -80,9 +80,11 @@ export default class GeneralRoomSettingsTab extends React.Component {
|
||||||
flairSection = <>
|
flairSection = <>
|
||||||
<span className='mx_SettingsTab_subheading'>{_t("Flair")}</span>
|
<span className='mx_SettingsTab_subheading'>{_t("Flair")}</span>
|
||||||
<div className='mx_SettingsTab_section mx_SettingsTab_subsectionText'>
|
<div className='mx_SettingsTab_section mx_SettingsTab_subsectionText'>
|
||||||
<RelatedGroupSettings roomId={room.roomId}
|
<RelatedGroupSettings
|
||||||
canSetRelatedGroups={canChangeGroups}
|
roomId={room.roomId}
|
||||||
relatedGroupsEvent={groupsEvent} />
|
canSetRelatedGroups={canChangeGroups}
|
||||||
|
relatedGroupsEvent={groupsEvent}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</>;
|
</>;
|
||||||
}
|
}
|
||||||
|
@ -97,8 +99,8 @@ export default class GeneralRoomSettingsTab extends React.Component {
|
||||||
<div className="mx_SettingsTab_heading">{_t("Room Addresses")}</div>
|
<div className="mx_SettingsTab_heading">{_t("Room Addresses")}</div>
|
||||||
<div className='mx_SettingsTab_section mx_SettingsTab_subsectionText'>
|
<div className='mx_SettingsTab_section mx_SettingsTab_subsectionText'>
|
||||||
<AliasSettings roomId={this.props.roomId}
|
<AliasSettings roomId={this.props.roomId}
|
||||||
canSetCanonicalAlias={canSetCanonical} canSetAliases={canSetAliases}
|
canSetCanonicalAlias={canSetCanonical} canSetAliases={canSetAliases}
|
||||||
canonicalAliasEvent={canonicalAliasEv} aliasEvents={aliasEvents} />
|
canonicalAliasEvent={canonicalAliasEv} aliasEvents={aliasEvents} />
|
||||||
</div>
|
</div>
|
||||||
<div className="mx_SettingsTab_heading">{_t("Other")}</div>
|
<div className="mx_SettingsTab_heading">{_t("Other")}</div>
|
||||||
{ flairSection }
|
{ flairSection }
|
||||||
|
|
|
@ -155,7 +155,7 @@ export default class NotificationsSettingsTab extends React.Component {
|
||||||
<div>
|
<div>
|
||||||
<span>{_t("Notification sound")}: <code>{this.state.currentSound}</code></span><br />
|
<span>{_t("Notification sound")}: <code>{this.state.currentSound}</code></span><br />
|
||||||
<AccessibleButton className="mx_NotificationSound_resetSound" disabled={this.state.currentSound == "default"} onClick={this._clearSound.bind(this)} kind="primary">
|
<AccessibleButton className="mx_NotificationSound_resetSound" disabled={this.state.currentSound == "default"} onClick={this._clearSound.bind(this)} kind="primary">
|
||||||
{_t("Reset")}
|
{_t("Reset")}
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
@ -167,11 +167,11 @@ export default class NotificationsSettingsTab extends React.Component {
|
||||||
{currentUploadedFile}
|
{currentUploadedFile}
|
||||||
|
|
||||||
<AccessibleButton className="mx_NotificationSound_browse" onClick={this._triggerUploader.bind(this)} kind="primary">
|
<AccessibleButton className="mx_NotificationSound_browse" onClick={this._triggerUploader.bind(this)} kind="primary">
|
||||||
{_t("Browse")}
|
{_t("Browse")}
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
|
|
||||||
<AccessibleButton className="mx_NotificationSound_save" disabled={this.state.uploadedFile == null} onClick={this._onClickSaveSound.bind(this)} kind="primary">
|
<AccessibleButton className="mx_NotificationSound_save" disabled={this.state.uploadedFile == null} onClick={this._onClickSaveSound.bind(this)} kind="primary">
|
||||||
{_t("Save")}
|
{_t("Save")}
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
<br />
|
<br />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -319,8 +319,11 @@ export default class GeneralUserSettingsTab extends React.Component {
|
||||||
return (
|
return (
|
||||||
<div className="mx_SettingsTab_section">
|
<div className="mx_SettingsTab_section">
|
||||||
<span className="mx_SettingsTab_subheading">{_t("Language and region")}</span>
|
<span className="mx_SettingsTab_subheading">{_t("Language and region")}</span>
|
||||||
<LanguageDropdown className="mx_GeneralUserSettingsTab_languageInput"
|
<LanguageDropdown
|
||||||
onOptionChange={this._onLanguageChange} value={this.state.language} />
|
className="mx_GeneralUserSettingsTab_languageInput"
|
||||||
|
onOptionChange={this._onLanguageChange}
|
||||||
|
value={this.state.language}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -329,8 +332,10 @@ export default class GeneralUserSettingsTab extends React.Component {
|
||||||
return (
|
return (
|
||||||
<div className="mx_SettingsTab_section">
|
<div className="mx_SettingsTab_section">
|
||||||
<span className="mx_SettingsTab_subheading">{_t("Spell check dictionaries")}</span>
|
<span className="mx_SettingsTab_subheading">{_t("Spell check dictionaries")}</span>
|
||||||
<SpellCheckSettings languages={this.state.spellCheckLanguages}
|
<SpellCheckSettings
|
||||||
onLanguagesChange={this._onSpellCheckLanguagesChange} />
|
languages={this.state.spellCheckLanguages}
|
||||||
|
onLanguagesChange={this._onSpellCheckLanguagesChange}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -257,13 +257,12 @@ export default class SecurityUserSettingsTab extends React.Component {
|
||||||
|
|
||||||
if (!ignoredUserIds || ignoredUserIds.length === 0) return null;
|
if (!ignoredUserIds || ignoredUserIds.length === 0) return null;
|
||||||
|
|
||||||
const userIds = ignoredUserIds
|
const userIds = ignoredUserIds.map((u) => <IgnoredUser
|
||||||
.map((u) => <IgnoredUser
|
userId={u}
|
||||||
userId={u}
|
onUnignored={this._onUserUnignored}
|
||||||
onUnignored={this._onUserUnignored}
|
key={u}
|
||||||
key={u}
|
inProgress={waitingUnignored.includes(u)}
|
||||||
inProgress={waitingUnignored.includes(u)}
|
/>);
|
||||||
/>);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='mx_SettingsTab_section'>
|
<div className='mx_SettingsTab_section'>
|
||||||
|
|
|
@ -176,8 +176,8 @@ export default class VoiceUserSettingsTab extends React.Component {
|
||||||
const defaultDevice = getDefaultDevice(audioOutputs);
|
const defaultDevice = getDefaultDevice(audioOutputs);
|
||||||
speakerDropdown = (
|
speakerDropdown = (
|
||||||
<Field element="select" label={_t("Audio Output")}
|
<Field element="select" label={_t("Audio Output")}
|
||||||
value={this.state.activeAudioOutput || defaultDevice}
|
value={this.state.activeAudioOutput || defaultDevice}
|
||||||
onChange={this._setAudioOutput}>
|
onChange={this._setAudioOutput}>
|
||||||
{this._renderDeviceOptions(audioOutputs, 'audioOutput')}
|
{this._renderDeviceOptions(audioOutputs, 'audioOutput')}
|
||||||
</Field>
|
</Field>
|
||||||
);
|
);
|
||||||
|
@ -188,8 +188,8 @@ export default class VoiceUserSettingsTab extends React.Component {
|
||||||
const defaultDevice = getDefaultDevice(audioInputs);
|
const defaultDevice = getDefaultDevice(audioInputs);
|
||||||
microphoneDropdown = (
|
microphoneDropdown = (
|
||||||
<Field element="select" label={_t("Microphone")}
|
<Field element="select" label={_t("Microphone")}
|
||||||
value={this.state.activeAudioInput || defaultDevice}
|
value={this.state.activeAudioInput || defaultDevice}
|
||||||
onChange={this._setAudioInput}>
|
onChange={this._setAudioInput}>
|
||||||
{this._renderDeviceOptions(audioInputs, 'audioInput')}
|
{this._renderDeviceOptions(audioInputs, 'audioInput')}
|
||||||
</Field>
|
</Field>
|
||||||
);
|
);
|
||||||
|
@ -200,8 +200,8 @@ export default class VoiceUserSettingsTab extends React.Component {
|
||||||
const defaultDevice = getDefaultDevice(videoInputs);
|
const defaultDevice = getDefaultDevice(videoInputs);
|
||||||
webcamDropdown = (
|
webcamDropdown = (
|
||||||
<Field element="select" label={_t("Camera")}
|
<Field element="select" label={_t("Camera")}
|
||||||
value={this.state.activeVideoInput || defaultDevice}
|
value={this.state.activeVideoInput || defaultDevice}
|
||||||
onChange={this._setVideoInput}>
|
onChange={this._setVideoInput}>
|
||||||
{this._renderDeviceOptions(videoInputs, 'videoInput')}
|
{this._renderDeviceOptions(videoInputs, 'videoInput')}
|
||||||
</Field>
|
</Field>
|
||||||
);
|
);
|
||||||
|
|
|
@ -29,14 +29,14 @@ export default class VerificationCancelled extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
||||||
return <div>
|
return <div>
|
||||||
<p>{_t(
|
<p>{_t(
|
||||||
"The other party cancelled the verification.",
|
"The other party cancelled the verification.",
|
||||||
)}</p>
|
)}</p>
|
||||||
<DialogButtons
|
<DialogButtons
|
||||||
primaryButton={_t('OK')}
|
primaryButton={_t('OK')}
|
||||||
hasCancel={false}
|
hasCancel={false}
|
||||||
onPrimaryButtonClick={this.props.onDone}
|
onPrimaryButtonClick={this.props.onDone}
|
||||||
/>
|
/>
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,8 +127,13 @@ export default class EventIndex extends EventEmitter {
|
||||||
this.crawlerCheckpoints.push(forwardCheckpoint);
|
this.crawlerCheckpoints.push(forwardCheckpoint);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("EventIndex: Error adding initial checkpoints for room",
|
console.log(
|
||||||
room.roomId, backCheckpoint, forwardCheckpoint, e);
|
"EventIndex: Error adding initial checkpoints for room",
|
||||||
|
room.roomId,
|
||||||
|
backCheckpoint,
|
||||||
|
forwardCheckpoint,
|
||||||
|
e,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -379,8 +384,12 @@ export default class EventIndex extends EventEmitter {
|
||||||
try {
|
try {
|
||||||
await indexManager.addCrawlerCheckpoint(checkpoint);
|
await indexManager.addCrawlerCheckpoint(checkpoint);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("EventIndex: Error adding new checkpoint for room",
|
console.log(
|
||||||
room.roomId, checkpoint, e);
|
"EventIndex: Error adding new checkpoint for room",
|
||||||
|
room.roomId,
|
||||||
|
checkpoint,
|
||||||
|
e,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.crawlerCheckpoints.push(checkpoint);
|
this.crawlerCheckpoints.push(checkpoint);
|
||||||
|
@ -459,7 +468,7 @@ export default class EventIndex extends EventEmitter {
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.httpStatus === 403) {
|
if (e.httpStatus === 403) {
|
||||||
console.log("EventIndex: Removing checkpoint as we don't have ",
|
console.log("EventIndex: Removing checkpoint as we don't have ",
|
||||||
"permissions to fetch messages from this room.", checkpoint);
|
"permissions to fetch messages from this room.", checkpoint);
|
||||||
try {
|
try {
|
||||||
await indexManager.removeCrawlerCheckpoint(checkpoint);
|
await indexManager.removeCrawlerCheckpoint(checkpoint);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -589,7 +598,7 @@ export default class EventIndex extends EventEmitter {
|
||||||
// to do here anymore.
|
// to do here anymore.
|
||||||
if (!newCheckpoint) {
|
if (!newCheckpoint) {
|
||||||
console.log("EventIndex: The server didn't return a valid ",
|
console.log("EventIndex: The server didn't return a valid ",
|
||||||
"new checkpoint, not continuing the crawl.", checkpoint);
|
"new checkpoint, not continuing the crawl.", checkpoint);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -599,12 +608,12 @@ export default class EventIndex extends EventEmitter {
|
||||||
// the new checkpoint to be used by the crawler.
|
// the new checkpoint to be used by the crawler.
|
||||||
if (eventsAlreadyAdded === true && newCheckpoint.fullCrawl !== true) {
|
if (eventsAlreadyAdded === true && newCheckpoint.fullCrawl !== true) {
|
||||||
console.log("EventIndex: Checkpoint had already all events",
|
console.log("EventIndex: Checkpoint had already all events",
|
||||||
"added, stopping the crawl", checkpoint);
|
"added, stopping the crawl", checkpoint);
|
||||||
await indexManager.removeCrawlerCheckpoint(newCheckpoint);
|
await indexManager.removeCrawlerCheckpoint(newCheckpoint);
|
||||||
} else {
|
} else {
|
||||||
if (eventsAlreadyAdded === true) {
|
if (eventsAlreadyAdded === true) {
|
||||||
console.log("EventIndex: Checkpoint had already all events",
|
console.log("EventIndex: Checkpoint had already all events",
|
||||||
"added, but continuing due to a full crawl", checkpoint);
|
"added, but continuing due to a full crawl", checkpoint);
|
||||||
}
|
}
|
||||||
this.crawlerCheckpoints.push(newCheckpoint);
|
this.crawlerCheckpoints.push(newCheckpoint);
|
||||||
}
|
}
|
||||||
|
@ -777,7 +786,7 @@ export default class EventIndex extends EventEmitter {
|
||||||
* timeline, false otherwise.
|
* timeline, false otherwise.
|
||||||
*/
|
*/
|
||||||
async populateFileTimeline(timelineSet, timeline, room, limit = 10,
|
async populateFileTimeline(timelineSet, timeline, room, limit = 10,
|
||||||
fromEvent = null, direction = EventTimeline.BACKWARDS) {
|
fromEvent = null, direction = EventTimeline.BACKWARDS) {
|
||||||
const matrixEvents = await this.loadFileEvents(room, limit, fromEvent, direction);
|
const matrixEvents = await this.loadFileEvents(room, limit, fromEvent, direction);
|
||||||
|
|
||||||
// If this is a normal fill request, not a pagination request, we need
|
// If this is a normal fill request, not a pagination request, we need
|
||||||
|
@ -807,7 +816,7 @@ export default class EventIndex extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("EventIndex: Populating file panel with", matrixEvents.length,
|
console.log("EventIndex: Populating file panel with", matrixEvents.length,
|
||||||
"events and setting the pagination token to", paginationToken);
|
"events and setting the pagination token to", paginationToken);
|
||||||
|
|
||||||
timeline.setPaginationToken(paginationToken, EventTimeline.BACKWARDS);
|
timeline.setPaginationToken(paginationToken, EventTimeline.BACKWARDS);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -125,14 +125,14 @@ class CustomRoomTagStore extends EventEmitter {
|
||||||
this._setState({tags});
|
this._setState({tags});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'on_client_not_viable':
|
case 'on_client_not_viable':
|
||||||
case 'on_logged_out': {
|
case 'on_logged_out': {
|
||||||
// we assume to always have a tags object in the state
|
// we assume to always have a tags object in the state
|
||||||
this._state = {tags: {}};
|
this._state = {tags: {}};
|
||||||
RoomListStore.instance.off(LISTS_UPDATE_EVENT, this._onListsUpdated);
|
RoomListStore.instance.off(LISTS_UPDATE_EVENT, this._onListsUpdated);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -168,7 +168,7 @@ class GroupFilterOrderStore extends Store {
|
||||||
|
|
||||||
Analytics.trackEvent('FilterStore', 'select_tag');
|
Analytics.trackEvent('FilterStore', 'select_tag');
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'deselect_tags':
|
case 'deselect_tags':
|
||||||
if (payload.tag) {
|
if (payload.tag) {
|
||||||
// if a tag is passed, only deselect that tag
|
// if a tag is passed, only deselect that tag
|
||||||
|
@ -181,7 +181,7 @@ class GroupFilterOrderStore extends Store {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Analytics.trackEvent('FilterStore', 'deselect_tags');
|
Analytics.trackEvent('FilterStore', 'deselect_tags');
|
||||||
break;
|
break;
|
||||||
case 'on_client_not_viable':
|
case 'on_client_not_viable':
|
||||||
case 'on_logged_out': {
|
case 'on_logged_out': {
|
||||||
// Reset state without pushing an update to the view, which generally assumes that
|
// Reset state without pushing an update to the view, which generally assumes that
|
||||||
|
@ -207,8 +207,8 @@ class GroupFilterOrderStore extends Store {
|
||||||
groupIds.forEach(groupId => {
|
groupIds.forEach(groupId => {
|
||||||
const rooms =
|
const rooms =
|
||||||
GroupStore.getGroupRooms(groupId)
|
GroupStore.getGroupRooms(groupId)
|
||||||
.map(r => client.getRoom(r.roomId)) // to Room objects
|
.map(r => client.getRoom(r.roomId)) // to Room objects
|
||||||
.filter(r => r !== null && r !== undefined); // filter out rooms we haven't joined from the group
|
.filter(r => r !== null && r !== undefined); // filter out rooms we haven't joined from the group
|
||||||
const badge = rooms && RoomNotifs.aggregateNotificationCount(rooms);
|
const badge = rooms && RoomNotifs.aggregateNotificationCount(rooms);
|
||||||
changedBadges[groupId] = (badge && badge.count !== 0) ? badge : undefined;
|
changedBadges[groupId] = (badge && badge.count !== 0) ? badge : undefined;
|
||||||
});
|
});
|
||||||
|
|
|
@ -311,7 +311,7 @@ function unpackMegolmKeyFile(data) {
|
||||||
while (1) {
|
while (1) {
|
||||||
const lineEnd = fileStr.indexOf('\n', lineStart);
|
const lineEnd = fileStr.indexOf('\n', lineStart);
|
||||||
const line = fileStr.slice(lineStart, lineEnd < 0 ? undefined : lineEnd)
|
const line = fileStr.slice(lineStart, lineEnd < 0 ? undefined : lineEnd)
|
||||||
.trim();
|
.trim();
|
||||||
if (line === TRAILER_LINE) {
|
if (line === TRAILER_LINE) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -177,7 +177,7 @@ describe('QueryMatcher', function() {
|
||||||
const qm = new QueryMatcher(NONWORDOBJECTS, {
|
const qm = new QueryMatcher(NONWORDOBJECTS, {
|
||||||
keys: ["name"],
|
keys: ["name"],
|
||||||
shouldMatchWordsOnly: false,
|
shouldMatchWordsOnly: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const results = qm.match('bob');
|
const results = qm.match('bob');
|
||||||
expect(results.length).toBe(1);
|
expect(results.length).toBe(1);
|
||||||
|
|
|
@ -26,9 +26,9 @@ describe("AccessSecretStorageDialog", function() {
|
||||||
it("Closes the dialog if _onRecoveryKeyNext is called with a valid key", (done) => {
|
it("Closes the dialog if _onRecoveryKeyNext is called with a valid key", (done) => {
|
||||||
const testInstance = TestRenderer.create(
|
const testInstance = TestRenderer.create(
|
||||||
<AccessSecretStorageDialog
|
<AccessSecretStorageDialog
|
||||||
checkPrivateKey={(p) => p && p.recoveryKey && p.recoveryKey == "a"}
|
checkPrivateKey={(p) => p && p.recoveryKey && p.recoveryKey == "a"}
|
||||||
onFinished={(v) => {
|
onFinished={(v) => {
|
||||||
if (v) { done(); }
|
if (v) { done(); }
|
||||||
}}
|
}}
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
|
@ -43,7 +43,7 @@ describe("AccessSecretStorageDialog", function() {
|
||||||
it("Considers a valid key to be valid", async function() {
|
it("Considers a valid key to be valid", async function() {
|
||||||
const testInstance = TestRenderer.create(
|
const testInstance = TestRenderer.create(
|
||||||
<AccessSecretStorageDialog
|
<AccessSecretStorageDialog
|
||||||
checkPrivateKey={() => true}
|
checkPrivateKey={() => true}
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
const v = "asdf";
|
const v = "asdf";
|
||||||
|
@ -61,7 +61,7 @@ describe("AccessSecretStorageDialog", function() {
|
||||||
it("Notifies the user if they input an invalid Security Key", async function(done) {
|
it("Notifies the user if they input an invalid Security Key", async function(done) {
|
||||||
const testInstance = TestRenderer.create(
|
const testInstance = TestRenderer.create(
|
||||||
<AccessSecretStorageDialog
|
<AccessSecretStorageDialog
|
||||||
checkPrivateKey={async () => false}
|
checkPrivateKey={async () => false}
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
const e = { target: { value: "a" } };
|
const e = { target: { value: "a" } };
|
||||||
|
@ -87,12 +87,14 @@ describe("AccessSecretStorageDialog", function() {
|
||||||
it("Notifies the user if they input an invalid passphrase", async function(done) {
|
it("Notifies the user if they input an invalid passphrase", async function(done) {
|
||||||
const testInstance = TestRenderer.create(
|
const testInstance = TestRenderer.create(
|
||||||
<AccessSecretStorageDialog
|
<AccessSecretStorageDialog
|
||||||
checkPrivateKey={() => false}
|
checkPrivateKey={() => false}
|
||||||
onFinished={() => {}}
|
onFinished={() => {}}
|
||||||
keyInfo={ { passphrase: {
|
keyInfo={{
|
||||||
salt: 'nonempty',
|
passphrase: {
|
||||||
iterations: 2,
|
salt: 'nonempty',
|
||||||
} } }
|
iterations: 2,
|
||||||
|
},
|
||||||
|
}}
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
const e = { target: { value: "a" } };
|
const e = { target: { value: "a" } };
|
||||||
|
|
|
@ -246,8 +246,8 @@ describe('MemberEventListSummary', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('truncates multiple sequences of repetitions with other events between',
|
it('truncates multiple sequences of repetitions with other events between',
|
||||||
function() {
|
function() {
|
||||||
const events = generateEvents([
|
const events = generateEvents([
|
||||||
{
|
{
|
||||||
userId: "@user_1:some.domain",
|
userId: "@user_1:some.domain",
|
||||||
prevMembership: "ban",
|
prevMembership: "ban",
|
||||||
|
@ -276,28 +276,29 @@ describe('MemberEventListSummary', function() {
|
||||||
membership: "invite",
|
membership: "invite",
|
||||||
senderId: "@some_other_user:some.domain",
|
senderId: "@some_other_user:some.domain",
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
const props = {
|
const props = {
|
||||||
events: events,
|
events: events,
|
||||||
children: generateTiles(events),
|
children: generateTiles(events),
|
||||||
summaryLength: 1,
|
summaryLength: 1,
|
||||||
avatarsMaxLength: 5,
|
avatarsMaxLength: 5,
|
||||||
threshold: 3,
|
threshold: 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
const instance = ReactTestUtils.renderIntoDocument(
|
const instance = ReactTestUtils.renderIntoDocument(
|
||||||
<MemberEventListSummary {...props} />,
|
<MemberEventListSummary {...props} />,
|
||||||
);
|
);
|
||||||
const summary = ReactTestUtils.findRenderedDOMComponentWithClass(
|
const summary = ReactTestUtils.findRenderedDOMComponentWithClass(
|
||||||
instance, "mx_EventListSummary_summary",
|
instance, "mx_EventListSummary_summary",
|
||||||
);
|
);
|
||||||
const summaryText = summary.textContent;
|
const summaryText = summary.textContent;
|
||||||
|
|
||||||
expect(summaryText).toBe(
|
expect(summaryText).toBe(
|
||||||
"user_1 was unbanned, joined and left 2 times, was banned, " +
|
"user_1 was unbanned, joined and left 2 times, was banned, " +
|
||||||
"joined and left 3 times and was invited",
|
"joined and left 3 times and was invited",
|
||||||
);
|
);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
it('handles multiple users following the same sequence of memberships', function() {
|
it('handles multiple users following the same sequence of memberships', function() {
|
||||||
const events = generateEvents([
|
const events = generateEvents([
|
||||||
|
@ -396,8 +397,8 @@ describe('MemberEventListSummary', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('correctly orders sequences of transitions by the order of their first event',
|
it('correctly orders sequences of transitions by the order of their first event',
|
||||||
function() {
|
function() {
|
||||||
const events = generateEvents([
|
const events = generateEvents([
|
||||||
{
|
{
|
||||||
userId: "@user_2:some.domain",
|
userId: "@user_2:some.domain",
|
||||||
prevMembership: "ban",
|
prevMembership: "ban",
|
||||||
|
@ -424,28 +425,29 @@ describe('MemberEventListSummary', function() {
|
||||||
{userId: "@user_2:some.domain", prevMembership: "join", membership: "leave"},
|
{userId: "@user_2:some.domain", prevMembership: "join", membership: "leave"},
|
||||||
{userId: "@user_2:some.domain", prevMembership: "leave", membership: "join"},
|
{userId: "@user_2:some.domain", prevMembership: "leave", membership: "join"},
|
||||||
{userId: "@user_2:some.domain", prevMembership: "join", membership: "leave"},
|
{userId: "@user_2:some.domain", prevMembership: "join", membership: "leave"},
|
||||||
]);
|
]);
|
||||||
const props = {
|
const props = {
|
||||||
events: events,
|
events: events,
|
||||||
children: generateTiles(events),
|
children: generateTiles(events),
|
||||||
summaryLength: 1,
|
summaryLength: 1,
|
||||||
avatarsMaxLength: 5,
|
avatarsMaxLength: 5,
|
||||||
threshold: 3,
|
threshold: 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
const instance = ReactTestUtils.renderIntoDocument(
|
const instance = ReactTestUtils.renderIntoDocument(
|
||||||
<MemberEventListSummary {...props} />,
|
<MemberEventListSummary {...props} />,
|
||||||
);
|
);
|
||||||
const summary = ReactTestUtils.findRenderedDOMComponentWithClass(
|
const summary = ReactTestUtils.findRenderedDOMComponentWithClass(
|
||||||
instance, "mx_EventListSummary_summary",
|
instance, "mx_EventListSummary_summary",
|
||||||
);
|
);
|
||||||
const summaryText = summary.textContent;
|
const summaryText = summary.textContent;
|
||||||
|
|
||||||
expect(summaryText).toBe(
|
expect(summaryText).toBe(
|
||||||
"user_2 was unbanned and joined and left 2 times, user_1 was unbanned, " +
|
"user_2 was unbanned and joined and left 2 times, user_1 was unbanned, " +
|
||||||
"joined and left 2 times and was banned",
|
"joined and left 2 times and was banned",
|
||||||
);
|
);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
it('correctly identifies transitions', function() {
|
it('correctly identifies transitions', function() {
|
||||||
const events = generateEvents([
|
const events = generateEvents([
|
||||||
|
@ -569,8 +571,8 @@ describe('MemberEventListSummary', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles invitation plurals correctly when there are multiple invites',
|
it('handles invitation plurals correctly when there are multiple invites',
|
||||||
function() {
|
function() {
|
||||||
const events = generateEvents([
|
const events = generateEvents([
|
||||||
{
|
{
|
||||||
userId: "@user_1:some.domain",
|
userId: "@user_1:some.domain",
|
||||||
prevMembership: "invite",
|
prevMembership: "invite",
|
||||||
|
@ -581,27 +583,28 @@ describe('MemberEventListSummary', function() {
|
||||||
prevMembership: "invite",
|
prevMembership: "invite",
|
||||||
membership: "leave",
|
membership: "leave",
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
const props = {
|
const props = {
|
||||||
events: events,
|
events: events,
|
||||||
children: generateTiles(events),
|
children: generateTiles(events),
|
||||||
summaryLength: 1,
|
summaryLength: 1,
|
||||||
avatarsMaxLength: 5,
|
avatarsMaxLength: 5,
|
||||||
threshold: 1, // threshold = 1 to force collapse
|
threshold: 1, // threshold = 1 to force collapse
|
||||||
};
|
};
|
||||||
|
|
||||||
const instance = ReactTestUtils.renderIntoDocument(
|
const instance = ReactTestUtils.renderIntoDocument(
|
||||||
<MemberEventListSummary {...props} />,
|
<MemberEventListSummary {...props} />,
|
||||||
);
|
);
|
||||||
const summary = ReactTestUtils.findRenderedDOMComponentWithClass(
|
const summary = ReactTestUtils.findRenderedDOMComponentWithClass(
|
||||||
instance, "mx_EventListSummary_summary",
|
instance, "mx_EventListSummary_summary",
|
||||||
);
|
);
|
||||||
const summaryText = summary.textContent;
|
const summaryText = summary.textContent;
|
||||||
|
|
||||||
expect(summaryText).toBe(
|
expect(summaryText).toBe(
|
||||||
"user_1 rejected their invitation 2 times",
|
"user_1 rejected their invitation 2 times",
|
||||||
);
|
);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
it('handles a summary length = 2, with no "others"', function() {
|
it('handles a summary length = 2, with no "others"', function() {
|
||||||
const events = generateEvents([
|
const events = generateEvents([
|
||||||
|
|
|
@ -100,7 +100,7 @@ describe('MemberList', () => {
|
||||||
memberList = r;
|
memberList = r;
|
||||||
};
|
};
|
||||||
root = ReactDOM.render(<WrappedMemberList roomId={memberListRoom.roomId}
|
root = ReactDOM.render(<WrappedMemberList roomId={memberListRoom.roomId}
|
||||||
wrappedRef={gatherWrappedRef} />, parentDiv);
|
wrappedRef={gatherWrappedRef} />, parentDiv);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach((done) => {
|
afterEach((done) => {
|
||||||
|
|
|
@ -70,8 +70,9 @@ describe('RoomList', () => {
|
||||||
root = ReactDOM.render(
|
root = ReactDOM.render(
|
||||||
<DragDropContext>
|
<DragDropContext>
|
||||||
<WrappedRoomList searchFilter="" onResize={() => {}} />
|
<WrappedRoomList searchFilter="" onResize={() => {}} />
|
||||||
</DragDropContext>
|
</DragDropContext>,
|
||||||
, parentDiv);
|
parentDiv,
|
||||||
|
);
|
||||||
ReactTestUtils.findRenderedComponentWithType(root, RoomList);
|
ReactTestUtils.findRenderedComponentWithType(root, RoomList);
|
||||||
|
|
||||||
movingRoom = createRoom({name: 'Moving room'});
|
movingRoom = createRoom({name: 'Moving room'});
|
||||||
|
|
|
@ -93,10 +93,10 @@ module.exports = class ElementSession {
|
||||||
const type = req.resourceType();
|
const type = req.resourceType();
|
||||||
const response = await req.response();
|
const response = await req.response();
|
||||||
//if (type === 'xhr' || type === 'fetch') {
|
//if (type === 'xhr' || type === 'fetch') {
|
||||||
buffer += `${type} ${response.status()} ${req.method()} ${req.url()} \n`;
|
buffer += `${type} ${response.status()} ${req.method()} ${req.url()} \n`;
|
||||||
// if (req.method() === "POST") {
|
// if (req.method() === "POST") {
|
||||||
// buffer += " Post data: " + req.postData();
|
// buffer += " Post data: " + req.postData();
|
||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -84,22 +84,22 @@ describe('MegolmExportEncryption', function() {
|
||||||
it('should handle missing header', function() {
|
it('should handle missing header', function() {
|
||||||
const input=stringToArray(`-----`);
|
const input=stringToArray(`-----`);
|
||||||
return MegolmExportEncryption.decryptMegolmKeyFile(input, '')
|
return MegolmExportEncryption.decryptMegolmKeyFile(input, '')
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
throw new Error('expected to throw');
|
throw new Error('expected to throw');
|
||||||
}, (error) => {
|
}, (error) => {
|
||||||
expect(error.message).toEqual('Header line not found');
|
expect(error.message).toEqual('Header line not found');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle missing trailer', function() {
|
it('should handle missing trailer', function() {
|
||||||
const input=stringToArray(`-----BEGIN MEGOLM SESSION DATA-----
|
const input=stringToArray(`-----BEGIN MEGOLM SESSION DATA-----
|
||||||
-----`);
|
-----`);
|
||||||
return MegolmExportEncryption.decryptMegolmKeyFile(input, '')
|
return MegolmExportEncryption.decryptMegolmKeyFile(input, '')
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
throw new Error('expected to throw');
|
throw new Error('expected to throw');
|
||||||
}, (error) => {
|
}, (error) => {
|
||||||
expect(error.message).toEqual('Trailer line not found');
|
expect(error.message).toEqual('Trailer line not found');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle a too-short body', function() {
|
it('should handle a too-short body', function() {
|
||||||
|
@ -109,11 +109,11 @@ cissyYBxjsfsAn
|
||||||
-----END MEGOLM SESSION DATA-----
|
-----END MEGOLM SESSION DATA-----
|
||||||
`);
|
`);
|
||||||
return MegolmExportEncryption.decryptMegolmKeyFile(input, '')
|
return MegolmExportEncryption.decryptMegolmKeyFile(input, '')
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
throw new Error('expected to throw');
|
throw new Error('expected to throw');
|
||||||
}, (error) => {
|
}, (error) => {
|
||||||
expect(error.message).toEqual('Invalid file: too short');
|
expect(error.message).toEqual('Invalid file: too short');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO find a subtlecrypto shim which doesn't break this test
|
// TODO find a subtlecrypto shim which doesn't break this test
|
||||||
|
|
|
@ -26,7 +26,7 @@ describe("mkClient self-test", function() {
|
||||||
["@TF:h", true],
|
["@TF:h", true],
|
||||||
["@FT:h", false],
|
["@FT:h", false],
|
||||||
["@FF:h", false]],
|
["@FF:h", false]],
|
||||||
)("behaves well for user trust %s", (userId, trust) => {
|
)("behaves well for user trust %s", (userId, trust) => {
|
||||||
expect(mkClient().checkUserTrust(userId).isCrossSigningVerified()).toBe(trust);
|
expect(mkClient().checkUserTrust(userId).isCrossSigningVerified()).toBe(trust);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ describe("mkClient self-test", function() {
|
||||||
["@TF:h", false],
|
["@TF:h", false],
|
||||||
["@FT:h", true],
|
["@FT:h", true],
|
||||||
["@FF:h", false]],
|
["@FF:h", false]],
|
||||||
)("behaves well for device trust %s", (userId, trust) => {
|
)("behaves well for device trust %s", (userId, trust) => {
|
||||||
expect(mkClient().checkDeviceTrust(userId, "device").isVerified()).toBe(trust);
|
expect(mkClient().checkDeviceTrust(userId, "device").isVerified()).toBe(trust);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue