Adhere to better eslint rules

This commit is contained in:
Michael Telatynski 2021-07-23 10:23:45 +01:00
parent 88884bbaad
commit f5630acea7
92 changed files with 710 additions and 348 deletions

View file

@ -51,10 +51,15 @@ export async function startAnyRegistrationFlow(options) {
description: _t("Use your account or create a new one to continue."), description: _t("Use your account or create a new one to continue."),
button: _t("Create Account"), button: _t("Create Account"),
extraButtons: [ extraButtons: [
<button key="start_login" onClick={() => { <button
key="start_login"
onClick={() => {
modal.close(); modal.close();
dis.dispatch({ action: 'start_login', screenAfterLogin: options.screen_after }); dis.dispatch({ action: 'start_login', screenAfterLogin: options.screen_after });
}}>{ _t('Sign In') }</button>, }}
>
{ _t('Sign In') }
</button>,
], ],
onFinished: (proceed) => { onFinished: (proceed) => {
if (proceed) { if (proceed) {

View file

@ -269,7 +269,7 @@ export default class CreateKeyBackupDialog extends React.PureComponent {
<details> <details>
<summary>{ _t("Advanced") }</summary> <summary>{ _t("Advanced") }</summary>
<AccessibleButton kind='primary' onClick={this._onSkipPassPhraseClick} > <AccessibleButton kind='primary' onClick={this._onSkipPassPhraseClick}>
{ _t("Set up with a Security Key") } { _t("Set up with a Security Key") }
</AccessibleButton> </AccessibleButton>
</details> </details>

View file

@ -474,7 +474,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
outlined outlined
> >
<div className="mx_CreateSecretStorageDialog_optionTitle"> <div className="mx_CreateSecretStorageDialog_optionTitle">
<span className="mx_CreateSecretStorageDialog_optionIcon mx_CreateSecretStorageDialog_optionIcon_secureBackup"></span> <span className="mx_CreateSecretStorageDialog_optionIcon mx_CreateSecretStorageDialog_optionIcon_secureBackup" />
{ _t("Generate a Security Key") } { _t("Generate a Security Key") }
</div> </div>
<div>{ _t("Well generate a Security Key for you to store somewhere safe, like a password manager or a safe.") }</div> <div>{ _t("Well generate a Security Key for you to store somewhere safe, like a password manager or a safe.") }</div>
@ -493,7 +493,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
outlined outlined
> >
<div className="mx_CreateSecretStorageDialog_optionTitle"> <div className="mx_CreateSecretStorageDialog_optionTitle">
<span className="mx_CreateSecretStorageDialog_optionIcon mx_CreateSecretStorageDialog_optionIcon_securePhrase"></span> <span className="mx_CreateSecretStorageDialog_optionIcon mx_CreateSecretStorageDialog_optionIcon_securePhrase" />
{ _t("Enter a Security Phrase") } { _t("Enter a Security Phrase") }
</div> </div>
<div>{ _t("Use a secret phrase only you know, and optionally save a Security Key to use for backup.") }</div> <div>{ _t("Use a secret phrase only you know, and optionally save a Security Key to use for backup.") }</div>
@ -701,7 +701,8 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
<code ref={this._collectRecoveryKeyNode}>{ this._recoveryKey.encodedPrivateKey }</code> <code ref={this._collectRecoveryKeyNode}>{ this._recoveryKey.encodedPrivateKey }</code>
</div> </div>
<div className="mx_CreateSecretStorageDialog_recoveryKeyButtons"> <div className="mx_CreateSecretStorageDialog_recoveryKeyButtons">
<AccessibleButton kind='primary' className="mx_Dialog_primary" <AccessibleButton kind='primary'
className="mx_Dialog_primary"
onClick={this._onDownloadClick} onClick={this._onDownloadClick}
disabled={this.state.phase === PHASE_STORING} disabled={this.state.phase === PHASE_STORING}
> >

View file

@ -148,8 +148,12 @@ export default class ExportE2eKeysDialog extends React.Component {
</label> </label>
</div> </div>
<div className='mx_E2eKeysDialog_inputCell'> <div className='mx_E2eKeysDialog_inputCell'>
<input ref={this._passphrase1} id='passphrase1' <input
autoFocus={true} size='64' type='password' ref={this._passphrase1}
id='passphrase1'
autoFocus={true}
size='64'
type='password'
disabled={disableForm} disabled={disableForm}
/> />
</div> </div>
@ -161,8 +165,10 @@ export default class ExportE2eKeysDialog extends React.Component {
</label> </label>
</div> </div>
<div className='mx_E2eKeysDialog_inputCell'> <div className='mx_E2eKeysDialog_inputCell'>
<input ref={this._passphrase2} id='passphrase2' <input ref={this._passphrase2}
size='64' type='password' id='passphrase2'
size='64'
type='password'
disabled={disableForm} disabled={disableForm}
/> />
</div> </div>

View file

@ -174,7 +174,10 @@ export default class ImportE2eKeysDialog 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('Import')} <input
className='mx_Dialog_primary'
type='submit'
value={_t('Import')}
disabled={!this.state.enableSubmit || disableForm} disabled={!this.state.enableSubmit || disableForm}
/> />
<button onClick={this._onCancelClick} disabled={disableForm}> <button onClick={this._onCancelClick} disabled={disableForm}>

View file

@ -120,8 +120,7 @@ export default class EmbeddedPage extends React.PureComponent {
const content = <div className={`${className}_body`} const content = <div className={`${className}_body`}
dangerouslySetInnerHTML={{ __html: this.state.page }} dangerouslySetInnerHTML={{ __html: this.state.page }}
> />;
</div>;
if (this.props.scrollbar) { if (this.props.scrollbar) {
return <AutoHideScrollbar className={classes}> return <AutoHideScrollbar className={classes}>

View file

@ -222,7 +222,7 @@ class FeaturedRoom extends React.Component {
let roomNameNode = null; let roomNameNode = null;
if (permalink) { if (permalink) {
roomNameNode = <a href={permalink} onClick={this.onClick} >{ roomName }</a>; roomNameNode = <a href={permalink} onClick={this.onClick}>{ roomName }</a>;
} else { } else {
roomNameNode = <span>{ roomName }</span>; roomNameNode = <span>{ roomName }</span>;
} }
@ -1185,10 +1185,13 @@ export default class GroupView extends React.Component {
avatarImage = <Spinner />; avatarImage = <Spinner />;
} else { } else {
const GroupAvatar = sdk.getComponent('avatars.GroupAvatar'); const GroupAvatar = sdk.getComponent('avatars.GroupAvatar');
avatarImage = <GroupAvatar groupId={this.props.groupId} avatarImage = <GroupAvatar
groupId={this.props.groupId}
groupName={this.state.profileForm.name} groupName={this.state.profileForm.name}
groupAvatarUrl={this.state.profileForm.avatar_url} groupAvatarUrl={this.state.profileForm.avatar_url}
width={28} height={28} resizeMethod='crop' width={28}
height={28}
resizeMethod='crop'
/>; />;
} }
@ -1199,9 +1202,12 @@ export default class GroupView extends React.Component {
</label> </label>
<div className="mx_GroupView_avatarPicker_edit"> <div className="mx_GroupView_avatarPicker_edit">
<label htmlFor="avatarInput" className="mx_GroupView_avatarPicker_label"> <label htmlFor="avatarInput" className="mx_GroupView_avatarPicker_label">
<img src={require("../../../res/img/camera.svg")} <img
alt={_t("Upload avatar")} title={_t("Upload avatar")} src={require("../../../res/img/camera.svg")}
width="17" height="15" /> alt={_t("Upload avatar")}
title={_t("Upload avatar")}
width="17"
height="15" />
</label> </label>
<input id="avatarInput" className="mx_GroupView_uploadInput" type="file" onChange={this._onAvatarSelected} /> <input id="avatarInput" className="mx_GroupView_uploadInput" type="file" onChange={this._onAvatarSelected} />
</div> </div>
@ -1238,7 +1244,8 @@ export default class GroupView extends React.Component {
groupAvatarUrl={groupAvatarUrl} groupAvatarUrl={groupAvatarUrl}
groupName={groupName} groupName={groupName}
onClick={onGroupHeaderItemClick} onClick={onGroupHeaderItemClick}
width={28} height={28} width={28}
height={28}
/>; />;
if (summary.profile && summary.profile.name) { if (summary.profile && summary.profile.name) {
nameNode = <div onClick={onGroupHeaderItemClick}> nameNode = <div onClick={onGroupHeaderItemClick}>
@ -1269,28 +1276,32 @@ export default class GroupView extends React.Component {
key="_cancelButton" key="_cancelButton"
onClick={this._onCancelClick} onClick={this._onCancelClick}
> >
<img src={require("../../../res/img/cancel.svg")} className="mx_filterFlipColor" <img
width="18" height="18" alt={_t("Cancel")} /> src={require("../../../res/img/cancel.svg")}
className="mx_filterFlipColor"
width="18"
height="18"
alt={_t("Cancel")} />
</AccessibleButton>, </AccessibleButton>,
); );
} else { } else {
if (summary.user && summary.user.membership === 'join') { if (summary.user && summary.user.membership === 'join') {
rightButtons.push( rightButtons.push(
<AccessibleButton className="mx_GroupHeader_button mx_GroupHeader_editButton" <AccessibleButton
className="mx_GroupHeader_button mx_GroupHeader_editButton"
key="_editButton" key="_editButton"
onClick={this._onEditClick} onClick={this._onEditClick}
title={_t("Community Settings")} title={_t("Community Settings")}
> />,
</AccessibleButton>,
); );
} }
rightButtons.push( rightButtons.push(
<AccessibleButton className="mx_GroupHeader_button mx_GroupHeader_shareButton" <AccessibleButton
className="mx_GroupHeader_button mx_GroupHeader_shareButton"
key="_shareButton" key="_shareButton"
onClick={this._onShareClick} onClick={this._onShareClick}
title={_t('Share Community')} title={_t('Share Community')}
> />,
</AccessibleButton>,
); );
} }

View file

@ -109,8 +109,7 @@ export default class MyGroups extends React.Component {
<SimpleRoomHeader title={_t("Communities")} icon={require("../../../res/img/icons-groups.svg")} /> <SimpleRoomHeader title={_t("Communities")} icon={require("../../../res/img/icons-groups.svg")} />
<div className='mx_MyGroups_header'> <div className='mx_MyGroups_header'>
<div className="mx_MyGroups_headerCard"> <div className="mx_MyGroups_headerCard">
<AccessibleButton className='mx_MyGroups_headerCard_button' onClick={this._onCreateGroupClick}> <AccessibleButton className='mx_MyGroups_headerCard_button' onClick={this._onCreateGroupClick} />
</AccessibleButton>
<div className="mx_MyGroups_headerCard_content"> <div className="mx_MyGroups_headerCard_content">
<div className="mx_MyGroups_headerCard_header"> <div className="mx_MyGroups_headerCard_header">
{ _t('Create a new community') } { _t('Create a new community') }

View file

@ -266,8 +266,12 @@ export default class RoomStatusBar extends React.PureComponent {
<div className="mx_RoomStatusBar"> <div className="mx_RoomStatusBar">
<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
height="24" title="/!\ " alt="/!\ " /> src={require("../../../res/img/feather-customised/warning-triangle.svg")}
width="24"
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.') }

View file

@ -1740,7 +1740,8 @@ export default class RoomView extends React.Component<IProps, IState> {
onJoinClick={this.onJoinButtonClicked} onJoinClick={this.onJoinButtonClicked}
onForgetClick={this.onForgetClick} onForgetClick={this.onForgetClick}
onRejectClick={this.onRejectThreepidInviteButtonClicked} onRejectClick={this.onRejectThreepidInviteButtonClicked}
canPreview={false} error={this.state.roomLoadError} canPreview={false}
error={this.state.roomLoadError}
roomAlias={roomAlias} roomAlias={roomAlias}
joining={this.state.joining} joining={this.state.joining}
inviterName={inviterName} inviterName={inviterName}

View file

@ -136,8 +136,8 @@ export default class SearchBox extends React.Component {
key="button" key="button"
tabIndex={-1} tabIndex={-1}
className="mx_SearchBox_closeButton" className="mx_SearchBox_closeButton"
onClick={() => {this._clearSearch("button"); }}> onClick={() => {this._clearSearch("button"); }}
</AccessibleButton>) : undefined; />) : undefined;
// show a shorter placeholder when blurred, if requested // show a shorter placeholder when blurred, if requested
// this is used for the room filter field that has // this is used for the room filter field that has

View file

@ -101,7 +101,9 @@ export const SpaceFeedbackPrompt = ({ onClick }: { onClick?: () => void }) => {
<hr /> <hr />
<div> <div>
<span className="mx_SpaceFeedbackPrompt_text">{ _t("Spaces are a beta feature.") }</span> <span className="mx_SpaceFeedbackPrompt_text">{ _t("Spaces are a beta feature.") }</span>
<AccessibleButton kind="link" onClick={() => { <AccessibleButton
kind="link"
onClick={() => {
if (onClick) onClick(); if (onClick) onClick();
Modal.createTrackedDialog("Beta Feedback", "feature_spaces", BetaFeedbackDialog, { Modal.createTrackedDialog("Beta Feedback", "feature_spaces", BetaFeedbackDialog, {
featureId: "feature_spaces", featureId: "feature_spaces",
@ -553,9 +555,7 @@ const SpaceAddExistingRooms = ({ space, onFinished }) => {
onFinished={onFinished} onFinished={onFinished}
/> />
<div className="mx_SpaceRoomView_buttons"> <div className="mx_SpaceRoomView_buttons" />
</div>
<SpaceFeedbackPrompt /> <SpaceFeedbackPrompt />
</div>; </div>;
}; };

View file

@ -315,7 +315,10 @@ export default class ForgotPassword extends React.Component<IProps, IState> {
{ _t("An email has been sent to %(emailAddress)s. Once you've followed the " + { _t("An email has been sent to %(emailAddress)s. Once you've followed the " +
"link it contains, click below.", { emailAddress: this.state.email }) } "link it contains, click below.", { emailAddress: this.state.email }) }
<br /> <br />
<input className="mx_Login_submit" type="button" onClick={this.onVerify} <input
className="mx_Login_submit"
type="button"
onClick={this.onVerify}
value={_t('I have verified my email address')} /> value={_t('I have verified my email address')} />
</div>; </div>;
} }
@ -328,7 +331,10 @@ export default class ForgotPassword extends React.Component<IProps, IState> {
"push notifications. To re-enable notifications, sign in again on each " + "push notifications. To re-enable notifications, sign in again on each " +
"device.", "device.",
) }</p> ) }</p>
<input className="mx_Login_submit" type="button" onClick={this.props.onComplete} <input
className="mx_Login_submit"
type="button"
onClick={this.props.onComplete}
value={_t('Return to login screen')} /> value={_t('Return to login screen')} />
</div>; </div>;
} }

View file

@ -463,7 +463,9 @@ export default class LoginComponent extends React.PureComponent<IProps, IState>
"Either use HTTPS or <a>enable unsafe scripts</a>.", {}, "Either use HTTPS or <a>enable unsafe scripts</a>.", {},
{ {
'a': (sub) => { 'a': (sub) => {
return <a target="_blank" rel="noreferrer noopener" return <a
target="_blank"
rel="noreferrer noopener"
href="https://www.google.com/search?&q=enable%20unsafe%20scripts" href="https://www.google.com/search?&q=enable%20unsafe%20scripts"
> >
{ sub } { sub }

View file

@ -557,12 +557,16 @@ export default class Registration extends React.Component<IProps, IState> {
loggedInUserId: this.state.differentLoggedInUserId, loggedInUserId: this.state.differentLoggedInUserId,
}, },
) }</p> ) }</p>
<p><AccessibleButton element="span" className="mx_linkButton" onClick={async event => { <p><AccessibleButton
element="span"
className="mx_linkButton"
onClick={async event => {
const sessionLoaded = await this.onLoginClickWithCheck(event); const sessionLoaded = await this.onLoginClickWithCheck(event);
if (sessionLoaded) { if (sessionLoaded) {
dis.dispatch({ action: "view_welcome_page" }); dis.dispatch({ action: "view_welcome_page" });
} }
}}> }}
>
{ _t("Continue with previous account") } { _t("Continue with previous account") }
</AccessibleButton></p> </AccessibleButton></p>
</div>; </div>;

View file

@ -54,9 +54,13 @@ export default class Waveform extends React.PureComponent<IProps, IState> {
'mx_Waveform_bar': true, 'mx_Waveform_bar': true,
'mx_Waveform_bar_100pct': isCompleteBar, 'mx_Waveform_bar_100pct': isCompleteBar,
}); });
return <span key={i} style={{ return <span
key={i}
style={{
"--barHeight": h, "--barHeight": h,
} as WaveformCSSProperties} className={classes} />; } as WaveformCSSProperties}
className={classes}
/>;
}) } }) }
</div>; </div>;
} }

View file

@ -416,8 +416,10 @@ export class TermsAuthEntry extends React.Component<ITermsAuthEntryProps, ITerms
let submitButton; let submitButton;
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
onClick={this.trySubmit} disabled={!allChecked}>{ _t("Accept") }</button>; className="mx_InteractiveAuthEntryComponents_termsSubmit mx_GeneralButton"
onClick={this.trySubmit}
disabled={!allChecked}>{ _t("Accept") }</button>;
} }
return ( return (
@ -616,7 +618,9 @@ export class MsisdnAuthEntry extends React.Component<IMsisdnAuthEntryProps, IMsi
aria-label={_t("Code")} aria-label={_t("Code")}
/> />
<br /> <br />
<input type="submit" value={_t("Submit")} <input
type="submit"
value={_t("Submit")}
className={submitClasses} className={submitClasses}
disabled={!enableSubmit} disabled={!enableSubmit}
/> />

View file

@ -187,7 +187,8 @@ const BaseAvatar = (props: IProps) => {
width: toPx(width), width: toPx(width),
height: toPx(height), height: toPx(height),
}} }}
title={title} alt={_t("Avatar")} title={title}
alt={_t("Avatar")}
inputRef={inputRef} inputRef={inputRef}
{...otherProps} /> {...otherProps} />
); );
@ -201,7 +202,8 @@ const BaseAvatar = (props: IProps) => {
width: toPx(width), width: toPx(width),
height: toPx(height), height: toPx(height),
}} }}
title={title} alt="" title={title}
alt=""
ref={inputRef} ref={inputRef}
{...otherProps} /> {...otherProps} />
); );

View file

@ -102,8 +102,12 @@ export default class MemberAvatar extends React.Component<IProps, IState> {
} }
return ( return (
<BaseAvatar {...otherProps} name={this.state.name} title={this.state.title} <BaseAvatar {...otherProps}
idName={userId} url={this.state.imageUrl} onClick={onClick} /> name={this.state.name}
title={this.state.title}
idName={userId}
url={this.state.imageUrl}
onClick={onClick} />
); );
} }
} }

View file

@ -60,8 +60,10 @@ export default class DialpadContextMenu extends React.Component<IProps, IState>
<AccessibleButton className="mx_DialPadContextMenu_cancel" onClick={this.onCancelClick} /> <AccessibleButton className="mx_DialPadContextMenu_cancel" onClick={this.onCancelClick} />
</div> </div>
<div className="mx_DialPadContextMenu_header"> <div className="mx_DialPadContextMenu_header">
<Field className="mx_DialPadContextMenu_dialled" <Field
value={this.state.value} autoFocus={true} className="mx_DialPadContextMenu_dialled"
value={this.state.value}
autoFocus={true}
onChange={this.onChange} onChange={this.onChange}
/> />
</div> </div>

View file

@ -109,8 +109,10 @@ export default class StatusMessageContextMenu extends React.Component {
</AccessibleButton>; </AccessibleButton>;
} }
} else { } else {
actionButton = <AccessibleButton className="mx_StatusMessageContextMenu_submit" actionButton = <AccessibleButton
disabled={!this.state.message} onClick={this._onSubmit} className="mx_StatusMessageContextMenu_submit"
disabled={!this.state.message}
onClick={this._onSubmit}
> >
<span>{ _t("Set status") }</span> <span>{ _t("Set status") }</span>
</AccessibleButton>; </AccessibleButton>;
@ -121,12 +123,19 @@ export default class StatusMessageContextMenu extends React.Component {
spinner = <Spinner w="24" h="24" />; spinner = <Spinner w="24" h="24" />;
} }
const form = <form className="mx_StatusMessageContextMenu_form" const form = <form
autoComplete="off" onSubmit={this._onSubmit} className="mx_StatusMessageContextMenu_form"
autoComplete="off"
onSubmit={this._onSubmit}
> >
<input type="text" className="mx_StatusMessageContextMenu_message" <input
key="message" placeholder={_t("Set a new status...")} type="text"
autoFocus={true} maxLength="60" value={this.state.message} className="mx_StatusMessageContextMenu_message"
key="message"
placeholder={_t("Set a new status...")}
autoFocus={true}
maxLength="60"
value={this.state.message}
onChange={this._onStatusChange} onChange={this._onStatusChange}
/> />
<div className="mx_StatusMessageContextMenu_actionContainer"> <div className="mx_StatusMessageContextMenu_actionContainer">

View file

@ -76,7 +76,8 @@ const WidgetContextMenu: React.FC<IProps> = ({
onFinished(); onFinished();
}; };
streamAudioStreamButton = <IconizedContextMenuOption streamAudioStreamButton = <IconizedContextMenuOption
onClick={onStreamAudioClick} label={_t("Start audio stream")} onClick={onStreamAudioClick}
label={_t("Start audio stream")}
/>; />;
} }

View file

@ -211,10 +211,16 @@ export const AddExistingToSpace: React.FC<IAddExistingToSpaceProps> = ({
function overflowTile(overflowCount, totalCount) { function overflowTile(overflowCount, totalCount) {
const text = _t("and %(count)s others...", { count: overflowCount }); const text = _t("and %(count)s others...", { count: overflowCount });
return ( return (
<EntityTile className="mx_EntityTile_ellipsis" avatarJsx={ <EntityTile
className="mx_EntityTile_ellipsis"
avatarJsx={
<BaseAvatar url={require("../../../../res/img/ellipsis.svg")} name="..." width={36} height={36} /> <BaseAvatar url={require("../../../../res/img/ellipsis.svg")} name="..." width={36} height={36} />
} name={text} presenceState="online" suppressOnHover={true} }
onClick={() => setTruncateAt(totalCount)} /> name={text}
presenceState="online"
suppressOnHover={true}
onClick={() => setTruncateAt(totalCount)}
/>
); );
} }

View file

@ -665,8 +665,8 @@ export default class AddressPickerDialog extends React.Component<IProps, IState>
onChange={this.onQueryChanged} onChange={this.onQueryChanged}
placeholder={this.getPlaceholder()} placeholder={this.getPlaceholder()}
defaultValue={this.props.value} defaultValue={this.props.value}
autoFocus={this.props.focus}> autoFocus={this.props.focus}
</textarea>, />,
); );
const filteredSuggestedList = this.getFilteredSuggestions(); const filteredSuggestedList = this.getFilteredSuggestions();
@ -727,8 +727,12 @@ export default class AddressPickerDialog extends React.Component<IProps, IState>
} }
return ( return (
<BaseDialog className="mx_AddressPickerDialog" onKeyDown={this.onKeyDown} <BaseDialog
onFinished={this.props.onFinished} title={this.props.title}> className="mx_AddressPickerDialog"
onKeyDown={this.onKeyDown}
onFinished={this.props.onFinished}
title={this.props.title}
>
{ inputLabel } { inputLabel }
<div className="mx_Dialog_content"> <div className="mx_Dialog_content">
<div className="mx_AddressPickerDialog_inputContainer">{ query }</div> <div className="mx_AddressPickerDialog_inputContainer">{ query }</div>

View file

@ -118,9 +118,7 @@ export default class BaseDialog extends React.Component {
let headerImage; let headerImage;
if (this.props.headerImage) { if (this.props.headerImage) {
headerImage = <img className="mx_Dialog_titleImage" src={this.props.headerImage} headerImage = <img className="mx_Dialog_titleImage" src={this.props.headerImage} alt="" />;
alt=""
/>;
} }
return ( return (

View file

@ -71,13 +71,16 @@ const BetaFeedbackDialog: React.FC<IProps> = ({ featureId, onFinished }) => {
&nbsp; &nbsp;
{ _t("Your platform and username will be noted to help us use your feedback as much as we can.") } { _t("Your platform and username will be noted to help us use your feedback as much as we can.") }
<AccessibleButton kind="link" onClick={() => { <AccessibleButton
kind="link"
onClick={() => {
onFinished(false); onFinished(false);
defaultDispatcher.dispatch({ defaultDispatcher.dispatch({
action: Action.ViewUserSettings, action: Action.ViewUserSettings,
initialTabId: UserTab.Labs, initialTabId: UserTab.Labs,
}); });
}}> }}
>
{ _t("To leave the beta, visit your settings.") } { _t("To leave the beta, visit your settings.") }
</AccessibleButton> </AccessibleButton>
</div> </div>

View file

@ -188,7 +188,9 @@ export default class BugReportDialog extends React.Component<IProps, IState> {
} }
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'
> >

View file

@ -205,9 +205,12 @@ export default class CommunityPrototypeInviteDialog extends React.PureComponent<
people.push(( people.push((
<AccessibleButton <AccessibleButton
onClick={this.onShowMorePeople} onClick={this.onShowMorePeople}
kind="link" key="more" kind="link"
key="more"
className="mx_CommunityPrototypeInviteDialog_morePeople" className="mx_CommunityPrototypeInviteDialog_morePeople"
>{ _t("Show more") }</AccessibleButton> >
{ _t("Show more") }
</AccessibleButton>
)); ));
} }
} }
@ -240,10 +243,13 @@ export default class CommunityPrototypeInviteDialog extends React.PureComponent<
{ peopleIntro } { peopleIntro }
{ people } { people }
<AccessibleButton <AccessibleButton
kind="primary" onClick={this.onSubmit} kind="primary"
onClick={this.onSubmit}
disabled={this.state.busy} disabled={this.state.busy}
className="mx_CommunityPrototypeInviteDialog_primaryButton" className="mx_CommunityPrototypeInviteDialog_primaryButton"
>{ buttonText }</AccessibleButton> >
{ buttonText }
</AccessibleButton>
</div> </div>
</form> </form>
</BaseDialog> </BaseDialog>

View file

@ -37,8 +37,8 @@ export default class ConfirmRedactDialog extends React.Component<IProps> {
"Note that if you delete a room name or topic change, it could undo the change.")} "Note that if you delete a room name or topic change, it could undo the change.")}
placeholder={_t("Reason (optional)")} placeholder={_t("Reason (optional)")}
focus focus
button={_t("Remove")}> button={_t("Remove")}
</TextInputDialog> />
); );
} }
} }

View file

@ -104,7 +104,9 @@ export default class ConfirmUserActionDialog extends React.Component<IProps> {
} }
return ( return (
<BaseDialog className="mx_ConfirmUserActionDialog" onFinished={this.props.onFinished} <BaseDialog
className="mx_ConfirmUserActionDialog"
onFinished={this.props.onFinished}
title={this.props.title} title={this.props.title}
contentId='mx_Dialog_content' contentId='mx_Dialog_content'
> >

View file

@ -204,8 +204,10 @@ export default class CreateCommunityPrototypeDialog extends React.PureComponent<
</div> </div>
<div className="mx_CreateCommunityPrototypeDialog_colAvatar"> <div className="mx_CreateCommunityPrototypeDialog_colAvatar">
<input <input
type="file" style={{ display: "none" }} type="file"
ref={this.avatarUploadRef} accept="image/*" style={{ display: "none" }}
ref={this.avatarUploadRef}
accept="image/*"
onChange={this.onAvatarChanged} onChange={this.onAvatarChanged}
/> />
<AccessibleButton <AccessibleButton

View file

@ -123,7 +123,9 @@ export default class CreateGroupDialog extends React.Component<IProps, IState> {
} }
return ( return (
<BaseDialog className="mx_CreateGroupDialog" onFinished={this.props.onFinished} <BaseDialog
className="mx_CreateGroupDialog"
onFinished={this.props.onFinished}
title={_t('Create Community')} title={_t('Create Community')}
> >
<form onSubmit={this.onFormSubmit}> <form onSubmit={this.onFormSubmit}>
@ -133,8 +135,11 @@ export default class CreateGroupDialog extends React.Component<IProps, IState> {
<label htmlFor="groupname">{ _t('Community Name') }</label> <label htmlFor="groupname">{ _t('Community Name') }</label>
</div> </div>
<div> <div>
<input id="groupname" className="mx_CreateGroupDialog_input" <input
autoFocus={true} size={64} id="groupname"
className="mx_CreateGroupDialog_input"
autoFocus={true}
size={64}
placeholder={_t('Example')} placeholder={_t('Example')}
onChange={this.onGroupNameChange} onChange={this.onGroupNameChange}
value={this.state.groupName} value={this.state.groupName}

View file

@ -279,7 +279,9 @@ export default class CreateRoomDialog extends React.Component<IProps, IState> {
title = _t("Create a room in %(communityName)s", { communityName: name }); title = _t("Create a room in %(communityName)s", { communityName: name });
} }
return ( return (
<BaseDialog className="mx_CreateRoomDialog" onFinished={this.props.onFinished} <BaseDialog
className="mx_CreateRoomDialog"
onFinished={this.props.onFinished}
title={title} title={title}
> >
<form onSubmit={this.onOk} onKeyDown={this.onKeyDown}> <form onSubmit={this.onOk} onKeyDown={this.onKeyDown}>

View file

@ -72,7 +72,7 @@ const CryptoStoreTooNewDialog: React.FC<IProps> = (props: IProps) => {
hasCancel={false} hasCancel={false}
onPrimaryButtonClick={props.onFinished} onPrimaryButtonClick={props.onFinished}
> >
<button onClick={_onLogoutClicked} > <button onClick={_onLogoutClicked}>
{ _t('Sign out') } { _t('Sign out') }
</button> </button>
</DialogButtons> </DialogButtons>

View file

@ -182,14 +182,23 @@ export class SendCustomEvent extends GenericEditor<ISendCustomEventProps, ISendC
<br /> <br />
<Field id="evContent" label={_t("Event Content")} type="text" className="mx_DevTools_textarea" <Field
autoComplete="off" value={this.state.evContent} onChange={this.onChange} element="textarea" /> id="evContent"
label={_t("Event Content")}
type="text"
className="mx_DevTools_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>
{ !this.state.message && <button onClick={this.send}>{ _t('Send') }</button> } { !this.state.message && <button onClick={this.send}>{ _t('Send') }</button> }
{ showTglFlip && <div style={{ float: "right" }}> { showTglFlip && <div style={{ float: "right" }}>
<input id="isStateEvent" className="mx_DevTools_tgl mx_DevTools_tgl-flip" <input
id="isStateEvent"
className="mx_DevTools_tgl mx_DevTools_tgl-flip"
type="checkbox" type="checkbox"
checked={this.state.isStateEvent} checked={this.state.isStateEvent}
onChange={this.onChange} onChange={this.onChange}
@ -282,14 +291,24 @@ class SendAccountData extends GenericEditor<ISendAccountDataProps, ISendAccountD
{ this.textInput('eventType', _t('Event Type')) } { this.textInput('eventType', _t('Event Type')) }
<br /> <br />
<Field id="evContent" label={_t("Event Content")} type="text" className="mx_DevTools_textarea" <Field
autoComplete="off" value={this.state.evContent} onChange={this.onChange} element="textarea" /> id="evContent"
label={_t("Event Content")}
type="text"
className="mx_DevTools_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>
{ !this.state.message && <button onClick={this.send}>{ _t('Send') }</button> } { !this.state.message && <button onClick={this.send}>{ _t('Send') }</button> }
{ !this.state.message && <div style={{ float: "right" }}> { !this.state.message && <div style={{ float: "right" }}>
<input id="isRoomAccountData" className="mx_DevTools_tgl mx_DevTools_tgl-flip" <input
id="isRoomAccountData"
className="mx_DevTools_tgl mx_DevTools_tgl-flip"
type="checkbox" type="checkbox"
checked={this.state.isRoomAccountData} checked={this.state.isRoomAccountData}
disabled={this.props.forceMode} disabled={this.props.forceMode}
@ -371,11 +390,18 @@ class FilteredList extends React.PureComponent<IFilteredListProps, IFilteredList
render() { render() {
return <div> return <div>
<Field label={_t('Filter results')} autoFocus={true} size={64} <Field
type="text" autoComplete="off" value={this.props.query} onChange={this.onQuery} label={_t('Filter results')}
autoFocus={true}
size={64}
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}
@ -459,11 +485,16 @@ class RoomStateExplorer extends React.PureComponent<IExplorerProps, IRoomStateEx
render() { render() {
if (this.state.event) { if (this.state.event) {
if (this.state.editing) { if (this.state.editing) {
return <SendCustomEvent room={this.props.room} forceStateEvent={true} onBack={this.onBack} inputs={{ return <SendCustomEvent
room={this.props.room}
forceStateEvent={true}
onBack={this.onBack}
inputs={{
eventType: this.state.event.getType(), eventType: this.state.event.getType(),
evContent: JSON.stringify(this.state.event.getContent(), null, '\t'), evContent: JSON.stringify(this.state.event.getContent(), null, '\t'),
stateKey: this.state.event.getStateKey(), stateKey: this.state.event.getStateKey(),
}} />; }}
/>;
} }
return <div className="mx_ViewSource"> return <div className="mx_ViewSource">
@ -594,7 +625,9 @@ class AccountDataExplorer extends React.PureComponent<IExplorerProps, IAccountDa
inputs={{ inputs={{
eventType: this.state.event.getType(), eventType: this.state.event.getType(),
evContent: JSON.stringify(this.state.event.getContent(), null, '\t'), evContent: JSON.stringify(this.state.event.getContent(), null, '\t'),
}} forceMode={true} />; }}
forceMode={true}
/>;
} }
return <div className="mx_ViewSource"> return <div className="mx_ViewSource">
@ -631,7 +664,9 @@ class AccountDataExplorer extends React.PureComponent<IExplorerProps, IAccountDa
<div className="mx_Dialog_buttons"> <div className="mx_Dialog_buttons">
<button onClick={this.onBack}>{ _t('Back') }</button> <button onClick={this.onBack}>{ _t('Back') }</button>
<div style={{ float: "right" }}> <div style={{ float: "right" }}>
<input id="isRoomAccountData" className="mx_DevTools_tgl mx_DevTools_tgl-flip" <input
id="isRoomAccountData"
className="mx_DevTools_tgl mx_DevTools_tgl-flip"
type="checkbox" type="checkbox"
checked={this.state.isRoomAccountData} checked={this.state.isRoomAccountData}
onChange={this.onChange} onChange={this.onChange}
@ -1021,8 +1056,13 @@ class SettingsExplorer extends React.PureComponent<IExplorerProps, ISettingsExpl
<div> <div>
<div className="mx_Dialog_content mx_DevTools_SettingsExplorer"> <div className="mx_Dialog_content mx_DevTools_SettingsExplorer">
<Field <Field
label={_t('Filter results')} autoFocus={true} size={64} label={_t('Filter results')}
type="text" autoComplete="off" value={this.state.query} onChange={this.onQueryChange} autoFocus={true}
size={64}
type="text"
autoComplete="off"
value={this.state.query}
onChange={this.onQueryChange}
className="mx_TextInputDialog_input mx_DevTools_RoomStateExplorer_query" className="mx_TextInputDialog_input mx_DevTools_RoomStateExplorer_query"
/> />
<table> <table>
@ -1040,7 +1080,9 @@ class SettingsExplorer extends React.PureComponent<IExplorerProps, ISettingsExpl
<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'
> >
@ -1104,18 +1146,26 @@ class SettingsExplorer extends React.PureComponent<IExplorerProps, ISettingsExpl
<div> <div>
<Field <Field
id="valExpl" label={_t("Values at explicit levels")} type="text" id="valExpl"
className="mx_DevTools_textarea" element="textarea" label={_t("Values at explicit levels")}
autoComplete="off" value={this.state.explicitValues} type="text"
className="mx_DevTools_textarea"
element="textarea"
autoComplete="off"
value={this.state.explicitValues}
onChange={this.onExplValuesEdit} onChange={this.onExplValuesEdit}
/> />
</div> </div>
<div> <div>
<Field <Field
id="valExpl" label={_t("Values at explicit levels in this room")} type="text" id="valExpl"
className="mx_DevTools_textarea" element="textarea" label={_t("Values at explicit levels in this room")}
autoComplete="off" value={this.state.explicitRoomValues} type="text"
className="mx_DevTools_textarea"
element="textarea"
autoComplete="off"
value={this.state.explicitRoomValues}
onChange={this.onExplRoomValuesEdit} onChange={this.onExplRoomValuesEdit}
/> />
</div> </div>

View file

@ -144,8 +144,10 @@ export default class EditCommunityPrototypeDialog extends React.PureComponent<IP
</div> </div>
<div className="mx_EditCommunityPrototypeDialog_rowAvatar"> <div className="mx_EditCommunityPrototypeDialog_rowAvatar">
<input <input
type="file" style={{ display: "none" }} type="file"
ref={this.avatarUploadRef} accept="image/*" style={{ display: "none" }}
ref={this.avatarUploadRef}
accept="image/*"
onChange={this.onAvatarChanged} onChange={this.onAvatarChanged}
/> />
<AccessibleButton <AccessibleButton

View file

@ -106,12 +106,12 @@ const Entry: React.FC<IEntryProps> = ({ room, event, matrixClient: cli, onFinish
className = "mx_ForwardList_sending"; className = "mx_ForwardList_sending";
disabled = true; disabled = true;
title = _t("Sending"); title = _t("Sending");
icon = <div className="mx_ForwardList_sendIcon" aria-label={title}></div>; icon = <div className="mx_ForwardList_sendIcon" aria-label={title} />;
} else if (sendState === SendState.Sent) { } else if (sendState === SendState.Sent) {
className = "mx_ForwardList_sent"; className = "mx_ForwardList_sent";
disabled = true; disabled = true;
title = _t("Sent"); title = _t("Sent");
icon = <div className="mx_ForwardList_sendIcon" aria-label={title}></div>; icon = <div className="mx_ForwardList_sendIcon" aria-label={title} />;
} else { } else {
className = "mx_ForwardList_sendFailed"; className = "mx_ForwardList_sendFailed";
disabled = true; disabled = true;
@ -204,10 +204,16 @@ const ForwardDialog: React.FC<IProps> = ({ matrixClient: cli, event, permalinkCr
function overflowTile(overflowCount, totalCount) { function overflowTile(overflowCount, totalCount) {
const text = _t("and %(count)s others...", { count: overflowCount }); const text = _t("and %(count)s others...", { count: overflowCount });
return ( return (
<EntityTile className="mx_EntityTile_ellipsis" avatarJsx={ <EntityTile
className="mx_EntityTile_ellipsis"
avatarJsx={
<BaseAvatar url={require("../../../../res/img/ellipsis.svg")} name="..." width={36} height={36} /> <BaseAvatar url={require("../../../../res/img/ellipsis.svg")} name="..." width={36} height={36} />
} name={text} presenceState="online" suppressOnHover={true} }
onClick={() => setTruncateAt(totalCount)} /> name={text}
presenceState="online"
suppressOnHover={true}
onClick={() => setTruncateAt(totalCount)}
/>
); );
} }

View file

@ -133,18 +133,23 @@ export default class IncomingSasDialog extends React.Component {
? mediaFromMxc(oppProfile.avatar_url).getSquareThumbnailHttp(48) ? mediaFromMxc(oppProfile.avatar_url).getSquareThumbnailHttp(48)
: null; : null;
profile = <div className="mx_IncomingSasDialog_opponentProfile"> profile = <div className="mx_IncomingSasDialog_opponentProfile">
<BaseAvatar name={oppProfile.displayname} <BaseAvatar
name={oppProfile.displayname}
idName={this.props.verifier.userId} idName={this.props.verifier.userId}
url={url} url={url}
width={48} height={48} resizeMethod='crop' width={48}
height={48}
resizeMethod='crop'
/> />
<h2>{ oppProfile.displayname }</h2> <h2>{ oppProfile.displayname }</h2>
</div>; </div>;
} else if (this.state.opponentProfileError) { } else if (this.state.opponentProfileError) {
profile = <div> profile = <div>
<BaseAvatar name={this.props.verifier.userId.slice(1)} <BaseAvatar
name={this.props.verifier.userId.slice(1)}
idName={this.props.verifier.userId} idName={this.props.verifier.userId}
width={48} height={48} width={48}
height={48}
/> />
<h2>{ this.props.verifier.userId }</h2> <h2>{ this.props.verifier.userId }</h2>
</div>; </div>;

View file

@ -63,8 +63,7 @@ export default class InfoDialog extends React.Component {
{ this.props.button !== false && <DialogButtons primaryButton={this.props.button || _t('OK')} { this.props.button !== false && <DialogButtons primaryButton={this.props.button || _t('OK')}
onPrimaryButtonClick={this.onFinished} onPrimaryButtonClick={this.onFinished}
hasCancel={false} hasCancel={false}
> /> }
</DialogButtons> }
</BaseDialog> </BaseDialog>
); );
} }

View file

@ -196,7 +196,9 @@ class DMUserTile extends React.PureComponent<IDMUserTileProps> {
? <img ? <img
className='mx_InviteDialog_userTile_avatar mx_InviteDialog_userTile_threepidAvatar' className='mx_InviteDialog_userTile_avatar mx_InviteDialog_userTile_threepidAvatar'
src={require("../../../../res/img/icon-email-pill-avatar.svg")} src={require("../../../../res/img/icon-email-pill-avatar.svg")}
width={avatarSize} height={avatarSize} /> width={avatarSize}
height={avatarSize}
/>
: <BaseAvatar : <BaseAvatar
className='mx_InviteDialog_userTile_avatar' className='mx_InviteDialog_userTile_avatar'
url={this.props.member.getMxcAvatarUrl() url={this.props.member.getMxcAvatarUrl()
@ -214,8 +216,11 @@ class DMUserTile extends React.PureComponent<IDMUserTileProps> {
className='mx_InviteDialog_userTile_remove' className='mx_InviteDialog_userTile_remove'
onClick={this.onRemove} onClick={this.onRemove}
> >
<img src={require("../../../../res/img/icon-pill-remove.svg")} <img
alt={_t('Remove')} width={8} height={8} src={require("../../../../res/img/icon-pill-remove.svg")}
alt={_t('Remove')}
width={8}
height={8}
/> />
</AccessibleButton> </AccessibleButton>
); );
@ -297,7 +302,9 @@ class DMRoomTile extends React.PureComponent<IDMRoomTileProps> {
const avatar = (this.props.member as ThreepidMember).isEmail const avatar = (this.props.member as ThreepidMember).isEmail
? <img ? <img
src={require("../../../../res/img/icon-email-pill-avatar.svg")} src={require("../../../../res/img/icon-email-pill-avatar.svg")}
width={avatarSize} height={avatarSize} /> width={avatarSize}
height={avatarSize}
/>
: <BaseAvatar : <BaseAvatar
url={this.props.member.getMxcAvatarUrl() url={this.props.member.getMxcAvatarUrl()
? mediaFromMxc(this.props.member.getMxcAvatarUrl()).getSquareThumbnailHttp(avatarSize) ? mediaFromMxc(this.props.member.getMxcAvatarUrl()).getSquareThumbnailHttp(avatarSize)
@ -1458,7 +1465,8 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
<p className='mx_InviteDialog_helpText'> <p className='mx_InviteDialog_helpText'>
<img <img
src={require("../../../../res/img/element-icons/info.svg")} src={require("../../../../res/img/element-icons/info.svg")}
width={14} height={14} /> width={14}
height={14} />
{ " " + _t("Invited people will be able to read old messages.") } { " " + _t("Invited people will be able to read old messages.") }
</p>; </p>;
} }
@ -1534,14 +1542,18 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
// Only show the backspace button if the field has content // Only show the backspace button if the field has content
let dialPadField; let dialPadField;
if (this.state.dialPadValue.length !== 0) { if (this.state.dialPadValue.length !== 0) {
dialPadField = <Field className="mx_InviteDialog_dialPadField" id="dialpad_number" dialPadField = <Field
className="mx_InviteDialog_dialPadField"
id="dialpad_number"
value={this.state.dialPadValue} value={this.state.dialPadValue}
autoFocus={true} autoFocus={true}
onChange={this.onDialChange} onChange={this.onDialChange}
postfixComponent={backspaceButton} postfixComponent={backspaceButton}
/>; />;
} else { } else {
dialPadField = <Field className="mx_InviteDialog_dialPadField" id="dialpad_number" dialPadField = <Field
className="mx_InviteDialog_dialPadField"
id="dialpad_number"
value={this.state.dialPadValue} value={this.state.dialPadValue}
autoFocus={true} autoFocus={true}
onChange={this.onDialChange} onChange={this.onDialChange}
@ -1552,14 +1564,19 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
<form onSubmit={this.onDialFormSubmit}> <form onSubmit={this.onDialFormSubmit}>
{ dialPadField } { dialPadField }
</form> </form>
<Dialpad hasDial={false} <Dialpad
onDigitPress={this.onDigitPress} onDeletePress={this.onDeletePress} hasDial={false}
onDigitPress={this.onDigitPress}
onDeletePress={this.onDeletePress}
/> />
</div>; </div>;
tabs.push(new Tab(TabId.DialPad, _td("Dial pad"), 'mx_InviteDialog_dialPadIcon', dialPadSection)); tabs.push(new Tab(TabId.DialPad, _td("Dial pad"), 'mx_InviteDialog_dialPadIcon', dialPadSection));
dialogContent = <React.Fragment> dialogContent = <React.Fragment>
<TabbedView tabs={tabs} initialTabId={this.state.currentTabId} <TabbedView
tabLocation={TabLocation.TOP} onChange={this.onTabChange} tabs={tabs}
initialTabId={this.state.currentTabId}
tabLocation={TabLocation.TOP}
onChange={this.onTabChange}
/> />
{ consultConnectSection } { consultConnectSection }
</React.Fragment>; </React.Fragment>;

View file

@ -85,7 +85,9 @@ export default class SessionRestoreErrorDialog extends React.Component {
} }
return ( return (
<BaseDialog className="mx_ErrorDialog" onFinished={this.props.onFinished} <BaseDialog
className="mx_ErrorDialog"
onFinished={this.props.onFinished}
title={_t('Unable to restore session')} title={_t('Unable to restore session')}
contentId='mx_Dialog_content' contentId='mx_Dialog_content'
hasCancel={false} hasCancel={false}

View file

@ -54,7 +54,9 @@ export default class StorageEvictedDialog extends React.Component {
} }
return ( return (
<BaseDialog className="mx_ErrorDialog" onFinished={this.props.onFinished} <BaseDialog
className="mx_ErrorDialog"
onFinished={this.props.onFinished}
title={_t('Missing session data')} title={_t('Missing session data')}
contentId='mx_Dialog_content' contentId='mx_Dialog_content'
hasCancel={false} hasCancel={false}

View file

@ -287,7 +287,8 @@ export default class AccessSecretStorageDialog extends React.PureComponent<IProp
<div className="mx_AccessSecretStorageDialog_reset"> <div className="mx_AccessSecretStorageDialog_reset">
{ _t("Forgotten or lost all recovery methods? <a>Reset all</a>", null, { { _t("Forgotten or lost all recovery methods? <a>Reset all</a>", null, {
a: (sub) => <a a: (sub) => <a
href="" onClick={this.onResetAllClick} href=""
onClick={this.onResetAllClick}
className="mx_AccessSecretStorageDialog_reset_link">{ sub }</a>, className="mx_AccessSecretStorageDialog_reset_link">{ sub }</a>,
}) } }) }
</div> </div>

View file

@ -399,7 +399,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
let keyStatus; let keyStatus;
if (this.state.recoveryKey.length === 0) { if (this.state.recoveryKey.length === 0) {
keyStatus = <div className="mx_RestoreKeyBackupDialog_keyStatus"></div>; keyStatus = <div className="mx_RestoreKeyBackupDialog_keyStatus" />;
} else if (this.state.recoveryKeyValid) { } else if (this.state.recoveryKeyValid) {
keyStatus = <div className="mx_RestoreKeyBackupDialog_keyStatus"> keyStatus = <div className="mx_RestoreKeyBackupDialog_keyStatus">
{ "\uD83D\uDC4D " }{ _t("This looks like a valid Security Key!") } { "\uD83D\uDC4D " }{ _t("This looks like a valid Security Key!") }

View file

@ -122,7 +122,7 @@ export default class AddressTile extends React.Component<IProps> {
let dismiss; let dismiss;
if (this.props.canDismiss) { if (this.props.canDismiss) {
dismiss = ( dismiss = (
<div className="mx_AddressTile_dismiss" onClick={this.props.onDismissed} > <div className="mx_AddressTile_dismiss" onClick={this.props.onDismissed}>
<img src={require("../../../../res/img/icon-address-delete.svg")} width="9" height="9" /> <img src={require("../../../../res/img/icon-address-delete.svg")} width="9" height="9" />
</div> </div>
); );

View file

@ -51,7 +51,8 @@ export class ExistingSource extends React.Component<DesktopCapturerSourceIProps>
<AccessibleButton <AccessibleButton
className="mx_desktopCapturerSourcePicker_stream_button" className="mx_desktopCapturerSourcePicker_stream_button"
title={this.props.source.name} title={this.props.source.name}
onClick={this.onClick} > onClick={this.onClick}
>
<img <img
className="mx_desktopCapturerSourcePicker_stream_thumbnail" className="mx_desktopCapturerSourcePicker_stream_thumbnail"
src={this.props.source.thumbnailURL} src={this.props.source.thumbnailURL}

View file

@ -384,7 +384,8 @@ export default class ImageView extends React.Component<IProps, IState> {
const avatar = ( const avatar = (
<MemberAvatar <MemberAvatar
member={mxEvent.sender} member={mxEvent.sender}
width={32} height={32} width={32}
height={32}
viewUserOnClick={true} viewUserOnClick={true}
/> />
); );
@ -403,7 +404,7 @@ export default class ImageView extends React.Component<IProps, IState> {
// an empty div here, since the panel uses space-between // an empty div here, since the panel uses space-between
// and we want the same placement of elements // and we want the same placement of elements
info = ( info = (
<div></div> <div />
); );
} }
@ -427,15 +428,15 @@ export default class ImageView extends React.Component<IProps, IState> {
<AccessibleTooltipButton <AccessibleTooltipButton
className="mx_ImageView_button mx_ImageView_button_zoomOut" className="mx_ImageView_button mx_ImageView_button_zoomOut"
title={_t("Zoom out")} title={_t("Zoom out")}
onClick={this.onZoomOutClick}> onClick={this.onZoomOutClick}
</AccessibleTooltipButton> />
); );
zoomInButton = ( zoomInButton = (
<AccessibleTooltipButton <AccessibleTooltipButton
className="mx_ImageView_button mx_ImageView_button_zoomIn" className="mx_ImageView_button mx_ImageView_button_zoomIn"
title={_t("Zoom in")} title={_t("Zoom in")}
onClick={this.onZoomInClick}> onClick={this.onZoomInClick}
</AccessibleTooltipButton> />
); );
} }
@ -457,24 +458,24 @@ export default class ImageView extends React.Component<IProps, IState> {
<AccessibleTooltipButton <AccessibleTooltipButton
className="mx_ImageView_button mx_ImageView_button_rotateCCW" className="mx_ImageView_button mx_ImageView_button_rotateCCW"
title={_t("Rotate Left")} title={_t("Rotate Left")}
onClick={this.onRotateCounterClockwiseClick}> onClick={this.onRotateCounterClockwiseClick}
</AccessibleTooltipButton> />
<AccessibleTooltipButton <AccessibleTooltipButton
className="mx_ImageView_button mx_ImageView_button_rotateCW" className="mx_ImageView_button mx_ImageView_button_rotateCW"
title={_t("Rotate Right")} title={_t("Rotate Right")}
onClick={this.onRotateClockwiseClick}> onClick={this.onRotateClockwiseClick}
</AccessibleTooltipButton> />
<AccessibleTooltipButton <AccessibleTooltipButton
className="mx_ImageView_button mx_ImageView_button_download" className="mx_ImageView_button mx_ImageView_button_download"
title={_t("Download")} title={_t("Download")}
onClick={this.onDownloadClick}> onClick={this.onDownloadClick}
</AccessibleTooltipButton> />
{ contextMenuButton } { contextMenuButton }
<AccessibleTooltipButton <AccessibleTooltipButton
className="mx_ImageView_button mx_ImageView_button_close" className="mx_ImageView_button mx_ImageView_button_close"
title={_t("Close")} title={_t("Close")}
onClick={this.props.onFinished}> onClick={this.props.onFinished}
</AccessibleTooltipButton> />
{ this.renderContextMenu() } { this.renderContextMenu() }
</div> </div>
</div> </div>

View file

@ -92,7 +92,7 @@ const MiniAvatarUploader: React.FC<IProps> = ({ hasAvatar, hasAvatarLabel, noAva
<div className="mx_MiniAvatarUploader_indicator"> <div className="mx_MiniAvatarUploader_indicator">
{ busy ? { busy ?
<Spinner w={20} h={20} /> : <Spinner w={20} h={20} /> :
<div className="mx_MiniAvatarUploader_cameraIcon"></div> } <div className="mx_MiniAvatarUploader_cameraIcon" /> }
</div> </div>
<div className={classNames("mx_Tooltip", { <div className={classNames("mx_Tooltip", {

View file

@ -258,7 +258,10 @@ class Pill extends React.Component {
linkText = groupId; linkText = groupId;
if (this.props.shouldShowPillAvatar) { if (this.props.shouldShowPillAvatar) {
avatar = <BaseAvatar avatar = <BaseAvatar
name={name || groupId} width={16} height={16} aria-hidden="true" name={name || groupId}
width={16}
height={16}
aria-hidden="true"
url={avatarUrl ? mediaFromMxc(avatarUrl).getSquareThumbnailHttp(16) : null} />; url={avatarUrl ? mediaFromMxc(avatarUrl).getSquareThumbnailHttp(16) : null} />;
} }
pillClass = 'mx_GroupPill'; pillClass = 'mx_GroupPill';

View file

@ -134,8 +134,10 @@ export default class PowerSelector extends React.Component {
const label = typeof this.props.label === "undefined" ? _t("Power level") : this.props.label; const label = typeof this.props.label === "undefined" ? _t("Power level") : this.props.label;
if (this.state.custom) { if (this.state.custom) {
picker = ( picker = (
<Field type="number" <Field
label={label} max={this.props.maxValue} type="number"
label={label}
max={this.props.maxValue}
onBlur={this.onCustomBlur} onBlur={this.onCustomBlur}
onKeyDown={this.onCustomKeyDown} onKeyDown={this.onCustomKeyDown}
onChange={this.onCustomChange} onChange={this.onCustomChange}
@ -157,9 +159,12 @@ export default class PowerSelector extends React.Component {
}); });
picker = ( picker = (
<Field element="select" <Field
label={label} onChange={this.onSelectChange} element="select"
value={String(this.state.selectValue)} disabled={this.props.disabled} label={label}
onChange={this.onSelectChange}
value={String(this.state.selectValue)}
disabled={this.props.disabled}
> >
{ options } { options }
</Field> </Field>

View file

@ -166,8 +166,7 @@ export default class Tooltip extends React.Component<IProps> {
public render() { public render() {
// Render a placeholder // Render a placeholder
return ( return (
<div className={this.props.className}> <div className={this.props.className} />
</div>
); );
} }
} }

View file

@ -101,14 +101,16 @@ class Category extends React.PureComponent<IProps> {
{ name } { name }
</h2> </h2>
<LazyRenderList <LazyRenderList
element="ul" className="mx_EmojiPicker_list" element="ul"
itemHeight={EMOJI_HEIGHT} items={rows} className="mx_EmojiPicker_list"
itemHeight={EMOJI_HEIGHT}
items={rows}
scrollTop={localScrollTop} scrollTop={localScrollTop}
height={localHeight} height={localHeight}
overflowItems={OVERFLOW_ROWS} overflowItems={OVERFLOW_ROWS}
overflowMargin={0} overflowMargin={0}
renderItem={this.renderEmojiRow}> renderItem={this.renderEmojiRow}
</LazyRenderList> />
</section> </section>
); );
} }

View file

@ -86,10 +86,16 @@ export default class GroupMemberList extends React.Component {
const BaseAvatar = sdk.getComponent("avatars.BaseAvatar"); const BaseAvatar = sdk.getComponent("avatars.BaseAvatar");
const text = _t("and %(count)s others...", { count: overflowCount }); const text = _t("and %(count)s others...", { count: overflowCount });
return ( return (
<EntityTile className="mx_EntityTile_ellipsis" avatarJsx={ <EntityTile
className="mx_EntityTile_ellipsis"
avatarJsx={
<BaseAvatar url={require("../../../../res/img/ellipsis.svg")} name="..." width={36} height={36} /> <BaseAvatar url={require("../../../../res/img/ellipsis.svg")} name="..." width={36} height={36} />
} name={text} presenceState="online" suppressOnHover={true} }
onClick={this._showFullMemberList} /> name={text}
presenceState="online"
suppressOnHover={true}
onClick={this._showFullMemberList}
/>
); );
}; };
@ -152,7 +158,9 @@ export default class GroupMemberList extends React.Component {
); );
}); });
return <TruncatedList className="mx_MemberList_wrapper" truncateAt={this.state.truncateAt} return <TruncatedList
className="mx_MemberList_wrapper"
truncateAt={this.state.truncateAt}
createOverflowElement={this._createOverflowTile} createOverflowElement={this._createOverflowTile}
> >
{ memberTiles } { memberTiles }

View file

@ -56,14 +56,19 @@ export default class GroupMemberTile extends React.Component {
aria-hidden="true" aria-hidden="true"
name={this.props.member.displayname || this.props.member.userId} name={this.props.member.displayname || this.props.member.userId}
idName={this.props.member.userId} idName={this.props.member.userId}
width={36} height={36} width={36}
height={36}
url={avatarUrl} url={avatarUrl}
/> />
); );
return ( return (
<EntityTile name={name} avatarJsx={av} onClick={this.onClick} <EntityTile
suppressOnHover={true} presenceState="online" name={name}
avatarJsx={av}
onClick={this.onClick}
suppressOnHover={true}
presenceState="online"
powerStatus={this.props.member.isPrivileged ? EntityTile.POWER_STATUS_ADMIN : null} powerStatus={this.props.member.isPrivileged ? EntityTile.POWER_STATUS_ADMIN : null}
/> />
); );

View file

@ -76,10 +76,16 @@ export default class GroupRoomList extends React.Component {
const BaseAvatar = sdk.getComponent("avatars.BaseAvatar"); const BaseAvatar = sdk.getComponent("avatars.BaseAvatar");
const text = _t("and %(count)s others...", { count: overflowCount }); const text = _t("and %(count)s others...", { count: overflowCount });
return ( return (
<EntityTile className="mx_EntityTile_ellipsis" avatarJsx={ <EntityTile
className="mx_EntityTile_ellipsis"
avatarJsx={
<BaseAvatar url={require("../../../../res/img/ellipsis.svg")} name="..." width={36} height={36} /> <BaseAvatar url={require("../../../../res/img/ellipsis.svg")} name="..." width={36} height={36} />
} name={text} presenceState="online" suppressOnHover={true} }
onClick={this._showFullRoomList} /> name={text}
presenceState="online"
suppressOnHover={true}
onClick={this._showFullRoomList}
/>
); );
}; };
@ -142,7 +148,8 @@ export default class GroupRoomList extends React.Component {
} }
const inputBox = ( const inputBox = (
<input <input
className="mx_GroupRoomList_query mx_textinput" id="mx_GroupRoomList_query" className="mx_GroupRoomList_query mx_textinput"
id="mx_GroupRoomList_query"
type="text" type="text"
onChange={this.onSearchQueryChanged} onChange={this.onSearchQueryChanged}
value={this.state.searchQuery} value={this.state.searchQuery}
@ -156,8 +163,11 @@ export default class GroupRoomList extends React.Component {
<div className="mx_GroupRoomList" role="tabpanel"> <div className="mx_GroupRoomList" role="tabpanel">
{ 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
createOverflowElement={this._createOverflowTile}> className="mx_GroupRoomList_wrapper"
truncateAt={this.state.truncateAt}
createOverflowElement={this._createOverflowTile}
>
{ this.makeGroupRoomTiles(this.state.searchQuery) } { this.makeGroupRoomTiles(this.state.searchQuery) }
</TruncatedList> </TruncatedList>
</AutoHideScrollbar> </AutoHideScrollbar>

View file

@ -48,8 +48,10 @@ class GroupRoomTile extends React.Component {
: null; : null;
const av = ( const av = (
<BaseAvatar name={this.props.groupRoom.displayname} <BaseAvatar
width={36} height={36} name={this.props.groupRoom.displayname}
width={36}
height={36}
url={avatarUrl} url={avatarUrl}
/> />
); );

View file

@ -206,7 +206,7 @@ export default class CallEvent extends React.Component<IProps, IState> {
{ sender } { sender }
</div> </div>
<div className="mx_CallEvent_type"> <div className="mx_CallEvent_type">
<div className="mx_CallEvent_type_icon"></div> <div className="mx_CallEvent_type_icon" />
{ callType } { callType }
</div> </div>
</div> </div>

View file

@ -306,7 +306,10 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
imageElement = <HiddenImagePlaceholder />; imageElement = <HiddenImagePlaceholder />;
} 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}
@ -340,7 +343,10 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
// which has the same width as the timeline // which has the same width as the timeline
// 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}
@ -360,12 +366,15 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
} }
const thumbnail = ( const thumbnail = (
<div className="mx_MImageBody_thumbnail_container" style={{ maxHeight: maxHeight + "px", maxWidth: maxWidth + "px" }} > <div className="mx_MImageBody_thumbnail_container" style={{ maxHeight: maxHeight + "px", maxWidth: maxWidth + "px" }}>
{ showPlaceholder && { showPlaceholder &&
<div className="mx_MImageBody_thumbnail" style={{ <div
className="mx_MImageBody_thumbnail"
style={{
// Constrain width here so that spinner appears central to the loaded thumbnail // Constrain width here so that spinner appears central to the loaded thumbnail
maxWidth: infoWidth + "px", maxWidth: infoWidth + "px",
}}> }}
>
{ placeholder } { placeholder }
</div> </div>
} }

View file

@ -267,8 +267,7 @@ export default class MVideoBody extends React.PureComponent<IBodyProps, IState>
width={width} width={width}
poster={poster} poster={poster}
onPlay={this.videoOnPlay} onPlay={this.videoOnPlay}
> />
</video>
{ this.props.tileShape && <MFileBody {...this.props} showGenericPlaceholder={false} /> } { this.props.tileShape && <MFileBody {...this.props} showGenericPlaceholder={false} /> }
</span> </span>
); );

View file

@ -78,8 +78,11 @@ export default class RoomAvatarEvent extends React.Component {
{ senderDisplayName: senderDisplayName }, { senderDisplayName: senderDisplayName },
{ {
'img': () => 'img': () =>
<AccessibleButton key="avatar" className="mx_RoomAvatarEvent_avatar" <AccessibleButton
onClick={this.onAvatarClick}> key="avatar"
className="mx_RoomAvatarEvent_avatar"
onClick={this.onAvatarClick}
>
<RoomAvatar width={14} height={14} oobData={oobData} /> <RoomAvatar width={14} height={14} oobData={oobData} />
</AccessibleButton>, </AccessibleButton>,
}) })

View file

@ -205,7 +205,7 @@ function DeviceItem({ userId, device }: {userId: string, device: IDevice}) {
if (isVerified) { if (isVerified) {
return ( return (
<div className={classes} title={device.deviceId} > <div className={classes} title={device.deviceId}>
<div className={iconClasses} /> <div className={iconClasses} />
<div className="mx_UserInfo_device_name">{ deviceName }</div> <div className="mx_UserInfo_device_name">{ deviceName }</div>
<div className="mx_UserInfo_device_trusted">{ trustedLabel }</div> <div className="mx_UserInfo_device_trusted">{ trustedLabel }</div>
@ -1353,13 +1353,16 @@ const BasicUserInfo: React.FC<{
if (hasCrossSigningKeys !== undefined) { if (hasCrossSigningKeys !== undefined) {
// Note: mx_UserInfo_verifyButton is for the end-to-end tests // Note: mx_UserInfo_verifyButton is for the end-to-end tests
verifyButton = ( verifyButton = (
<AccessibleButton className="mx_UserInfo_field mx_UserInfo_verifyButton" onClick={() => { <AccessibleButton
className="mx_UserInfo_field mx_UserInfo_verifyButton"
onClick={() => {
if (hasCrossSigningKeys) { if (hasCrossSigningKeys) {
verifyUser(member as User); verifyUser(member as User);
} else { } else {
legacyVerifyUser(member as User); legacyVerifyUser(member as User);
} }
}}> }}
>
{ _t("Verify") } { _t("Verify") }
</AccessibleButton> </AccessibleButton>
); );
@ -1374,12 +1377,15 @@ const BasicUserInfo: React.FC<{
let editDevices; let editDevices;
if (member.userId == cli.getUserId()) { if (member.userId == cli.getUserId()) {
editDevices = (<p> editDevices = (<p>
<AccessibleButton className="mx_UserInfo_field" onClick={() => { <AccessibleButton
className="mx_UserInfo_field"
onClick={() => {
dis.dispatch({ dis.dispatch({
action: Action.ViewUserSettings, action: Action.ViewUserSettings,
initialTabId: UserTab.Security, initialTabId: UserTab.Security,
}); });
}}> }}
>
{ _t("Edit devices") } { _t("Edit devices") }
</AccessibleButton> </AccessibleButton>
</p>); </p>);

View file

@ -711,9 +711,12 @@ export default class EventTile extends React.Component<IProps, IState> {
// add to the start so the most recent is on the end (ie. ends up rightmost) // add to the start so the most recent is on the end (ie. ends up rightmost)
avatars.unshift( avatars.unshift(
<ReadReceiptMarker key={userId} member={receipt.roomMember} <ReadReceiptMarker
key={userId}
member={receipt.roomMember}
fallbackUserId={userId} fallbackUserId={userId}
leftOffset={left} hidden={hidden} leftOffset={left}
hidden={hidden}
readReceiptInfo={readReceiptInfo} readReceiptInfo={readReceiptInfo}
checkUnmounting={this.props.checkUnmounting} checkUnmounting={this.props.checkUnmounting}
suppressAnimation={this.suppressReadReceiptAnimation} suppressAnimation={this.suppressReadReceiptAnimation}
@ -949,8 +952,10 @@ export default class EventTile extends React.Component<IProps, IState> {
} }
avatar = ( avatar = (
<div className="mx_EventTile_avatar"> <div className="mx_EventTile_avatar">
<MemberAvatar member={member} <MemberAvatar
width={avatarSize} height={avatarSize} member={member}
width={avatarSize}
height={avatarSize}
viewUserOnClick={true} viewUserOnClick={true}
/> />
</div> </div>

View file

@ -28,10 +28,11 @@ export default (props) => {
badge = (<div className="mx_JumpToBottomButton_badge">{ props.numUnreadMessages }</div>); badge = (<div className="mx_JumpToBottomButton_badge">{ props.numUnreadMessages }</div>);
} }
return (<div className={className}> return (<div className={className}>
<AccessibleButton className="mx_JumpToBottomButton_scrollDown" <AccessibleButton
className="mx_JumpToBottomButton_scrollDown"
title={_t("Scroll to most recent messages")} title={_t("Scroll to most recent messages")}
onClick={props.onScrollToBottomClick}> onClick={props.onScrollToBottomClick}
</AccessibleButton> />
{ badge } { badge }
</div>); </div>);
}; };

View file

@ -306,10 +306,16 @@ export default class MemberList extends React.Component<IProps, IState> {
// For now we'll pretend this is any entity. It should probably be a separate tile. // For now we'll pretend this is any entity. It should probably be a separate tile.
const text = _t("and %(count)s others...", { count: overflowCount }); const text = _t("and %(count)s others...", { count: overflowCount });
return ( return (
<EntityTile className="mx_EntityTile_ellipsis" avatarJsx={ <EntityTile
className="mx_EntityTile_ellipsis"
avatarJsx={
<BaseAvatar url={require("../../../../res/img/ellipsis.svg")} name="..." width={36} height={36} /> <BaseAvatar url={require("../../../../res/img/ellipsis.svg")} name="..." width={36} height={36} />
} name={text} presenceState="online" suppressOnHover={true} }
onClick={onClick} /> name={text}
presenceState="online"
suppressOnHover={true}
onClick={onClick}
/>
); );
}; };
@ -465,8 +471,12 @@ export default class MemberList extends React.Component<IProps, IState> {
return <MemberTile key={m.userId} member={m} ref={m.userId} showPresence={this.showPresence} />; return <MemberTile key={m.userId} member={m} ref={m.userId} showPresence={this.showPresence} />;
} else { } else {
// Is a 3pid invite // Is a 3pid invite
return <EntityTile key={m.getStateKey()} name={m.getContent().display_name} suppressOnHover={true} return <EntityTile
onClick={() => this.onPending3pidInviteClick(m)} />; key={m.getStateKey()}
name={m.getContent().display_name}
suppressOnHover={true}
onClick={() => this.onPending3pidInviteClick(m)}
/>;
} }
}); });
} }

View file

@ -98,9 +98,7 @@ const EmojiButton = ({ addEmoji }) => {
isExpanded={menuDisplayed} isExpanded={menuDisplayed}
title={_t('Emoji picker')} title={_t('Emoji picker')}
inputRef={button} inputRef={button}
> />
</ContextMenuTooltipButton>
{ contextMenu } { contextMenu }
</React.Fragment>; </React.Fragment>;
@ -439,7 +437,8 @@ export default class MessageComposer extends React.Component<IProps, IState> {
if (secondsLeft) { if (secondsLeft) {
recordingTooltip = <Tooltip recordingTooltip = <Tooltip
label={_t("%(seconds)ss left", { seconds: secondsLeft })} label={_t("%(seconds)ss left", { seconds: secondsLeft })}
alignment={Alignment.Top} yOffset={-50} alignment={Alignment.Top}
yOffset={-50}
/>; />;
} }

View file

@ -58,13 +58,18 @@ const NewRoomIntro = () => {
const member = room?.getMember(dmPartner); const member = room?.getMember(dmPartner);
const displayName = member?.rawDisplayName || dmPartner; const displayName = member?.rawDisplayName || dmPartner;
body = <React.Fragment> body = <React.Fragment>
<RoomAvatar room={room} width={AVATAR_SIZE} height={AVATAR_SIZE} onClick={() => { <RoomAvatar
room={room}
width={AVATAR_SIZE}
height={AVATAR_SIZE}
onClick={() => {
defaultDispatcher.dispatch<ViewUserPayload>({ defaultDispatcher.dispatch<ViewUserPayload>({
action: Action.ViewUser, action: Action.ViewUser,
// XXX: We should be using a real member object and not assuming what the receiver wants. // XXX: We should be using a real member object and not assuming what the receiver wants.
member: member || { userId: dmPartner } as User, member: member || { userId: dmPartner } as User,
}); });
}} /> }}
/>
<h2>{ room.name }</h2> <h2>{ room.name }</h2>

View file

@ -192,7 +192,9 @@ export default class ReadReceiptMarker extends React.PureComponent {
member={this.props.member} member={this.props.member}
fallbackUserId={this.props.fallbackUserId} fallbackUserId={this.props.fallbackUserId}
aria-hidden="true" aria-hidden="true"
width={14} height={14} resizeMethod="crop" width={14}
height={14}
resizeMethod="crop"
style={style} style={style}
title={title} title={title}
onClick={this.props.onClick} onClick={this.props.onClick}

View file

@ -105,7 +105,9 @@ export default class RoomBreadcrumbs extends React.PureComponent<IProps, IState>
// NOTE: The CSSTransition timeout MUST match the timeout in our CSS! // NOTE: The CSSTransition timeout MUST match the timeout in our CSS!
return ( return (
<CSSTransition <CSSTransition
appear={true} in={this.state.doAnimation} timeout={640} appear={true}
in={this.state.doAnimation}
timeout={640}
classNames='mx_RoomBreadcrumbs' classNames='mx_RoomBreadcrumbs'
> >
<Toolbar className='mx_RoomBreadcrumbs' aria-label={_t("Recently visited rooms")}> <Toolbar className='mx_RoomBreadcrumbs' aria-label={_t("Recently visited rooms")}>

View file

@ -105,8 +105,12 @@ export default class RoomDetailRow extends React.Component {
return <tr key={room.roomId} onClick={this.onClick} onMouseDown={this.props.onMouseDown}> return <tr key={room.roomId} onClick={this.onClick} onMouseDown={this.props.onMouseDown}>
<td className="mx_RoomDirectory_roomAvatar"> <td className="mx_RoomDirectory_roomAvatar">
<BaseAvatar width={24} height={24} resizeMethod='crop' <BaseAvatar
name={name} idName={name} width={24}
height={24}
resizeMethod='crop'
name={name}
idName={name}
url={avatarUrl} /> url={avatarUrl} />
</td> </td>
<td className="mx_RoomDirectory_roomDescription"> <td className="mx_RoomDirectory_roomDescription">

View file

@ -428,7 +428,9 @@ export default class RoomList extends React.PureComponent<IProps, IState> {
groupId={g.groupId} groupId={g.groupId}
groupName={g.name} groupName={g.name}
groupAvatarUrl={g.avatarUrl} groupAvatarUrl={g.avatarUrl}
width={32} height={32} resizeMethod='crop' width={32}
height={32}
resizeMethod='crop'
/> />
); );
const openGroup = () => { const openGroup = () => {

View file

@ -536,8 +536,10 @@ export default class RoomPreviewBar extends React.Component {
"If you think you're seeing this message in error, please " + "If you think you're seeing this message in error, please " +
"<issueLink>submit a bug report</issueLink>.", "<issueLink>submit a bug report</issueLink>.",
{ errcode: this.props.error.errcode }, { errcode: this.props.error.errcode },
{ issueLink: label => <a href="https://github.com/vector-im/element-web/issues/new/choose" { issueLink: label => <a
target="_blank" rel="noreferrer noopener">{ label }</a> }, href="https://github.com/vector-im/element-web/issues/new/choose"
target="_blank"
rel="noreferrer noopener">{ label }</a> },
), ),
]; ];
break; break;

View file

@ -35,13 +35,15 @@ export default class SimpleRoomHeader extends React.Component {
let icon; let icon;
if (this.props.icon) { if (this.props.icon) {
icon = <img icon = <img
className="mx_RoomHeader_icon" src={this.props.icon} className="mx_RoomHeader_icon"
width="25" height="25" src={this.props.icon}
width="25"
height="25"
/>; />;
} }
return ( return (
<div className="mx_RoomHeader mx_RoomHeader_wrapper" > <div className="mx_RoomHeader mx_RoomHeader_wrapper">
<div className="mx_RoomHeader_simpleHeader"> <div className="mx_RoomHeader_simpleHeader">
{ icon } { icon }
{ this.props.title } { this.props.title }

View file

@ -403,8 +403,7 @@ export default class Stickerpicker extends React.PureComponent {
onClick={this._onHideStickersClick} onClick={this._onHideStickersClick}
active={this.state.showStickers.toString()} active={this.state.showStickers.toString()}
title={_t("Hide Stickers")} title={_t("Hide Stickers")}
> />;
</AccessibleButton>;
const GenericElementContextMenu = sdk.getComponent('context_menus.GenericElementContextMenu'); const GenericElementContextMenu = sdk.getComponent('context_menus.GenericElementContextMenu');
stickerPicker = <ContextMenu stickerPicker = <ContextMenu
@ -431,8 +430,7 @@ export default class Stickerpicker extends React.PureComponent {
className="mx_MessageComposer_button mx_MessageComposer_stickers" className="mx_MessageComposer_button mx_MessageComposer_stickers"
onClick={this._onShowStickersClick} onClick={this._onShowStickersClick}
title={_t("Show Stickers")} title={_t("Show Stickers")}
> />;
</AccessibleTooltipButton>;
} }
return <React.Fragment> return <React.Fragment>
{ stickersButton } { stickersButton }

View file

@ -32,14 +32,16 @@ export default class TopUnreadMessagesBar extends React.Component {
render() { render() {
return ( return (
<div className="mx_TopUnreadMessagesBar"> <div className="mx_TopUnreadMessagesBar">
<AccessibleButton className="mx_TopUnreadMessagesBar_scrollUp" <AccessibleButton
className="mx_TopUnreadMessagesBar_scrollUp"
title={_t('Jump to first unread message.')} title={_t('Jump to first unread message.')}
onClick={this.props.onScrollUpClick}> onClick={this.props.onScrollUpClick}
</AccessibleButton> />
<AccessibleButton className="mx_TopUnreadMessagesBar_markAsRead" <AccessibleButton
className="mx_TopUnreadMessagesBar_markAsRead"
title={_t('Mark all as read')} title={_t('Mark all as read')}
onClick={this.props.onCloseClick}> onClick={this.props.onCloseClick}
</AccessibleButton> />
</div> </div>
); );
} }

View file

@ -124,7 +124,7 @@ export default class BridgeTile extends React.PureComponent<IProps> {
url={avatarUrl} url={avatarUrl}
/>; />;
} else { } else {
networkIcon = <div className="noProtocolIcon"></div>; networkIcon = <div className="noProtocolIcon" />;
} }
let networkItem = null; let networkItem = null;
if (network) { if (network) {

View file

@ -148,13 +148,22 @@ export default class ChangeAvatar extends React.Component {
if (this.props.room && !this.avatarSet) { if (this.props.room && !this.avatarSet) {
const RoomAvatar = sdk.getComponent('avatars.RoomAvatar'); const RoomAvatar = sdk.getComponent('avatars.RoomAvatar');
avatarImg = <RoomAvatar avatarImg = <RoomAvatar
room={this.props.room} width={this.props.width} height={this.props.height} resizeMethod='crop' room={this.props.room}
width={this.props.width}
height={this.props.height}
resizeMethod='crop'
/>; />;
} else { } else {
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
name='?' idName={MatrixClientPeg.get().getUserIdLocalpart()} url={this.state.avatarUrl} />; width={this.props.width}
height={this.props.height}
resizeMethod='crop'
name='?'
idName={MatrixClientPeg.get().getUserIdLocalpart()}
url={this.state.avatarUrl}
/>;
} }
let uploadSection; let uploadSection;

View file

@ -178,8 +178,11 @@ export default class EventIndexPanel extends React.Component<{}, IState> {
"appear in search results.", "appear in search results.",
) }</div> ) }</div>
<div> <div>
<AccessibleButton kind="primary" disabled={this.state.enabling} <AccessibleButton
onClick={this.onEnable}> kind="primary"
disabled={this.state.enabling}
onClick={this.onEnable}
>
{ _t("Enable") } { _t("Enable") }
</AccessibleButton> </AccessibleButton>
{ this.state.enabling ? <InlineSpinner /> : <div /> } { this.state.enabling ? <InlineSpinner /> : <div /> }
@ -203,8 +206,10 @@ export default class EventIndexPanel extends React.Component<{}, IState> {
brand, brand,
}, },
{ {
nativeLink: sub => <a href={nativeLink} nativeLink: sub => <a
target="_blank" rel="noreferrer noopener" href={nativeLink}
target="_blank"
rel="noreferrer noopener"
>{ sub }</a>, >{ sub }</a>,
}, },
) }</div> ) }</div>
@ -219,8 +224,10 @@ export default class EventIndexPanel extends React.Component<{}, IState> {
brand, brand,
}, },
{ {
desktopLink: sub => <a href="https://element.io/get-started" desktopLink: sub => <a
target="_blank" rel="noreferrer noopener" href="https://element.io/get-started"
target="_blank"
rel="noreferrer noopener"
>{ sub }</a>, >{ sub }</a>,
}, },
) }</div> ) }</div>

View file

@ -172,7 +172,8 @@ export default class ProfileSettings extends React.Component {
> >
<input <input
type="file" type="file"
ref={this._avatarUpload} className="mx_ProfileSettings_avatarUpload" ref={this._avatarUpload}
className="mx_ProfileSettings_avatarUpload"
onChange={this._onAvatarChanged} onChange={this._onAvatarChanged}
accept="image/*" accept="image/*"
/> />
@ -181,7 +182,8 @@ export default class ProfileSettings extends React.Component {
<span className="mx_SettingsTab_subheading">{ _t("Profile") }</span> <span className="mx_SettingsTab_subheading">{ _t("Profile") }</span>
<Field <Field
label={_t("Display Name")} label={_t("Display Name")}
type="text" value={this.state.displayName} type="text"
value={this.state.displayName}
autoComplete="off" autoComplete="off"
onChange={this._onDisplayNameChanged} onChange={this._onDisplayNameChanged}
/> />

View file

@ -426,7 +426,9 @@ export default class SetIdServer extends React.Component<IProps, IState> {
disabled={this.state.busy} disabled={this.state.busy}
forceValidity={this.state.error ? false : null} forceValidity={this.state.error ? false : null}
/> />
<AccessibleButton type="submit" kind="primary_sm" <AccessibleButton
type="submit"
kind="primary_sm"
onClick={this.checkIdServer} onClick={this.checkIdServer}
disabled={!this.idServerChangeEnabled()} disabled={!this.idServerChangeEnabled()}
>{ _t("Change") }</AccessibleButton> >{ _t("Change") }</AccessibleButton>

View file

@ -97,9 +97,12 @@ 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
canSetCanonicalAlias={canSetCanonical} canSetAliases={canSetAliases} roomId={this.props.roomId}
canonicalAliasEvent={canonicalAliasEv} /> canSetCanonicalAlias={canSetCanonical}
canSetAliases={canSetAliases}
canonicalAliasEvent={canonicalAliasEv}
/>
</div> </div>
<div className="mx_SettingsTab_heading">{ _t("Other") }</div> <div className="mx_SettingsTab_heading">{ _t("Other") }</div>
{ flairSection } { flairSection }

View file

@ -346,8 +346,11 @@ export default class RolesRoomSettingsTab extends React.Component<IProps> {
let bannedBy = member.events.member.getSender(); // start by falling back to mxid let bannedBy = member.events.member.getSender(); // start by falling back to mxid
if (sender) bannedBy = sender.name; if (sender) bannedBy = sender.name;
return ( return (
<BannedUser key={member.userId} canUnban={canBanUsers} <BannedUser
member={member} reason={banEvent.reason} key={member.userId}
canUnban={canBanUsers}
member={member}
reason={banEvent.reason}
by={bannedBy} by={bannedBy}
/> />
); );

View file

@ -133,8 +133,10 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
"may prevent many bots and bridges from working correctly. <a>Learn more about encryption.</a>", "may prevent many bots and bridges from working correctly. <a>Learn more about encryption.</a>",
{}, {},
{ {
a: sub => <a href="https://element.io/help#encryption" a: sub => <a
rel="noreferrer noopener" target="_blank" href="https://element.io/help#encryption"
rel="noreferrer noopener"
target="_blank"
>{ sub }</a>, >{ sub }</a>,
}, },
), ),
@ -424,8 +426,11 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
<div className='mx_SettingsTab_subsectionText'> <div className='mx_SettingsTab_subsectionText'>
<span>{ _t("Once enabled, encryption cannot be disabled.") }</span> <span>{ _t("Once enabled, encryption cannot be disabled.") }</span>
</div> </div>
<LabelledToggleSwitch value={isEncrypted} onChange={this.onEncryptionChange} <LabelledToggleSwitch
label={_t("Encrypted")} disabled={!canEnableEncryption} value={isEncrypted}
onChange={this.onEncryptionChange}
label={_t("Encrypted")}
disabled={!canEnableEncryption}
/> />
</div> </div>
{ encryptionSettings } { encryptionSettings }

View file

@ -303,9 +303,12 @@ export default class AppearanceUserSettingsTab extends React.Component<IProps, I
/> />
<AccessibleButton <AccessibleButton
onClick={this.onAddCustomTheme} onClick={this.onAddCustomTheme}
type="submit" kind="primary_sm" type="submit"
kind="primary_sm"
disabled={!this.state.customThemeUrl.trim()} disabled={!this.state.customThemeUrl.trim()}
>{ _t("Add theme") }</AccessibleButton> >
{ _t("Add theme") }
</AccessibleButton>
{ messageElement } { messageElement }
</form> </form>
</div> </div>

View file

@ -426,9 +426,13 @@ export default class GeneralUserSettingsTab extends React.Component {
const supportsMultiLanguageSpellCheck = plaf.supportsMultiLanguageSpellCheck(); const supportsMultiLanguageSpellCheck = plaf.supportsMultiLanguageSpellCheck();
const discoWarning = this.state.requiredPolicyInfo.hasTerms const discoWarning = this.state.requiredPolicyInfo.hasTerms
? <img className='mx_GeneralUserSettingsTab_warningIcon' ? <img
className='mx_GeneralUserSettingsTab_warningIcon'
src={require("../../../../../../res/img/feather-customised/warning-triangle.svg")} src={require("../../../../../../res/img/feather-customised/warning-triangle.svg")}
width="18" height="18" alt={_t("Warning")} /> width="18"
height="18"
alt={_t("Warning")}
/>
: null; : null;
let accountManagementSection; let accountManagementSection;

View file

@ -134,28 +134,39 @@ export default class HelpUserSettingsTab extends React.Component<IProps, IState>
<span className='mx_SettingsTab_subheading'>{ _t("Credits") }</span> <span className='mx_SettingsTab_subheading'>{ _t("Credits") }</span>
<ul> <ul>
<li> <li>
The <a href="themes/element/img/backgrounds/lake.jpg" rel="noreferrer noopener" The <a href="themes/element/img/backgrounds/lake.jpg" rel="noreferrer noopener" target="_blank">
target="_blank">default cover photo</a> is ©&nbsp; default cover photo
<a href="https://www.flickr.com/golan" rel="noreferrer noopener" </a> is ©&nbsp;
target="_blank">Jesús Roncero</a> used under the terms of&nbsp; <a href="https://www.flickr.com/golan" rel="noreferrer noopener" target="_blank">
<a href="https://creativecommons.org/licenses/by-sa/4.0/" rel="noreferrer noopener" Jesús Roncero
target="_blank">CC-BY-SA 4.0</a>. </a> used under the terms of&nbsp;
<a href="https://creativecommons.org/licenses/by-sa/4.0/" rel="noreferrer noopener" target="_blank">
CC-BY-SA 4.0
</a>.
</li> </li>
<li> <li>
The <a href="https://github.com/matrix-org/twemoji-colr" rel="noreferrer noopener" The <a
target="_blank">twemoji-colr</a> font is ©&nbsp; href="https://github.com/matrix-org/twemoji-colr"
<a href="https://mozilla.org" rel="noreferrer noopener" rel="noreferrer noopener"
target="_blank">Mozilla Foundation</a> used under the terms of&nbsp; target="_blank"
<a href="http://www.apache.org/licenses/LICENSE-2.0" rel="noreferrer noopener" >
target="_blank">Apache 2.0</a>. twemoji-colr
</a> font is ©&nbsp;
<a href="https://mozilla.org" rel="noreferrer noopener" target="_blank">
Mozilla Foundation
</a> used under the terms of&nbsp;
<a href="http://www.apache.org/licenses/LICENSE-2.0" rel="noreferrer noopener" target="_blank">Apache 2.0</a>.
</li> </li>
<li> <li>
The <a href="https://twemoji.twitter.com/" rel="noreferrer noopener" The <a href="https://twemoji.twitter.com/" rel="noreferrer noopener" target="_blank">
target="_blank">Twemoji</a> emoji art is ©&nbsp; Twemoji
<a href="https://twemoji.twitter.com/" rel="noreferrer noopener" </a> emoji art is ©&nbsp;
target="_blank">Twitter, Inc and other contributors</a> used under the terms of&nbsp; <a href="https://twemoji.twitter.com/" rel="noreferrer noopener" target="_blank">
<a href="https://creativecommons.org/licenses/by/4.0/" rel="noreferrer noopener" Twitter, Inc and other contributors
target="_blank">CC-BY 4.0</a>. </a> used under the terms of&nbsp;
<a href="https://creativecommons.org/licenses/by/4.0/" rel="noreferrer noopener" target="_blank">
CC-BY 4.0
</a>.
</li> </li>
</ul> </ul>
</div> </div>
@ -254,7 +265,8 @@ export default class HelpUserSettingsTab extends React.Component<IProps, IState>
"<a>Security Disclosure Policy</a>.", {}, "<a>Security Disclosure Policy</a>.", {},
{ {
a: sub => <a href="https://matrix.org/security-disclosure-policy/" a: sub => <a href="https://matrix.org/security-disclosure-policy/"
rel="noreferrer noopener" target="_blank" rel="noreferrer noopener"
target="_blank"
>{ sub }</a>, >{ sub }</a>,
}, },
) } ) }

View file

@ -86,8 +86,11 @@ export default class LabsUserSettingsTab extends React.Component {
'test out new features and help shape them before they actually launch. ' + 'test out new features and help shape them before they actually launch. ' +
'<a>Learn more</a>.', {}, { '<a>Learn more</a>.', {}, {
'a': (sub) => { 'a': (sub) => {
return <a href="https://github.com/vector-im/element-web/blob/develop/docs/labs.md" return <a
rel='noreferrer noopener' target='_blank'>{ sub }</a>; href="https://github.com/vector-im/element-web/blob/develop/docs/labs.md"
rel='noreferrer noopener'
target='_blank'
>{ sub }</a>;
}, },
}) })
} }

View file

@ -57,11 +57,15 @@ export const SpaceAvatar = ({
src={avatar} src={avatar}
alt="" alt=""
/> />
<AccessibleButton onClick={() => { <AccessibleButton
onClick={() => {
avatarUploadRef.current.value = ""; avatarUploadRef.current.value = "";
setAvatarDataUrl(undefined); setAvatarDataUrl(undefined);
setAvatar(undefined); setAvatar(undefined);
}} kind="link" className="mx_SpaceBasicSettings_avatar_remove"> }}
kind="link"
className="mx_SpaceBasicSettings_avatar_remove"
>
{ _t("Delete") } { _t("Delete") }
</AccessibleButton> </AccessibleButton>
</React.Fragment>; </React.Fragment>;
@ -77,7 +81,10 @@ export const SpaceAvatar = ({
return <div className="mx_SpaceBasicSettings_avatarContainer"> return <div className="mx_SpaceBasicSettings_avatarContainer">
{ avatarSection } { avatarSection }
<input type="file" ref={avatarUploadRef} onChange={(e) => { <input
type="file"
ref={avatarUploadRef}
onChange={(e) => {
if (!e.target.files?.length) return; if (!e.target.files?.length) return;
const file = e.target.files[0]; const file = e.target.files[0];
setAvatar(file); setAvatar(file);
@ -86,7 +93,9 @@ export const SpaceAvatar = ({
setAvatarDataUrl(ev.target.result as string); setAvatarDataUrl(ev.target.result as string);
}; };
reader.readAsDataURL(file); reader.readAsDataURL(file);
}} accept="image/*" /> }}
accept="image/*"
/>
</div>; </div>;
}; };

View file

@ -665,15 +665,19 @@ export default class CallView extends React.Component<IProps, IState> {
let fullScreenButton; let fullScreenButton;
if (this.props.call.type === CallType.Video && !this.props.pipMode) { if (this.props.call.type === CallType.Video && !this.props.pipMode) {
fullScreenButton = <div className="mx_CallView_header_button mx_CallView_header_button_fullscreen" fullScreenButton = <div
onClick={this.onFullscreenClick} title={_t("Fill Screen")} className="mx_CallView_header_button mx_CallView_header_button_fullscreen"
onClick={this.onFullscreenClick}
title={_t("Fill Screen")}
/>; />;
} }
let expandButton; let expandButton;
if (this.props.pipMode) { if (this.props.pipMode) {
expandButton = <div className="mx_CallView_header_button mx_CallView_header_button_expand" expandButton = <div
onClick={this.onExpandClick} title={_t("Return to call")} className="mx_CallView_header_button mx_CallView_header_button_expand"
onClick={this.onExpandClick}
title={_t("Return to call")}
/>; />;
} }
@ -685,7 +689,7 @@ export default class CallView extends React.Component<IProps, IState> {
let header: React.ReactNode; let header: React.ReactNode;
if (!this.props.pipMode) { if (!this.props.pipMode) {
header = <div className="mx_CallView_header"> header = <div className="mx_CallView_header">
<div className="mx_CallView_header_phoneIcon"></div> <div className="mx_CallView_header_phoneIcon" />
<span className="mx_CallView_header_callType">{ callTypeText }</span> <span className="mx_CallView_header_callType">{ callTypeText }</span>
{ headerControls } { headerControls }
</div>; </div>;

View file

@ -68,13 +68,19 @@ export default class Dialpad extends React.PureComponent<IProps> {
for (let i = 0; i < BUTTONS.length; i++) { for (let i = 0; i < BUTTONS.length; i++) {
const button = BUTTONS[i]; const button = BUTTONS[i];
const digitSubtext = BUTTON_LETTERS[i]; const digitSubtext = BUTTON_LETTERS[i];
buttonNodes.push(<DialPadButton key={button} kind={DialPadButtonKind.Digit} buttonNodes.push(<DialPadButton
digit={button} digitSubtext={digitSubtext} onButtonPress={this.props.onDigitPress} key={button}
kind={DialPadButtonKind.Digit}
digit={button}
digitSubtext={digitSubtext}
onButtonPress={this.props.onDigitPress}
/>); />);
} }
if (this.props.hasDial) { if (this.props.hasDial) {
buttonNodes.push(<DialPadButton key="dial" kind={DialPadButtonKind.Dial} buttonNodes.push(<DialPadButton
key="dial"
kind={DialPadButtonKind.Dial}
onButtonPress={this.props.onDialPress} onButtonPress={this.props.onDialPress}
/>); />);
} }

View file

@ -81,14 +81,18 @@ export default class DialpadModal extends React.PureComponent<IProps, IState> {
// Only show the backspace button if the field has content // Only show the backspace button if the field has content
let dialPadField; let dialPadField;
if (this.state.value.length !== 0) { if (this.state.value.length !== 0) {
dialPadField = <Field className="mx_DialPadModal_field" id="dialpad_number" dialPadField = <Field
className="mx_DialPadModal_field"
id="dialpad_number"
value={this.state.value} value={this.state.value}
autoFocus={true} autoFocus={true}
onChange={this.onChange} onChange={this.onChange}
postfixComponent={backspaceButton} postfixComponent={backspaceButton}
/>; />;
} else { } else {
dialPadField = <Field className="mx_DialPadModal_field" id="dialpad_number" dialPadField = <Field
className="mx_DialPadModal_field"
id="dialpad_number"
value={this.state.value} value={this.state.value}
autoFocus={true} autoFocus={true}
onChange={this.onChange} onChange={this.onChange}

View file

@ -136,7 +136,7 @@ export default class VideoFeed extends React.Component<IProps, IState> {
const avatarSize = this.props.pipMode ? 76 : 160; const avatarSize = this.props.pipMode ? 76 : 160;
return ( return (
<div className={classnames(videoClasses)} > <div className={classnames(videoClasses)}>
<MemberAvatar <MemberAvatar
member={member} member={member}
height={avatarSize} height={avatarSize}

View file

@ -312,8 +312,12 @@ describe('MessagePanel', function() {
it('should insert the read-marker in the right place', function() { it('should insert the read-marker in the right place', function() {
const res = TestUtils.renderIntoDocument( const res = TestUtils.renderIntoDocument(
<WrappedMessagePanel className="cls" events={events} readMarkerEventId={events[4].getId()} <WrappedMessagePanel
readMarkerVisible={true} />, className="cls"
events={events}
readMarkerEventId={events[4].getId()}
readMarkerVisible={true}
/>,
); );
const tiles = TestUtils.scryRenderedComponentsWithType( const tiles = TestUtils.scryRenderedComponentsWithType(
@ -330,8 +334,12 @@ describe('MessagePanel', function() {
it('should show the read-marker that fall in summarised events after the summary', function() { it('should show the read-marker that fall in summarised events after the summary', function() {
const melsEvents = mkMelsEvents(); const melsEvents = mkMelsEvents();
const res = TestUtils.renderIntoDocument( const res = TestUtils.renderIntoDocument(
<WrappedMessagePanel className="cls" events={melsEvents} readMarkerEventId={melsEvents[4].getId()} <WrappedMessagePanel
readMarkerVisible={true} />, className="cls"
events={melsEvents}
readMarkerEventId={melsEvents[4].getId()}
readMarkerVisible={true}
/>,
); );
const summary = TestUtils.findRenderedDOMComponentWithClass(res, 'mx_EventListSummary'); const summary = TestUtils.findRenderedDOMComponentWithClass(res, 'mx_EventListSummary');
@ -348,8 +356,12 @@ describe('MessagePanel', function() {
it('should hide the read-marker at the end of summarised events', function() { it('should hide the read-marker at the end of summarised events', function() {
const melsEvents = mkMelsEventsOnly(); const melsEvents = mkMelsEventsOnly();
const res = TestUtils.renderIntoDocument( const res = TestUtils.renderIntoDocument(
<WrappedMessagePanel className="cls" events={melsEvents} readMarkerEventId={melsEvents[9].getId()} <WrappedMessagePanel
readMarkerVisible={true} />, className="cls"
events={melsEvents}
readMarkerEventId={melsEvents[9].getId()}
readMarkerVisible={true}
/>,
); );
const summary = TestUtils.findRenderedDOMComponentWithClass(res, 'mx_EventListSummary'); const summary = TestUtils.findRenderedDOMComponentWithClass(res, 'mx_EventListSummary');
@ -371,7 +383,10 @@ describe('MessagePanel', function() {
// first render with the RM in one place // first render with the RM in one place
let mp = ReactDOM.render( let mp = ReactDOM.render(
<WrappedMessagePanel className="cls" events={events} readMarkerEventId={events[4].getId()} <WrappedMessagePanel
className="cls"
events={events}
readMarkerEventId={events[4].getId()}
readMarkerVisible={true} readMarkerVisible={true}
/>, parentDiv); />, parentDiv);
@ -387,7 +402,10 @@ describe('MessagePanel', function() {
// now move the RM // now move the RM
mp = ReactDOM.render( mp = ReactDOM.render(
<WrappedMessagePanel className="cls" events={events} readMarkerEventId={events[6].getId()} <WrappedMessagePanel
className="cls"
events={events}
readMarkerEventId={events[6].getId()}
readMarkerVisible={true} readMarkerVisible={true}
/>, parentDiv); />, parentDiv);