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."),
button: _t("Create Account"),
extraButtons: [
<button key="start_login" onClick={() => {
modal.close();
dis.dispatch({ action: 'start_login', screenAfterLogin: options.screen_after });
}}>{ _t('Sign In') }</button>,
<button
key="start_login"
onClick={() => {
modal.close();
dis.dispatch({ action: 'start_login', screenAfterLogin: options.screen_after });
}}
>
{ _t('Sign In') }
</button>,
],
onFinished: (proceed) => {
if (proceed) {

View File

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

View File

@ -474,7 +474,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
outlined
>
<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") }
</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
>
<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") }
</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>
</div>
<div className="mx_CreateSecretStorageDialog_recoveryKeyButtons">
<AccessibleButton kind='primary' className="mx_Dialog_primary"
<AccessibleButton kind='primary'
className="mx_Dialog_primary"
onClick={this._onDownloadClick}
disabled={this.state.phase === PHASE_STORING}
>

View File

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

View File

@ -174,7 +174,10 @@ export default class ImportE2eKeysDialog extends React.Component {
</div>
</div>
<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}
/>
<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`}
dangerouslySetInnerHTML={{ __html: this.state.page }}
>
</div>;
/>;
if (this.props.scrollbar) {
return <AutoHideScrollbar className={classes}>

View File

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

View File

@ -266,8 +266,12 @@ export default class RoomStatusBar extends React.PureComponent {
<div className="mx_RoomStatusBar">
<div role="alert">
<div className="mx_RoomStatusBar_connectionLostBar">
<img src={require("../../../res/img/feather-customised/warning-triangle.svg")} width="24"
height="24" title="/!\ " alt="/!\ " />
<img
src={require("../../../res/img/feather-customised/warning-triangle.svg")}
width="24"
height="24"
title="/!\ "
alt="/!\ " />
<div>
<div className="mx_RoomStatusBar_connectionLostBar_title">
{ _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}
onForgetClick={this.onForgetClick}
onRejectClick={this.onRejectThreepidInviteButtonClicked}
canPreview={false} error={this.state.roomLoadError}
canPreview={false}
error={this.state.roomLoadError}
roomAlias={roomAlias}
joining={this.state.joining}
inviterName={inviterName}

View File

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

View File

@ -101,12 +101,14 @@ export const SpaceFeedbackPrompt = ({ onClick }: { onClick?: () => void }) => {
<hr />
<div>
<span className="mx_SpaceFeedbackPrompt_text">{ _t("Spaces are a beta feature.") }</span>
<AccessibleButton kind="link" onClick={() => {
if (onClick) onClick();
Modal.createTrackedDialog("Beta Feedback", "feature_spaces", BetaFeedbackDialog, {
<AccessibleButton
kind="link"
onClick={() => {
if (onClick) onClick();
Modal.createTrackedDialog("Beta Feedback", "feature_spaces", BetaFeedbackDialog, {
featureId: "feature_spaces",
});
}}>
});
}}>
{ _t("Feedback") }
</AccessibleButton>
</div>
@ -553,9 +555,7 @@ const SpaceAddExistingRooms = ({ space, onFinished }) => {
onFinished={onFinished}
/>
<div className="mx_SpaceRoomView_buttons">
</div>
<div className="mx_SpaceRoomView_buttons" />
<SpaceFeedbackPrompt />
</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 " +
"link it contains, click below.", { emailAddress: this.state.email }) }
<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')} />
</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 " +
"device.",
) }</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')} />
</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>.", {},
{
'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"
>
{ sub }

View File

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

View File

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

View File

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

View File

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

View File

@ -102,8 +102,12 @@ export default class MemberAvatar extends React.Component<IProps, IState> {
}
return (
<BaseAvatar {...otherProps} name={this.state.name} title={this.state.title}
idName={userId} url={this.state.imageUrl} onClick={onClick} />
<BaseAvatar {...otherProps}
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} />
</div>
<div className="mx_DialPadContextMenu_header">
<Field className="mx_DialPadContextMenu_dialled"
value={this.state.value} autoFocus={true}
<Field
className="mx_DialPadContextMenu_dialled"
value={this.state.value}
autoFocus={true}
onChange={this.onChange}
/>
</div>

View File

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

View File

@ -76,7 +76,8 @@ const WidgetContextMenu: React.FC<IProps> = ({
onFinished();
};
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) {
const text = _t("and %(count)s others...", { count: overflowCount });
return (
<EntityTile className="mx_EntityTile_ellipsis" avatarJsx={
<BaseAvatar url={require("../../../../res/img/ellipsis.svg")} name="..." width={36} height={36} />
} name={text} presenceState="online" suppressOnHover={true}
onClick={() => setTruncateAt(totalCount)} />
<EntityTile
className="mx_EntityTile_ellipsis"
avatarJsx={
<BaseAvatar url={require("../../../../res/img/ellipsis.svg")} name="..." width={36} height={36} />
}
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}
placeholder={this.getPlaceholder()}
defaultValue={this.props.value}
autoFocus={this.props.focus}>
</textarea>,
autoFocus={this.props.focus}
/>,
);
const filteredSuggestedList = this.getFilteredSuggestions();
@ -727,8 +727,12 @@ export default class AddressPickerDialog extends React.Component<IProps, IState>
}
return (
<BaseDialog className="mx_AddressPickerDialog" onKeyDown={this.onKeyDown}
onFinished={this.props.onFinished} title={this.props.title}>
<BaseDialog
className="mx_AddressPickerDialog"
onKeyDown={this.onKeyDown}
onFinished={this.props.onFinished}
title={this.props.title}
>
{ inputLabel }
<div className="mx_Dialog_content">
<div className="mx_AddressPickerDialog_inputContainer">{ query }</div>

View File

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

View File

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

View File

@ -188,7 +188,9 @@ export default class BugReportDialog extends React.Component<IProps, IState> {
}
return (
<BaseDialog className="mx_BugReportDialog" onFinished={this.onCancel}
<BaseDialog
className="mx_BugReportDialog"
onFinished={this.onCancel}
title={_t('Submit debug logs')}
contentId='mx_Dialog_content'
>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -106,12 +106,12 @@ const Entry: React.FC<IEntryProps> = ({ room, event, matrixClient: cli, onFinish
className = "mx_ForwardList_sending";
disabled = true;
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) {
className = "mx_ForwardList_sent";
disabled = true;
title = _t("Sent");
icon = <div className="mx_ForwardList_sendIcon" aria-label={title}></div>;
icon = <div className="mx_ForwardList_sendIcon" aria-label={title} />;
} else {
className = "mx_ForwardList_sendFailed";
disabled = true;
@ -204,10 +204,16 @@ const ForwardDialog: React.FC<IProps> = ({ matrixClient: cli, event, permalinkCr
function overflowTile(overflowCount, totalCount) {
const text = _t("and %(count)s others...", { count: overflowCount });
return (
<EntityTile className="mx_EntityTile_ellipsis" avatarJsx={
<BaseAvatar url={require("../../../../res/img/ellipsis.svg")} name="..." width={36} height={36} />
} name={text} presenceState="online" suppressOnHover={true}
onClick={() => setTruncateAt(totalCount)} />
<EntityTile
className="mx_EntityTile_ellipsis"
avatarJsx={
<BaseAvatar url={require("../../../../res/img/ellipsis.svg")} name="..." width={36} height={36} />
}
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)
: null;
profile = <div className="mx_IncomingSasDialog_opponentProfile">
<BaseAvatar name={oppProfile.displayname}
<BaseAvatar
name={oppProfile.displayname}
idName={this.props.verifier.userId}
url={url}
width={48} height={48} resizeMethod='crop'
width={48}
height={48}
resizeMethod='crop'
/>
<h2>{ oppProfile.displayname }</h2>
</div>;
} else if (this.state.opponentProfileError) {
profile = <div>
<BaseAvatar name={this.props.verifier.userId.slice(1)}
<BaseAvatar
name={this.props.verifier.userId.slice(1)}
idName={this.props.verifier.userId}
width={48} height={48}
width={48}
height={48}
/>
<h2>{ this.props.verifier.userId }</h2>
</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')}
onPrimaryButtonClick={this.onFinished}
hasCancel={false}
>
</DialogButtons> }
/> }
</BaseDialog>
);
}

View File

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

View File

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

View File

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

View File

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

View File

@ -399,7 +399,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
let keyStatus;
if (this.state.recoveryKey.length === 0) {
keyStatus = <div className="mx_RestoreKeyBackupDialog_keyStatus"></div>;
keyStatus = <div className="mx_RestoreKeyBackupDialog_keyStatus" />;
} else if (this.state.recoveryKeyValid) {
keyStatus = <div className="mx_RestoreKeyBackupDialog_keyStatus">
{ "\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;
if (this.props.canDismiss) {
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" />
</div>
);

View File

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

View File

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

View File

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

View File

@ -258,7 +258,10 @@ class Pill extends React.Component {
linkText = groupId;
if (this.props.shouldShowPillAvatar) {
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} />;
}
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;
if (this.state.custom) {
picker = (
<Field type="number"
label={label} max={this.props.maxValue}
<Field
type="number"
label={label}
max={this.props.maxValue}
onBlur={this.onCustomBlur}
onKeyDown={this.onCustomKeyDown}
onChange={this.onCustomChange}
@ -157,9 +159,12 @@ export default class PowerSelector extends React.Component {
});
picker = (
<Field element="select"
label={label} onChange={this.onSelectChange}
value={String(this.state.selectValue)} disabled={this.props.disabled}
<Field
element="select"
label={label}
onChange={this.onSelectChange}
value={String(this.state.selectValue)}
disabled={this.props.disabled}
>
{ options }
</Field>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -306,7 +306,10 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
imageElement = <HiddenImagePlaceholder />;
} else {
imageElement = (
<img style={{ display: 'none' }} src={thumbUrl} ref={this.image}
<img
style={{ display: 'none' }}
src={thumbUrl}
ref={this.image}
alt={content.body}
onError={this.onImageError}
onLoad={this.onImageLoad}
@ -340,7 +343,10 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
// which has the same width as the timeline
// mx_MImageBody_thumbnail resizes img to exactly container size
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" }}
alt={content.body}
onError={this.onImageError}
@ -360,12 +366,15 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
}
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 &&
<div className="mx_MImageBody_thumbnail" style={{
// Constrain width here so that spinner appears central to the loaded thumbnail
maxWidth: infoWidth + "px",
}}>
<div
className="mx_MImageBody_thumbnail"
style={{
// Constrain width here so that spinner appears central to the loaded thumbnail
maxWidth: infoWidth + "px",
}}
>
{ placeholder }
</div>
}

View File

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

View File

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

View File

@ -205,7 +205,7 @@ function DeviceItem({ userId, device }: {userId: string, device: IDevice}) {
if (isVerified) {
return (
<div className={classes} title={device.deviceId} >
<div className={classes} title={device.deviceId}>
<div className={iconClasses} />
<div className="mx_UserInfo_device_name">{ deviceName }</div>
<div className="mx_UserInfo_device_trusted">{ trustedLabel }</div>
@ -1353,13 +1353,16 @@ const BasicUserInfo: React.FC<{
if (hasCrossSigningKeys !== undefined) {
// Note: mx_UserInfo_verifyButton is for the end-to-end tests
verifyButton = (
<AccessibleButton className="mx_UserInfo_field mx_UserInfo_verifyButton" onClick={() => {
if (hasCrossSigningKeys) {
verifyUser(member as User);
} else {
legacyVerifyUser(member as User);
}
}}>
<AccessibleButton
className="mx_UserInfo_field mx_UserInfo_verifyButton"
onClick={() => {
if (hasCrossSigningKeys) {
verifyUser(member as User);
} else {
legacyVerifyUser(member as User);
}
}}
>
{ _t("Verify") }
</AccessibleButton>
);
@ -1374,12 +1377,15 @@ const BasicUserInfo: React.FC<{
let editDevices;
if (member.userId == cli.getUserId()) {
editDevices = (<p>
<AccessibleButton className="mx_UserInfo_field" onClick={() => {
dis.dispatch({
<AccessibleButton
className="mx_UserInfo_field"
onClick={() => {
dis.dispatch({
action: Action.ViewUserSettings,
initialTabId: UserTab.Security,
});
}}>
});
}}
>
{ _t("Edit devices") }
</AccessibleButton>
</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)
avatars.unshift(
<ReadReceiptMarker key={userId} member={receipt.roomMember}
<ReadReceiptMarker
key={userId}
member={receipt.roomMember}
fallbackUserId={userId}
leftOffset={left} hidden={hidden}
leftOffset={left}
hidden={hidden}
readReceiptInfo={readReceiptInfo}
checkUnmounting={this.props.checkUnmounting}
suppressAnimation={this.suppressReadReceiptAnimation}
@ -949,8 +952,10 @@ export default class EventTile extends React.Component<IProps, IState> {
}
avatar = (
<div className="mx_EventTile_avatar">
<MemberAvatar member={member}
width={avatarSize} height={avatarSize}
<MemberAvatar
member={member}
width={avatarSize}
height={avatarSize}
viewUserOnClick={true}
/>
</div>

View File

@ -28,10 +28,11 @@ export default (props) => {
badge = (<div className="mx_JumpToBottomButton_badge">{ props.numUnreadMessages }</div>);
}
return (<div className={className}>
<AccessibleButton className="mx_JumpToBottomButton_scrollDown"
<AccessibleButton
className="mx_JumpToBottomButton_scrollDown"
title={_t("Scroll to most recent messages")}
onClick={props.onScrollToBottomClick}>
</AccessibleButton>
onClick={props.onScrollToBottomClick}
/>
{ badge }
</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.
const text = _t("and %(count)s others...", { count: overflowCount });
return (
<EntityTile className="mx_EntityTile_ellipsis" avatarJsx={
<BaseAvatar url={require("../../../../res/img/ellipsis.svg")} name="..." width={36} height={36} />
} name={text} presenceState="online" suppressOnHover={true}
onClick={onClick} />
<EntityTile
className="mx_EntityTile_ellipsis"
avatarJsx={
<BaseAvatar url={require("../../../../res/img/ellipsis.svg")} name="..." width={36} height={36} />
}
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} />;
} else {
// Is a 3pid invite
return <EntityTile key={m.getStateKey()} name={m.getContent().display_name} suppressOnHover={true}
onClick={() => this.onPending3pidInviteClick(m)} />;
return <EntityTile
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}
title={_t('Emoji picker')}
inputRef={button}
>
</ContextMenuTooltipButton>
/>
{ contextMenu }
</React.Fragment>;
@ -439,7 +437,8 @@ export default class MessageComposer extends React.Component<IProps, IState> {
if (secondsLeft) {
recordingTooltip = <Tooltip
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 displayName = member?.rawDisplayName || dmPartner;
body = <React.Fragment>
<RoomAvatar room={room} width={AVATAR_SIZE} height={AVATAR_SIZE} onClick={() => {
defaultDispatcher.dispatch<ViewUserPayload>({
<RoomAvatar
room={room}
width={AVATAR_SIZE}
height={AVATAR_SIZE}
onClick={() => {
defaultDispatcher.dispatch<ViewUserPayload>({
action: Action.ViewUser,
// XXX: We should be using a real member object and not assuming what the receiver wants.
member: member || { userId: dmPartner } as User,
});
}} />
});
}}
/>
<h2>{ room.name }</h2>

View File

@ -192,7 +192,9 @@ export default class ReadReceiptMarker extends React.PureComponent {
member={this.props.member}
fallbackUserId={this.props.fallbackUserId}
aria-hidden="true"
width={14} height={14} resizeMethod="crop"
width={14}
height={14}
resizeMethod="crop"
style={style}
title={title}
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!
return (
<CSSTransition
appear={true} in={this.state.doAnimation} timeout={640}
appear={true}
in={this.state.doAnimation}
timeout={640}
classNames='mx_RoomBreadcrumbs'
>
<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}>
<td className="mx_RoomDirectory_roomAvatar">
<BaseAvatar width={24} height={24} resizeMethod='crop'
name={name} idName={name}
<BaseAvatar
width={24}
height={24}
resizeMethod='crop'
name={name}
idName={name}
url={avatarUrl} />
</td>
<td className="mx_RoomDirectory_roomDescription">

View File

@ -428,7 +428,9 @@ export default class RoomList extends React.PureComponent<IProps, IState> {
groupId={g.groupId}
groupName={g.name}
groupAvatarUrl={g.avatarUrl}
width={32} height={32} resizeMethod='crop'
width={32}
height={32}
resizeMethod='crop'
/>
);
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 " +
"<issueLink>submit a bug report</issueLink>.",
{ errcode: this.props.error.errcode },
{ issueLink: label => <a href="https://github.com/vector-im/element-web/issues/new/choose"
target="_blank" rel="noreferrer noopener">{ label }</a> },
{ issueLink: label => <a
href="https://github.com/vector-im/element-web/issues/new/choose"
target="_blank"
rel="noreferrer noopener">{ label }</a> },
),
];
break;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -426,7 +426,9 @@ export default class SetIdServer extends React.Component<IProps, IState> {
disabled={this.state.busy}
forceValidity={this.state.error ? false : null}
/>
<AccessibleButton type="submit" kind="primary_sm"
<AccessibleButton
type="submit"
kind="primary_sm"
onClick={this.checkIdServer}
disabled={!this.idServerChangeEnabled()}
>{ _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_section mx_SettingsTab_subsectionText'>
<AliasSettings roomId={this.props.roomId}
canSetCanonicalAlias={canSetCanonical} canSetAliases={canSetAliases}
canonicalAliasEvent={canonicalAliasEv} />
<AliasSettings
roomId={this.props.roomId}
canSetCanonicalAlias={canSetCanonical}
canSetAliases={canSetAliases}
canonicalAliasEvent={canonicalAliasEv}
/>
</div>
<div className="mx_SettingsTab_heading">{ _t("Other") }</div>
{ 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
if (sender) bannedBy = sender.name;
return (
<BannedUser key={member.userId} canUnban={canBanUsers}
member={member} reason={banEvent.reason}
<BannedUser
key={member.userId}
canUnban={canBanUsers}
member={member}
reason={banEvent.reason}
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>",
{},
{
a: sub => <a href="https://element.io/help#encryption"
rel="noreferrer noopener" target="_blank"
a: sub => <a
href="https://element.io/help#encryption"
rel="noreferrer noopener"
target="_blank"
>{ sub }</a>,
},
),
@ -424,8 +426,11 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
<div className='mx_SettingsTab_subsectionText'>
<span>{ _t("Once enabled, encryption cannot be disabled.") }</span>
</div>
<LabelledToggleSwitch value={isEncrypted} onChange={this.onEncryptionChange}
label={_t("Encrypted")} disabled={!canEnableEncryption}
<LabelledToggleSwitch
value={isEncrypted}
onChange={this.onEncryptionChange}
label={_t("Encrypted")}
disabled={!canEnableEncryption}
/>
</div>
{ encryptionSettings }

View File

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

View File

@ -426,9 +426,13 @@ export default class GeneralUserSettingsTab extends React.Component {
const supportsMultiLanguageSpellCheck = plaf.supportsMultiLanguageSpellCheck();
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")}
width="18" height="18" alt={_t("Warning")} />
width="18"
height="18"
alt={_t("Warning")}
/>
: null;
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>
<ul>
<li>
The <a href="themes/element/img/backgrounds/lake.jpg" rel="noreferrer noopener"
target="_blank">default cover photo</a> is ©&nbsp;
<a href="https://www.flickr.com/golan" rel="noreferrer noopener"
target="_blank">Jesús Roncero</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>.
The <a href="themes/element/img/backgrounds/lake.jpg" rel="noreferrer noopener" target="_blank">
default cover photo
</a> is ©&nbsp;
<a href="https://www.flickr.com/golan" rel="noreferrer noopener" target="_blank">
Jesús Roncero
</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>
The <a href="https://github.com/matrix-org/twemoji-colr" rel="noreferrer noopener"
target="_blank">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>.
The <a
href="https://github.com/matrix-org/twemoji-colr"
rel="noreferrer noopener"
target="_blank"
>
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>
The <a href="https://twemoji.twitter.com/" rel="noreferrer noopener"
target="_blank">Twemoji</a> emoji art is ©&nbsp;
<a href="https://twemoji.twitter.com/" rel="noreferrer noopener"
target="_blank">Twitter, Inc and other contributors</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>.
The <a href="https://twemoji.twitter.com/" rel="noreferrer noopener" target="_blank">
Twemoji
</a> emoji art is ©&nbsp;
<a href="https://twemoji.twitter.com/" rel="noreferrer noopener" target="_blank">
Twitter, Inc and other contributors
</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>
</ul>
</div>
@ -254,7 +265,8 @@ export default class HelpUserSettingsTab extends React.Component<IProps, IState>
"<a>Security Disclosure Policy</a>.", {},
{
a: sub => <a href="https://matrix.org/security-disclosure-policy/"
rel="noreferrer noopener" target="_blank"
rel="noreferrer noopener"
target="_blank"
>{ 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. ' +
'<a>Learn more</a>.', {}, {
'a': (sub) => {
return <a href="https://github.com/vector-im/element-web/blob/develop/docs/labs.md"
rel='noreferrer noopener' target='_blank'>{ sub }</a>;
return <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}
alt=""
/>
<AccessibleButton onClick={() => {
avatarUploadRef.current.value = "";
setAvatarDataUrl(undefined);
setAvatar(undefined);
}} kind="link" className="mx_SpaceBasicSettings_avatar_remove">
<AccessibleButton
onClick={() => {
avatarUploadRef.current.value = "";
setAvatarDataUrl(undefined);
setAvatar(undefined);
}}
kind="link"
className="mx_SpaceBasicSettings_avatar_remove"
>
{ _t("Delete") }
</AccessibleButton>
</React.Fragment>;
@ -77,16 +81,21 @@ export const SpaceAvatar = ({
return <div className="mx_SpaceBasicSettings_avatarContainer">
{ avatarSection }
<input type="file" ref={avatarUploadRef} onChange={(e) => {
if (!e.target.files?.length) return;
const file = e.target.files[0];
setAvatar(file);
const reader = new FileReader();
reader.onload = (ev) => {
setAvatarDataUrl(ev.target.result as string);
};
reader.readAsDataURL(file);
}} accept="image/*" />
<input
type="file"
ref={avatarUploadRef}
onChange={(e) => {
if (!e.target.files?.length) return;
const file = e.target.files[0];
setAvatar(file);
const reader = new FileReader();
reader.onload = (ev) => {
setAvatarDataUrl(ev.target.result as string);
};
reader.readAsDataURL(file);
}}
accept="image/*"
/>
</div>;
};

View File

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

View File

@ -68,13 +68,19 @@ export default class Dialpad extends React.PureComponent<IProps> {
for (let i = 0; i < BUTTONS.length; i++) {
const button = BUTTONS[i];
const digitSubtext = BUTTON_LETTERS[i];
buttonNodes.push(<DialPadButton key={button} kind={DialPadButtonKind.Digit}
digit={button} digitSubtext={digitSubtext} onButtonPress={this.props.onDigitPress}
buttonNodes.push(<DialPadButton
key={button}
kind={DialPadButtonKind.Digit}
digit={button}
digitSubtext={digitSubtext}
onButtonPress={this.props.onDigitPress}
/>);
}
if (this.props.hasDial) {
buttonNodes.push(<DialPadButton key="dial" kind={DialPadButtonKind.Dial}
buttonNodes.push(<DialPadButton
key="dial"
kind={DialPadButtonKind.Dial}
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
let dialPadField;
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}
autoFocus={true}
onChange={this.onChange}
postfixComponent={backspaceButton}
/>;
} else {
dialPadField = <Field className="mx_DialPadModal_field" id="dialpad_number"
dialPadField = <Field
className="mx_DialPadModal_field"
id="dialpad_number"
value={this.state.value}
autoFocus={true}
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;
return (
<div className={classnames(videoClasses)} >
<div className={classnames(videoClasses)}>
<MemberAvatar
member={member}
height={avatarSize}

View File

@ -312,8 +312,12 @@ describe('MessagePanel', function() {
it('should insert the read-marker in the right place', function() {
const res = TestUtils.renderIntoDocument(
<WrappedMessagePanel className="cls" events={events} readMarkerEventId={events[4].getId()}
readMarkerVisible={true} />,
<WrappedMessagePanel
className="cls"
events={events}
readMarkerEventId={events[4].getId()}
readMarkerVisible={true}
/>,
);
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() {
const melsEvents = mkMelsEvents();
const res = TestUtils.renderIntoDocument(
<WrappedMessagePanel className="cls" events={melsEvents} readMarkerEventId={melsEvents[4].getId()}
readMarkerVisible={true} />,
<WrappedMessagePanel
className="cls"
events={melsEvents}
readMarkerEventId={melsEvents[4].getId()}
readMarkerVisible={true}
/>,
);
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() {
const melsEvents = mkMelsEventsOnly();
const res = TestUtils.renderIntoDocument(
<WrappedMessagePanel className="cls" events={melsEvents} readMarkerEventId={melsEvents[9].getId()}
readMarkerVisible={true} />,
<WrappedMessagePanel
className="cls"
events={melsEvents}
readMarkerEventId={melsEvents[9].getId()}
readMarkerVisible={true}
/>,
);
const summary = TestUtils.findRenderedDOMComponentWithClass(res, 'mx_EventListSummary');
@ -371,7 +383,10 @@ describe('MessagePanel', function() {
// first render with the RM in one place
let mp = ReactDOM.render(
<WrappedMessagePanel className="cls" events={events} readMarkerEventId={events[4].getId()}
<WrappedMessagePanel
className="cls"
events={events}
readMarkerEventId={events[4].getId()}
readMarkerVisible={true}
/>, parentDiv);
@ -387,7 +402,10 @@ describe('MessagePanel', function() {
// now move the RM
mp = ReactDOM.render(
<WrappedMessagePanel className="cls" events={events} readMarkerEventId={events[6].getId()}
<WrappedMessagePanel
className="cls"
events={events}
readMarkerEventId={events[6].getId()}
readMarkerVisible={true}
/>, parentDiv);