Comply with noImplicitAny (#9940)

* Stash noImplicitAny work

* Stash

* Fix imports

* Iterate

* Fix tests

* Delint

* Fix tests
This commit is contained in:
Michael Telatynski 2023-02-13 11:39:16 +00:00 committed by GitHub
parent ac7f69216e
commit 61a63e47f4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
359 changed files with 1621 additions and 1353 deletions

View file

@ -31,7 +31,7 @@ interface IState {
* A clock which shows a clip's maximum duration.
*/
export default class DurationClock extends React.PureComponent<IProps, IState> {
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.state = {

View file

@ -34,12 +34,12 @@ interface IState {
*/
export default class LiveRecordingClock extends React.PureComponent<IProps, IState> {
private seconds = 0;
private scheduledUpdate = new MarkedExecution(
private scheduledUpdate: MarkedExecution = new MarkedExecution(
() => this.updateClock(),
() => requestAnimationFrame(() => this.scheduledUpdate.trigger()),
);
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.state = {
seconds: 0,

View file

@ -39,12 +39,12 @@ export default class LiveRecordingWaveform extends React.PureComponent<IProps, I
};
private waveform: number[] = [];
private scheduledUpdate = new MarkedExecution(
private scheduledUpdate: MarkedExecution = new MarkedExecution(
() => this.updateWaveform(),
() => requestAnimationFrame(() => this.scheduledUpdate.trigger()),
);
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.state = {
waveform: arraySeed(0, RECORDING_PLAYBACK_SAMPLES),

View file

@ -35,7 +35,7 @@ interface IProps extends Omit<React.ComponentProps<typeof AccessibleTooltipButto
* to be displayed in reference to a recording.
*/
export default class PlayPauseButton extends React.PureComponent<IProps> {
public constructor(props) {
public constructor(props: IProps) {
super(props);
}

View file

@ -39,7 +39,7 @@ interface IState {
* A clock for a playback of a recording.
*/
export default class PlaybackClock extends React.PureComponent<IProps, IState> {
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.state = {

View file

@ -34,7 +34,7 @@ interface IState {
* A waveform which shows the waveform of a previously recorded recording
*/
export default class PlaybackWaveform extends React.PureComponent<IProps, IState> {
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.state = {

View file

@ -46,7 +46,7 @@ export default class SeekBar extends React.PureComponent<IProps, IState> {
// We use an animation frame request to avoid overly spamming prop updates, even if we aren't
// really using anything demanding on the CSS front.
private animationFrameFn = new MarkedExecution(
private animationFrameFn: MarkedExecution = new MarkedExecution(
() => this.doUpdate(),
() => requestAnimationFrame(() => this.animationFrameFn.trigger()),
);

View file

@ -21,7 +21,7 @@ import SdkConfig from "../../../SdkConfig";
import { _t } from "../../../languageHandler";
import Dropdown from "../elements/Dropdown";
const COUNTRIES_BY_ISO2 = {};
const COUNTRIES_BY_ISO2: Record<string, PhoneNumberCountryDefinition> = {};
for (const c of COUNTRIES) {
COUNTRIES_BY_ISO2[c.iso2] = c;
}

View file

@ -100,7 +100,7 @@ interface IPasswordAuthEntryState {
export class PasswordAuthEntry extends React.Component<IAuthEntryProps, IPasswordAuthEntryState> {
public static LOGIN_TYPE = AuthType.Password;
public constructor(props) {
public constructor(props: IAuthEntryProps) {
super(props);
this.state = {
@ -264,7 +264,7 @@ interface ITermsAuthEntryState {
export class TermsAuthEntry extends React.Component<ITermsAuthEntryProps, ITermsAuthEntryState> {
public static LOGIN_TYPE = AuthType.Terms;
public constructor(props) {
public constructor(props: ITermsAuthEntryProps) {
super(props);
// example stageParams:
@ -288,8 +288,12 @@ export class TermsAuthEntry extends React.Component<ITermsAuthEntryProps, ITerms
const allPolicies = this.props.stageParams.policies || {};
const prefLang = SettingsStore.getValue("language");
const initToggles = {};
const pickedPolicies = [];
const initToggles: Record<string, boolean> = {};
const pickedPolicies: {
id: string;
name: string;
url: string;
}[] = [];
for (const policyId of Object.keys(allPolicies)) {
const policy = allPolicies[policyId];
@ -325,7 +329,7 @@ export class TermsAuthEntry extends React.Component<ITermsAuthEntryProps, ITerms
}
private togglePolicy(policyId: string): void {
const newToggles = {};
const newToggles: Record<string, boolean> = {};
for (const policy of this.state.policies) {
let checked = this.state.toggledPolicies[policy.id];
if (policy.id === policyId) checked = !checked;
@ -484,7 +488,7 @@ export class EmailIdentityAuthEntry extends React.Component<
{
a: (text: string) => (
<Fragment>
<AccessibleButton kind="link_inline" onClick={() => null} disabled>
<AccessibleButton kind="link_inline" onClick={null} disabled>
{text} <Spinner w={14} h={14} />
</AccessibleButton>
</Fragment>
@ -555,7 +559,7 @@ export class MsisdnAuthEntry extends React.Component<IMsisdnAuthEntryProps, IMsi
private sid: string;
private msisdn: string;
public constructor(props) {
public constructor(props: IMsisdnAuthEntryProps) {
super(props);
this.state = {
@ -908,7 +912,7 @@ export class FallbackAuthEntry extends React.Component<IAuthEntryProps> {
private popupWindow: Window;
private fallbackButton = createRef<HTMLButtonElement>();
public constructor(props) {
public constructor(props: IAuthEntryProps) {
super(props);
// we have to make the user click a button, as browsers will block

View file

@ -75,7 +75,7 @@ interface IState {
* This uses the unstable feature of MSC3906: https://github.com/matrix-org/matrix-spec-proposals/pull/3906
*/
export default class LoginWithQR extends React.Component<IProps, IState> {
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.state = {

View file

@ -41,7 +41,7 @@ interface IProps {
* This uses the unstable feature of MSC3906: https://github.com/matrix-org/matrix-spec-proposals/pull/3906
*/
export default class LoginWithQRFlow extends React.Component<IProps> {
public constructor(props) {
public constructor(props: IProps) {
super(props);
}

View file

@ -30,8 +30,8 @@ interface IProps extends Omit<IInputProps, "onValidate"> {
labelRequired?: string;
labelInvalid?: string;
onChange(ev: React.FormEvent<HTMLElement>);
onValidate?(result: IValidationResult);
onChange(ev: React.FormEvent<HTMLElement>): void;
onValidate?(result: IValidationResult): void;
}
class PassphraseConfirmField extends PureComponent<IProps> {

View file

@ -36,8 +36,8 @@ interface IProps extends Omit<IInputProps, "onValidate"> {
labelStrongPassword?: string;
labelAllowedButUnsafe?: string;
onChange(ev: React.FormEvent<HTMLElement>);
onValidate?(result: IValidationResult);
onChange(ev: React.FormEvent<HTMLElement>): void;
onValidate?(result: IValidationResult): void;
}
class PassphraseField extends PureComponent<IProps> {

View file

@ -14,17 +14,18 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from "react";
import React, { SyntheticEvent } from "react";
import classNames from "classnames";
import { _t } from "../../../languageHandler";
import SdkConfig from "../../../SdkConfig";
import { ValidatedServerConfig } from "../../../utils/ValidatedServerConfig";
import AccessibleButton from "../elements/AccessibleButton";
import withValidation, { IValidationResult } from "../elements/Validation";
import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton";
import withValidation, { IFieldState, IValidationResult } from "../elements/Validation";
import Field from "../elements/Field";
import CountryDropdown from "./CountryDropdown";
import EmailField from "./EmailField";
import { PhoneNumberCountryDefinition } from "../../../phonenumber";
// For validating phone numbers without country codes
const PHONE_NUMBER_REGEX = /^[0-9()\-\s]*$/;
@ -51,7 +52,7 @@ interface IProps {
interface IState {
fieldValid: Partial<Record<LoginField, boolean>>;
loginType: LoginField.Email | LoginField.MatrixId | LoginField.Phone;
password: "";
password: string;
}
const enum LoginField {
@ -66,6 +67,10 @@ const enum LoginField {
* The email/username/phone fields are fully-controlled, the password field is not.
*/
export default class PasswordLogin extends React.PureComponent<IProps, IState> {
private [LoginField.Email]: Field;
private [LoginField.Phone]: Field;
private [LoginField.MatrixId]: Field;
public static defaultProps = {
onUsernameChanged: function () {},
onUsernameBlur: function () {},
@ -75,7 +80,7 @@ export default class PasswordLogin extends React.PureComponent<IProps, IState> {
disableSubmit: false,
};
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.state = {
// Field error codes by field ID
@ -85,13 +90,13 @@ export default class PasswordLogin extends React.PureComponent<IProps, IState> {
};
}
private onForgotPasswordClick = (ev): void => {
private onForgotPasswordClick = (ev: ButtonEvent): void => {
ev.preventDefault();
ev.stopPropagation();
this.props.onForgotPasswordClick();
};
private onSubmitForm = async (ev): Promise<void> => {
private onSubmitForm = async (ev: SyntheticEvent): Promise<void> => {
ev.preventDefault();
const allFieldsValid = await this.verifyFieldsBeforeSubmit();
@ -99,47 +104,40 @@ export default class PasswordLogin extends React.PureComponent<IProps, IState> {
return;
}
let username = ""; // XXX: Synapse breaks if you send null here:
let phoneCountry = null;
let phoneNumber = null;
switch (this.state.loginType) {
case LoginField.Email:
case LoginField.MatrixId:
username = this.props.username;
this.props.onSubmit(this.props.username, undefined, undefined, this.state.password);
break;
case LoginField.Phone:
phoneCountry = this.props.phoneCountry;
phoneNumber = this.props.phoneNumber;
this.props.onSubmit(undefined, this.props.phoneCountry, this.props.phoneNumber, this.state.password);
break;
}
this.props.onSubmit(username, phoneCountry, phoneNumber, this.state.password);
};
private onUsernameChanged = (ev): void => {
private onUsernameChanged = (ev: React.ChangeEvent<HTMLInputElement>): void => {
this.props.onUsernameChanged(ev.target.value);
};
private onUsernameBlur = (ev): void => {
private onUsernameBlur = (ev: React.FocusEvent<HTMLInputElement>): void => {
this.props.onUsernameBlur(ev.target.value);
};
private onLoginTypeChange = (ev): void => {
const loginType = ev.target.value;
private onLoginTypeChange = (ev: React.ChangeEvent<HTMLSelectElement>): void => {
const loginType = ev.target.value as IState["loginType"];
this.setState({ loginType });
this.props.onUsernameChanged(""); // Reset because email and username use the same state
};
private onPhoneCountryChanged = (country): void => {
private onPhoneCountryChanged = (country: PhoneNumberCountryDefinition): void => {
this.props.onPhoneCountryChanged(country.iso2);
};
private onPhoneNumberChanged = (ev): void => {
private onPhoneNumberChanged = (ev: React.ChangeEvent<HTMLInputElement>): void => {
this.props.onPhoneNumberChanged(ev.target.value);
};
private onPasswordChanged = (ev): void => {
private onPasswordChanged = (ev: React.ChangeEvent<HTMLInputElement>): void => {
this.setState({ password: ev.target.value });
};
@ -151,7 +149,7 @@ export default class PasswordLogin extends React.PureComponent<IProps, IState> {
activeElement.blur();
}
const fieldIDsInDisplayOrder = [this.state.loginType, LoginField.Password];
const fieldIDsInDisplayOrder: LoginField[] = [this.state.loginType, LoginField.Password];
// Run all fields with stricter validation that no longer allows empty
// values for required fields.
@ -221,7 +219,7 @@ export default class PasswordLogin extends React.PureComponent<IProps, IState> {
],
});
private onUsernameValidate = async (fieldState): Promise<IValidationResult> => {
private onUsernameValidate = async (fieldState: IFieldState): Promise<IValidationResult> => {
const result = await this.validateUsernameRules(fieldState);
this.markFieldValid(LoginField.MatrixId, result.valid);
return result;
@ -248,7 +246,7 @@ export default class PasswordLogin extends React.PureComponent<IProps, IState> {
],
});
private onPhoneNumberValidate = async (fieldState): Promise<IValidationResult> => {
private onPhoneNumberValidate = async (fieldState: IFieldState): Promise<IValidationResult> => {
const result = await this.validatePhoneNumberRules(fieldState);
this.markFieldValid(LoginField.Password, result.valid);
return result;
@ -266,7 +264,7 @@ export default class PasswordLogin extends React.PureComponent<IProps, IState> {
],
});
private onPasswordValidate = async (fieldState): Promise<IValidationResult> => {
private onPasswordValidate = async (fieldState: IFieldState): Promise<IValidationResult> => {
const result = await this.validatePasswordRules(fieldState);
this.markFieldValid(LoginField.Password, result.valid);
return result;

View file

@ -15,18 +15,18 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from "react";
import React, { BaseSyntheticEvent } from "react";
import { MatrixClient } from "matrix-js-sdk/src/client";
import { logger } from "matrix-js-sdk/src/logger";
import { MatrixError } from "matrix-js-sdk/src/matrix";
import * as Email from "../../../email";
import { looksValid as phoneNumberLooksValid } from "../../../phonenumber";
import { looksValid as phoneNumberLooksValid, PhoneNumberCountryDefinition } from "../../../phonenumber";
import Modal from "../../../Modal";
import { _t, _td } from "../../../languageHandler";
import SdkConfig from "../../../SdkConfig";
import { SAFE_LOCALPART_REGEX } from "../../../Registration";
import withValidation, { IValidationResult } from "../elements/Validation";
import withValidation, { IFieldState, IValidationResult } from "../elements/Validation";
import { ValidatedServerConfig } from "../../../utils/ValidatedServerConfig";
import EmailField from "./EmailField";
import PassphraseField from "./PassphraseField";
@ -95,12 +95,18 @@ interface IState {
* A pure UI component which displays a registration form.
*/
export default class RegistrationForm extends React.PureComponent<IProps, IState> {
private [RegistrationField.Email]: Field;
private [RegistrationField.Password]: Field;
private [RegistrationField.PasswordConfirm]: Field;
private [RegistrationField.Username]: Field;
private [RegistrationField.PhoneNumber]: Field;
public static defaultProps = {
onValidationChange: logger.error,
canSubmit: true,
};
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.state = {
@ -115,7 +121,9 @@ export default class RegistrationForm extends React.PureComponent<IProps, IState
};
}
private onSubmit = async (ev): Promise<void> => {
private onSubmit = async (
ev: BaseSyntheticEvent<Event, EventTarget & HTMLFormElement, EventTarget & HTMLFormElement>,
): Promise<void> => {
ev.preventDefault();
ev.persist();
@ -152,7 +160,9 @@ export default class RegistrationForm extends React.PureComponent<IProps, IState
}
};
private doSubmit(ev): void {
private doSubmit(
ev: BaseSyntheticEvent<Event, EventTarget & HTMLFormElement, EventTarget & HTMLFormElement>,
): void {
PosthogAnalytics.instance.setAuthenticationType("Password");
const email = this.state.email.trim();
@ -248,7 +258,7 @@ export default class RegistrationForm extends React.PureComponent<IProps, IState
});
}
private onEmailChange = (ev): void => {
private onEmailChange = (ev: React.ChangeEvent<HTMLInputElement>): void => {
this.setState({
email: ev.target.value.trim(),
});
@ -277,7 +287,7 @@ export default class RegistrationForm extends React.PureComponent<IProps, IState
],
});
private onPasswordChange = (ev): void => {
private onPasswordChange = (ev: React.ChangeEvent<HTMLInputElement>): void => {
this.setState({
password: ev.target.value,
});
@ -287,7 +297,7 @@ export default class RegistrationForm extends React.PureComponent<IProps, IState
this.markFieldValid(RegistrationField.Password, result.valid);
};
private onPasswordConfirmChange = (ev): void => {
private onPasswordConfirmChange = (ev: React.ChangeEvent<HTMLInputElement>): void => {
this.setState({
passwordConfirm: ev.target.value,
});
@ -297,19 +307,19 @@ export default class RegistrationForm extends React.PureComponent<IProps, IState
this.markFieldValid(RegistrationField.PasswordConfirm, result.valid);
};
private onPhoneCountryChange = (newVal): void => {
private onPhoneCountryChange = (newVal: PhoneNumberCountryDefinition): void => {
this.setState({
phoneCountry: newVal.iso2,
});
};
private onPhoneNumberChange = (ev): void => {
private onPhoneNumberChange = (ev: React.ChangeEvent<HTMLInputElement>): void => {
this.setState({
phoneNumber: ev.target.value,
});
};
private onPhoneNumberValidate = async (fieldState): Promise<IValidationResult> => {
private onPhoneNumberValidate = async (fieldState: IFieldState): Promise<IValidationResult> => {
const result = await this.validatePhoneNumberRules(fieldState);
this.markFieldValid(RegistrationField.PhoneNumber, result.valid);
return result;
@ -334,13 +344,13 @@ export default class RegistrationForm extends React.PureComponent<IProps, IState
],
});
private onUsernameChange = (ev): void => {
private onUsernameChange = (ev: React.ChangeEvent<HTMLInputElement>): void => {
this.setState({
username: ev.target.value,
});
};
private onUsernameValidate = async (fieldState): Promise<IValidationResult> => {
private onUsernameValidate = async (fieldState: IFieldState): Promise<IValidationResult> => {
const result = await this.validateUsernameRules(fieldState);
this.markFieldValid(RegistrationField.Username, result.valid);
return result;

View file

@ -48,7 +48,7 @@ interface IProps {
tabIndex?: number;
}
const calculateUrls = (url: string, urls: string[], lowBandwidth: boolean): string[] => {
const calculateUrls = (url?: string, urls?: string[], lowBandwidth = false): string[] => {
// work out the full set of urls to try to load. This is formed like so:
// imageUrls: [ props.url, ...props.urls ]
@ -66,7 +66,7 @@ const calculateUrls = (url: string, urls: string[], lowBandwidth: boolean): stri
return Array.from(new Set(_urls));
};
const useImageUrl = ({ url, urls }): [string, () => void] => {
const useImageUrl = ({ url, urls }: { url?: string; urls?: string[] }): [string, () => void] => {
// Since this is a hot code path and the settings store can be slow, we
// use the cached lowBandwidth value from the room context if it exists
const roomContext = useContext(RoomContext);

View file

@ -34,7 +34,7 @@ interface IState {
export default class DialpadContextMenu extends React.Component<IProps, IState> {
private numberEntryFieldRef: React.RefObject<Field> = createRef();
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.state = {
@ -58,14 +58,14 @@ export default class DialpadContextMenu extends React.Component<IProps, IState>
this.props.onFinished();
};
public onKeyDown = (ev): void => {
public onKeyDown = (ev: React.KeyboardEvent): void => {
// Prevent Backspace and Delete keys from functioning in the entry field
if (ev.code === "Backspace" || ev.code === "Delete") {
ev.preventDefault();
}
};
public onChange = (ev): void => {
public onChange = (ev: React.ChangeEvent<HTMLInputElement>): void => {
this.setState({ value: ev.target.value });
};

View file

@ -26,7 +26,7 @@ interface IProps extends IContextMenuProps {
}
export default class LegacyCallContextMenu extends React.Component<IProps> {
public constructor(props) {
public constructor(props: IProps) {
super(props);
}

View file

@ -88,7 +88,7 @@ export default class BaseDialog extends React.Component<IProps> {
fixedWidth: true,
};
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.matrixClient = MatrixClientPeg.get();
@ -132,7 +132,7 @@ export default class BaseDialog extends React.Component<IProps> {
headerImage = <img className="mx_Dialog_titleImage" src={this.props.headerImage} alt="" />;
}
const lockProps = {
const lockProps: Record<string, any> = {
"onKeyDown": this.onKeyDown,
"role": "dialog",
// This should point to a node describing the dialog.

View file

@ -54,7 +54,7 @@ interface IState {
export default class BugReportDialog extends React.Component<IProps, IState> {
private unmounted: boolean;
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.state = {
sendLogs: true,

View file

@ -21,6 +21,7 @@ import { RoomMember } from "matrix-js-sdk/src/models/room-member";
import { Room } from "matrix-js-sdk/src/models/room";
import { EventTimeline } from "matrix-js-sdk/src/models/event-timeline";
import { EventType } from "matrix-js-sdk/src/@types/event";
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { _t } from "../../../languageHandler";
import dis from "../../../dispatcher/dispatcher";
@ -42,7 +43,7 @@ const BulkRedactDialog: React.FC<IBulkRedactDialogProps> = (props) => {
const [keepStateEvents, setKeepStateEvents] = useState(true);
let timeline = room.getLiveTimeline();
let eventsToRedact = [];
let eventsToRedact: MatrixEvent[] = [];
while (timeline) {
eventsToRedact = [
...eventsToRedact,

View file

@ -27,16 +27,26 @@ interface IProps {
onFinished: (success: boolean) => void;
}
const REPOS = ["vector-im/element-web", "matrix-org/matrix-react-sdk", "matrix-org/matrix-js-sdk"];
type State = Partial<Record<typeof REPOS[number], null | string | Commit[]>>;
export default class ChangelogDialog extends React.Component<IProps> {
public constructor(props) {
interface Commit {
sha: string;
html_url: string;
commit: {
message: string;
};
}
const REPOS = ["vector-im/element-web", "matrix-org/matrix-react-sdk", "matrix-org/matrix-js-sdk"] as const;
export default class ChangelogDialog extends React.Component<IProps, State> {
public constructor(props: IProps) {
super(props);
this.state = {};
}
private async fetchChanges(repo: string, oldVersion: string, newVersion: string): Promise<void> {
private async fetchChanges(repo: typeof REPOS[number], oldVersion: string, newVersion: string): Promise<void> {
const url = `https://riot.im/github/repos/${repo}/compare/${oldVersion}...${newVersion}`;
try {
@ -66,7 +76,7 @@ export default class ChangelogDialog extends React.Component<IProps> {
}
}
private elementsForCommit(commit): JSX.Element {
private elementsForCommit(commit: Commit): JSX.Element {
return (
<li key={commit.sha} className="mx_ChangelogDialog_li">
<a href={commit.html_url} target="_blank" rel="noreferrer noopener">
@ -86,7 +96,7 @@ export default class ChangelogDialog extends React.Component<IProps> {
msg: this.state[repo],
});
} else {
content = this.state[repo].map(this.elementsForCommit);
content = (this.state[repo] as Commit[]).map(this.elementsForCommit);
}
return (
<div key={repo}>

View file

@ -45,7 +45,7 @@ interface IState {
* To avoid this, we keep the dialog open as long as /redact is in progress.
*/
export default class ConfirmAndWaitRedactDialog extends React.PureComponent<IProps, IState> {
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.state = {
isRedacting: false,

View file

@ -62,7 +62,7 @@ export default class CreateRoomDialog extends React.Component<IProps, IState> {
private nameField = createRef<Field>();
private aliasField = createRef<RoomAliasField>();
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.supportsRestricted = !!this.props.parentSpace;

View file

@ -21,7 +21,7 @@ import { logger } from "matrix-js-sdk/src/logger";
import { _t } from "../../../languageHandler";
import BaseDialog from "./BaseDialog";
import AccessibleButton from "../elements/AccessibleButton";
import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
import { BetaPill } from "../beta/BetaCard";
import Field from "../elements/Field";
@ -54,7 +54,7 @@ const CreateSubspaceDialog: React.FC<IProps> = ({ space, onAddExistingSpaceClick
}
const [joinRule, setJoinRule] = useState<JoinRule>(defaultJoinRule);
const onCreateSubspaceClick = async (e): Promise<void> => {
const onCreateSubspaceClick = async (e: ButtonEvent): Promise<void> => {
e.preventDefault();
if (busy) return;

View file

@ -28,6 +28,16 @@ import BaseDialog from "./BaseDialog";
import defaultDispatcher from "../../../dispatcher/dispatcher";
import { Action } from "../../../dispatcher/actions";
type DialogAesthetics = Partial<{
[x in AuthType]: {
[x: number]: {
body: string;
continueText?: string;
continueKind?: string;
};
};
}>;
interface IProps {
onFinished: (success: boolean) => void;
}
@ -46,7 +56,7 @@ interface IState {
}
export default class DeactivateAccountDialog extends React.Component<IProps, IState> {
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.state = {
@ -65,7 +75,7 @@ export default class DeactivateAccountDialog extends React.Component<IProps, ISt
this.initAuth(/* shouldErase= */ false);
}
private onStagePhaseChange = (stage: AuthType, phase: string): void => {
private onStagePhaseChange = (stage: AuthType, phase: number): void => {
const dialogAesthetics = {
[SSOAuthEntry.PHASE_PREAUTH]: {
body: _t("Confirm your account deactivation by using Single Sign On to prove your identity."),
@ -80,7 +90,7 @@ export default class DeactivateAccountDialog extends React.Component<IProps, ISt
};
// This is the same as aestheticsForStagePhases in InteractiveAuthDialog minus the `title`
const DEACTIVATE_AESTHETICS = {
const DEACTIVATE_AESTHETICS: DialogAesthetics = {
[SSOAuthEntry.LOGIN_TYPE]: dialogAesthetics,
[SSOAuthEntry.UNSTABLE_LOGIN_TYPE]: dialogAesthetics,
[PasswordAuthEntry.LOGIN_TYPE]: {
@ -96,9 +106,9 @@ export default class DeactivateAccountDialog extends React.Component<IProps, ISt
let continueKind = null;
if (aesthetics) {
const phaseAesthetics = aesthetics[phase];
if (phaseAesthetics && phaseAesthetics.body) bodyText = phaseAesthetics.body;
if (phaseAesthetics && phaseAesthetics.continueText) continueText = phaseAesthetics.continueText;
if (phaseAesthetics && phaseAesthetics.continueKind) continueKind = phaseAesthetics.continueKind;
if (phaseAesthetics?.body) bodyText = phaseAesthetics.body;
if (phaseAesthetics?.continueText) continueText = phaseAesthetics.continueText;
if (phaseAesthetics?.continueKind) continueKind = phaseAesthetics.continueKind;
}
this.setState({ bodyText, continueText, continueKind });
};

View file

@ -91,7 +91,7 @@ const DevtoolsDialog: React.FC<IProps> = ({ roomId, onFinished }) => {
<BaseTool onBack={onBack}>
{Object.entries(Tools).map(([category, tools]) => (
<div key={category}>
<h3>{_t(categoryLabels[category])}</h3>
<h3>{_t(categoryLabels[category as unknown as Category])}</h3>
{tools.map(([label, tool]) => {
const onClick = (): void => {
setTool([label, tool]);

View file

@ -46,9 +46,6 @@ interface IState {
export default class ErrorDialog extends React.Component<IProps, IState> {
public static defaultProps = {
focus: true,
title: null,
description: null,
button: null,
};
private onClick = (): void => {

View file

@ -25,7 +25,14 @@ import DialogButtons from "../elements/DialogButtons";
import Field from "../elements/Field";
import StyledRadioGroup from "../elements/StyledRadioGroup";
import StyledCheckbox from "../elements/StyledCheckbox";
import { ExportFormat, ExportType, textForFormat, textForType } from "../../../utils/exportUtils/exportUtils";
import {
ExportFormat,
ExportFormatKey,
ExportType,
ExportTypeKey,
textForFormat,
textForType,
} from "../../../utils/exportUtils/exportUtils";
import withValidation, { IFieldState, IValidationResult } from "../elements/Validation";
import HTMLExporter from "../../../utils/exportUtils/HtmlExport";
import JSONExporter from "../../../utils/exportUtils/JSONExport";
@ -237,15 +244,15 @@ const ExportDialog: React.FC<IProps> = ({ room, onFinished }) => {
setExporter(null);
};
const exportFormatOptions = Object.keys(ExportFormat).map((format) => ({
value: ExportFormat[format],
label: textForFormat(ExportFormat[format]),
const exportFormatOptions = Object.values(ExportFormat).map((format) => ({
value: format,
label: textForFormat(format),
}));
const exportTypeOptions = Object.keys(ExportType).map((type) => {
const exportTypeOptions = Object.values(ExportType).map((type) => {
return (
<option key={type} value={ExportType[type]}>
{textForType(ExportType[type])}
<option key={ExportType[type]} value={type}>
{textForType(type)}
</option>
);
});
@ -332,7 +339,7 @@ const ExportDialog: React.FC<IProps> = ({ room, onFinished }) => {
<StyledRadioGroup
name="exportFormat"
value={exportFormat}
onChange={(key) => setExportFormat(ExportFormat[key])}
onChange={(key: ExportFormatKey) => setExportFormat(ExportFormat[key])}
definitions={exportFormatOptions}
/>
</>
@ -347,7 +354,7 @@ const ExportDialog: React.FC<IProps> = ({ room, onFinished }) => {
element="select"
value={exportType}
onChange={(e) => {
setExportType(ExportType[e.target.value]);
setExportType(ExportType[e.target.value as ExportTypeKey]);
}}
>
{exportTypeOptions}

View file

@ -243,7 +243,7 @@ const ForwardDialog: React.FC<IProps> = ({ matrixClient: cli, event, permalinkCr
}
const [truncateAt, setTruncateAt] = useState(20);
function overflowTile(overflowCount, totalCount): JSX.Element {
function overflowTile(overflowCount: number, totalCount: number): JSX.Element {
const text = _t("and %(count)s others...", { count: overflowCount });
return (
<EntityTile

View file

@ -155,7 +155,7 @@ export default class HostSignupDialog extends React.PureComponent<IProps, IState
});
}
private onAccountDetailsDialogFinished = async (result): Promise<void> => {
private onAccountDetailsDialogFinished = async (result: boolean): Promise<void> => {
if (result) {
return this.sendAccountDetails();
}

View file

@ -18,7 +18,7 @@ limitations under the License.
import React from "react";
import { MatrixClient } from "matrix-js-sdk/src/client";
import { IAuthData } from "matrix-js-sdk/src/interactive-auth";
import { AuthType, IAuthData } from "matrix-js-sdk/src/interactive-auth";
import { _t } from "../../../languageHandler";
import AccessibleButton from "../elements/AccessibleButton";
@ -27,8 +27,8 @@ import { SSOAuthEntry } from "../auth/InteractiveAuthEntryComponents";
import BaseDialog from "./BaseDialog";
import { IDialogProps } from "./IDialogProps";
interface IDialogAesthetics {
[x: string]: {
type DialogAesthetics = Partial<{
[x in AuthType]: {
[x: number]: {
title: string;
body: string;
@ -36,7 +36,7 @@ interface IDialogAesthetics {
continueKind: string;
};
};
}
}>;
export interface InteractiveAuthDialogProps extends IDialogProps {
// matrix client to use for UI auth requests
@ -71,15 +71,15 @@ export interface InteractiveAuthDialogProps extends IDialogProps {
// }
//
// Default is defined in _getDefaultDialogAesthetics()
aestheticsForStagePhases?: IDialogAesthetics;
aestheticsForStagePhases?: DialogAesthetics;
}
interface IState {
authError: Error;
// See _onUpdateStagePhase()
uiaStage: number | string;
uiaStagePhase: number | string;
uiaStage: AuthType | null;
uiaStagePhase: number | null;
}
export default class InteractiveAuthDialog extends React.Component<InteractiveAuthDialogProps, IState> {
@ -95,7 +95,7 @@ export default class InteractiveAuthDialog extends React.Component<InteractiveAu
};
}
private getDefaultDialogAesthetics(): IDialogAesthetics {
private getDefaultDialogAesthetics(): DialogAesthetics {
const ssoAesthetics = {
[SSOAuthEntry.PHASE_PREAUTH]: {
title: _t("Use Single Sign On to continue"),
@ -125,13 +125,13 @@ export default class InteractiveAuthDialog extends React.Component<InteractiveAu
this.props.onFinished(false, null);
} else {
this.setState({
authError: result,
authError: result as Error,
});
}
}
};
private onUpdateStagePhase = (newStage: string | number, newPhase: string | number): void => {
private onUpdateStagePhase = (newStage: AuthType, newPhase: number): void => {
// We copy the stage and stage phase params into state for title selection in render()
this.setState({ uiaStage: newStage, uiaStagePhase: newPhase });
};

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { createRef, ReactNode } from "react";
import React, { createRef, ReactNode, SyntheticEvent } from "react";
import classNames from "classnames";
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
import { Room } from "matrix-js-sdk/src/models/room";
@ -92,7 +92,7 @@ enum TabId {
}
class DMUserTile extends React.PureComponent<IDMUserTileProps> {
private onRemove = (e): void => {
private onRemove = (e: ButtonEvent): void => {
// Stop the browser from highlighting text
e.preventDefault();
e.stopPropagation();
@ -139,7 +139,7 @@ interface IDMRoomTileProps {
}
class DMRoomTile extends React.PureComponent<IDMRoomTileProps> {
private onClick = (e): void => {
private onClick = (e: ButtonEvent): void => {
// Stop the browser from highlighting text
e.preventDefault();
e.stopPropagation();
@ -271,6 +271,10 @@ interface InviteRoomProps extends BaseProps {
roomId: string;
}
function isRoomInvite(props: Props): props is InviteRoomProps {
return props.kind === KIND_INVITE;
}
interface InviteCallProps extends BaseProps {
kind: typeof KIND_CALL_TRANSFER;
@ -311,7 +315,7 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
private numberEntryFieldRef: React.RefObject<Field> = createRef();
private unmounted = false;
public constructor(props) {
public constructor(props: Props) {
super(props);
if (props.kind === KIND_INVITE && !props.roomId) {
@ -321,7 +325,7 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
}
const alreadyInvited = new Set([MatrixClientPeg.get().getUserId(), SdkConfig.get("welcome_user_id")]);
if (props.roomId) {
if (isRoomInvite(props)) {
const room = MatrixClientPeg.get().getRoom(props.roomId);
if (!room) throw new Error("Room ID given to InviteDialog does not look like a room");
room.getMembersWithMembership("invite").forEach((m) => alreadyInvited.add(m.userId));
@ -361,7 +365,7 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
this.unmounted = true;
}
private onConsultFirstChange = (ev): void => {
private onConsultFirstChange = (ev: React.ChangeEvent<HTMLInputElement>): void => {
this.setState({ consultFirst: ev.target.checked });
};
@ -538,11 +542,11 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
this.props.onFinished(true);
};
private onKeyDown = (e): void => {
private onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>): void => {
if (this.state.busy) return;
let handled = false;
const value = e.target.value.trim();
const value = e.currentTarget.value.trim();
const action = getKeyBindingsManager().getAccessibilityAction(e);
switch (action) {
@ -692,7 +696,7 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
}
};
private updateFilter = (e): void => {
private updateFilter = (e: React.ChangeEvent<HTMLInputElement>): void => {
const term = e.target.value;
this.setState({ filterText: term });
@ -750,7 +754,7 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
}
};
private onPaste = async (e): Promise<void> => {
private onPaste = async (e: React.ClipboardEvent): Promise<void> => {
if (this.state.filterText) {
// if the user has already typed something, just let them
// paste normally.
@ -825,7 +829,7 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
this.setState({ targets: [...this.state.targets, ...toAdd] });
};
private onClickInputArea = (e): void => {
private onClickInputArea = (e: React.MouseEvent): void => {
// Stop the browser from highlighting text
e.preventDefault();
e.stopPropagation();
@ -835,7 +839,7 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
}
};
private onUseDefaultIdentityServerClick = (e): void => {
private onUseDefaultIdentityServerClick = (e: ButtonEvent): void => {
e.preventDefault();
// Update the IS in account data. Actually using it may trigger terms.
@ -844,7 +848,7 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
this.setState({ canUseIdentityServer: true, tryingIdentityServer: false });
};
private onManageSettingsClick = (e): void => {
private onManageSettingsClick = (e: ButtonEvent): void => {
e.preventDefault();
dis.fire(Action.ViewUserSettings);
this.props.onFinished(false);
@ -864,8 +868,8 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
// Mix in the server results if we have any, but only if we're searching. We track the additional
// members separately because we want to filter sourceMembers but trust the mixin arrays to have
// the right members in them.
let priorityAdditionalMembers = []; // Shows up before our own suggestions, higher quality
let otherAdditionalMembers = []; // Shows up after our own suggestions, lower quality
let priorityAdditionalMembers: Result[] = []; // Shows up before our own suggestions, higher quality
let otherAdditionalMembers: Result[] = []; // Shows up after our own suggestions, lower quality
const hasMixins = this.state.serverResultsMixin || this.state.threepidResultsMixin;
if (this.state.filterText && hasMixins && kind === "suggestions") {
// We don't want to duplicate members though, so just exclude anyone we've already seen.
@ -1030,12 +1034,12 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
}
}
private onDialFormSubmit = (ev): void => {
private onDialFormSubmit = (ev: SyntheticEvent): void => {
ev.preventDefault();
this.transferCall();
};
private onDialChange = (ev): void => {
private onDialChange = (ev: React.ChangeEvent<HTMLInputElement>): void => {
this.setState({ dialPadValue: ev.currentTarget.value });
};
@ -1066,9 +1070,9 @@ export default class InviteDialog extends React.PureComponent<Props, IInviteDial
this.setState({ currentTabId: tabId });
};
private async onLinkClick(e): Promise<void> {
private async onLinkClick(e: React.MouseEvent<HTMLAnchorElement>): Promise<void> {
e.preventDefault();
selectText(e.target);
selectText(e.currentTarget);
}
private get screenName(): ScreenName {

View file

@ -45,7 +45,7 @@ export default class LogoutDialog extends React.Component<IProps, IState> {
onFinished: function () {},
};
public constructor(props) {
public constructor(props: IProps) {
super(props);
const cli = MatrixClientPeg.get();

View file

@ -121,8 +121,8 @@ export default class MessageEditHistoryDialog extends React.PureComponent<IProps
}
private renderEdits(): JSX.Element[] {
const nodes = [];
let lastEvent;
const nodes: JSX.Element[] = [];
let lastEvent: MatrixEvent;
let allEvents = this.state.events;
// append original event when we've done last pagination
if (this.state.originalEvent && !this.state.nextBatch) {

View file

@ -65,7 +65,7 @@ export default class ModalWidgetDialog extends React.PureComponent<IProps, IStat
disabledButtonIds: (this.props.widgetDefinition.buttons || []).filter((b) => b.disabled).map((b) => b.id),
};
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.widget = new ElementWidget({

View file

@ -15,7 +15,7 @@ limitations under the License.
*/
import * as React from "react";
import { useRef, useState } from "react";
import { SyntheticEvent, useRef, useState } from "react";
import { _t, _td } from "../../../languageHandler";
import { IDialogProps } from "./IDialogProps";
@ -32,7 +32,7 @@ const RegistrationEmailPromptDialog: React.FC<IProps> = ({ onFinished }) => {
const [email, setEmail] = useState("");
const fieldRef = useRef<Field>();
const onSubmit = async (e): Promise<void> => {
const onSubmit = async (e: SyntheticEvent): Promise<void> => {
e.preventDefault();
if (email) {
const valid = await fieldRef.current.validate({});

View file

@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from "react";
import React, { ChangeEvent } from "react";
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { logger } from "matrix-js-sdk/src/logger";
@ -189,7 +189,7 @@ export default class ReportEventDialog extends React.Component<IProps, IState> {
};
// The user has written down a freeform description of the abuse.
private onReasonChange = ({ target: { value: reason } }): void => {
private onReasonChange = ({ target: { value: reason } }: ChangeEvent<HTMLTextAreaElement>): void => {
this.setState({ reason });
};

View file

@ -33,6 +33,7 @@ import { UIFeature } from "../../../settings/UIFeature";
import BaseDialog from "./BaseDialog";
import { Action } from "../../../dispatcher/actions";
import { VoipRoomSettingsTab } from "../settings/tabs/room/VoipRoomSettingsTab";
import { ActionPayload } from "../../../dispatcher/payloads";
export const ROOM_GENERAL_TAB = "ROOM_GENERAL_TAB";
export const ROOM_VOIP_TAB = "ROOM_VOIP_TAB";
@ -74,7 +75,7 @@ export default class RoomSettingsDialog extends React.Component<IProps, IState>
MatrixClientPeg.get().removeListener(RoomEvent.Name, this.onRoomName);
}
private onAction = (payload): void => {
private onAction = (payload: ActionPayload): void => {
// When view changes below us, close the room settings
// whilst the modal is open this can only be triggered when someone hits Leave Room
if (payload.action === Action.ViewHomePage) {

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { ReactNode } from "react";
import React, { ReactNode, SyntheticEvent } from "react";
import { EventType } from "matrix-js-sdk/src/@types/event";
import { JoinRule } from "matrix-js-sdk/src/@types/partials";
@ -53,7 +53,7 @@ export default class RoomUpgradeWarningDialog extends React.Component<IProps, IS
private readonly isPrivate: boolean;
private readonly currentVersion: string;
public constructor(props) {
public constructor(props: IProps) {
super(props);
const room = MatrixClientPeg.get().getRoom(this.props.roomId);
@ -93,7 +93,7 @@ export default class RoomUpgradeWarningDialog extends React.Component<IProps, IS
this.setState({ inviteUsersToNewRoom });
};
private openBugReportDialog = (e): void => {
private openBugReportDialog = (e: SyntheticEvent): void => {
e.preventDefault();
e.stopPropagation();

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { createRef } from "react";
import React, { ChangeEvent, createRef, SyntheticEvent } from "react";
import { AutoDiscovery } from "matrix-js-sdk/src/autodiscovery";
import { logger } from "matrix-js-sdk/src/logger";
@ -45,7 +45,7 @@ export default class ServerPickerDialog extends React.PureComponent<IProps, ISta
private readonly fieldRef = createRef<Field>();
private validatedConf: ValidatedServerConfig;
public constructor(props) {
public constructor(props: IProps) {
super(props);
const config = SdkConfig.get();
@ -75,7 +75,7 @@ export default class ServerPickerDialog extends React.PureComponent<IProps, ISta
this.setState({ defaultChosen: false });
};
private onHomeserverChange = (ev): void => {
private onHomeserverChange = (ev: ChangeEvent<HTMLInputElement>): void => {
this.setState({ otherHomeserver: ev.target.value });
};
@ -149,7 +149,7 @@ export default class ServerPickerDialog extends React.PureComponent<IProps, ISta
private onHomeserverValidate = (fieldState: IFieldState): Promise<IValidationResult> => this.validate(fieldState);
private onSubmit = async (ev): Promise<void> => {
private onSubmit = async (ev: SyntheticEvent): Promise<void> => {
ev.preventDefault();
const valid = await this.fieldRef.current.validate({ allowEmpty: false });

View file

@ -36,12 +36,12 @@ const socials = [
{
name: "Facebook",
img: require("../../../../res/img/social/facebook.png"),
url: (url) => `https://www.facebook.com/sharer/sharer.php?u=${url}`,
url: (url: String) => `https://www.facebook.com/sharer/sharer.php?u=${url}`,
},
{
name: "Twitter",
img: require("../../../../res/img/social/twitter-2.png"),
url: (url) => `https://twitter.com/home?status=${url}`,
url: (url: string) => `https://twitter.com/home?status=${url}`,
},
/* // icon missing
name: 'Google Plus',
@ -50,17 +50,17 @@ const socials = [
},*/ {
name: "LinkedIn",
img: require("../../../../res/img/social/linkedin.png"),
url: (url) => `https://www.linkedin.com/shareArticle?mini=true&url=${url}`,
url: (url: string) => `https://www.linkedin.com/shareArticle?mini=true&url=${url}`,
},
{
name: "Reddit",
img: require("../../../../res/img/social/reddit.png"),
url: (url) => `https://www.reddit.com/submit?url=${url}`,
url: (url: string) => `https://www.reddit.com/submit?url=${url}`,
},
{
name: "email",
img: require("../../../../res/img/social/email-1.png"),
url: (url) => `mailto:?body=${url}`,
url: (url: string) => `mailto:?body=${url}`,
},
];
@ -75,7 +75,7 @@ interface IState {
}
export default class ShareDialog extends React.PureComponent<IProps, IState> {
public constructor(props) {
public constructor(props: IProps) {
super(props);
let permalinkCreator: RoomPermalinkCreator = null;
@ -91,9 +91,9 @@ export default class ShareDialog extends React.PureComponent<IProps, IState> {
};
}
public static onLinkClick(e): void {
public static onLinkClick(e: React.MouseEvent): void {
e.preventDefault();
selectText(e.target);
selectText(e.currentTarget);
}
private onLinkSpecificEventCheckboxClick = (): void => {

View file

@ -17,14 +17,14 @@ limitations under the License.
import React from "react";
import { _t } from "../../../languageHandler";
import { CommandCategories, Commands } from "../../../SlashCommands";
import { Command, CommandCategories, Commands } from "../../../SlashCommands";
import { IDialogProps } from "./IDialogProps";
import InfoDialog from "./InfoDialog";
interface IProps extends IDialogProps {}
const SlashCommandHelpDialog: React.FC<IProps> = ({ onFinished }) => {
const categories = {};
const categories: Record<string, Command[]> = {};
Commands.forEach((cmd) => {
if (!cmd.isEnabled()) return;
if (!categories[cmd.category]) {

View file

@ -21,6 +21,7 @@ import { SERVICE_TYPES } from "matrix-js-sdk/src/service-types";
import { _t, pickBestLanguage } from "../../../languageHandler";
import DialogButtons from "../elements/DialogButtons";
import BaseDialog from "./BaseDialog";
import { ServicePolicyPair } from "../../../Terms";
interface ITermsCheckboxProps {
onChange: (url: string, checked: boolean) => void;
@ -43,7 +44,7 @@ interface ITermsDialogProps {
* Array of [Service, policies] pairs, where policies is the response from the
* /terms endpoint for that service
*/
policiesAndServicePairs: any[];
policiesAndServicePairs: ServicePolicyPair[];
/**
* urls that the user has already agreed to
@ -63,7 +64,7 @@ interface IState {
}
export default class TermsDialog extends React.PureComponent<ITermsDialogProps, IState> {
public constructor(props) {
public constructor(props: ITermsDialogProps) {
super(props);
this.state = {
// url -> boolean

View file

@ -39,7 +39,7 @@ export default class UploadConfirmDialog extends React.Component<IProps> {
totalFiles: 1,
};
public constructor(props) {
public constructor(props: IProps) {
super(props);
// Create a fresh `Blob` for previewing (even though `File` already is

View file

@ -50,7 +50,7 @@ interface IState {
export default class UserSettingsDialog extends React.Component<IProps, IState> {
private settingsWatchers: string[] = [];
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.state = {

View file

@ -35,7 +35,7 @@ interface IState {
}
export default class VerificationRequestDialog extends React.Component<IProps, IState> {
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.state = {
verificationRequest: this.props.verificationRequest,

View file

@ -33,13 +33,12 @@ interface IProps extends IDialogProps {
widgetKind: WidgetKind; // TODO: Refactor into the Widget class
}
interface IBooleanStates {
// @ts-ignore - TS wants a string key, but we know better
[capability: Capability]: boolean;
}
type BooleanStates = Partial<{
[capability in Capability]: boolean;
}>;
interface IState {
booleanStates: IBooleanStates;
booleanStates: BooleanStates;
rememberSelection: boolean;
}
@ -52,7 +51,7 @@ export default class WidgetCapabilitiesPromptDialog extends React.PureComponent<
const parsedEvents = WidgetEventCapability.findEventCapabilities(this.props.requestedCapabilities);
parsedEvents.forEach((e) => this.eventPermissionsMap.set(e.raw, e));
const states: IBooleanStates = {};
const states: BooleanStates = {};
this.props.requestedCapabilities.forEach((c) => (states[c] = true));
this.state = {
@ -71,7 +70,7 @@ export default class WidgetCapabilitiesPromptDialog extends React.PureComponent<
this.setState({ rememberSelection: newVal });
};
private onSubmit = async (ev): Promise<void> => {
private onSubmit = async (): Promise<void> => {
this.closeAndTryRemember(
Object.entries(this.state.booleanStates)
.filter(([_, isSelected]) => isSelected)
@ -79,7 +78,7 @@ export default class WidgetCapabilitiesPromptDialog extends React.PureComponent<
);
};
private onReject = async (ev): Promise<void> => {
private onReject = async (): Promise<void> => {
this.closeAndTryRemember([]); // nothing was approved
};

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { useContext, useMemo, useRef, useState } from "react";
import React, { ChangeEvent, useContext, useMemo, useRef, useState } from "react";
import { IContent, MatrixEvent } from "matrix-js-sdk/src/models/event";
import { _t, _td } from "../../../../languageHandler";
@ -87,7 +87,7 @@ export const EventEditor: React.FC<IEventEditorProps> = ({ fieldDefs, defaultCon
type="text"
autoComplete="on"
value={fieldData[i]}
onChange={(ev) =>
onChange={(ev: ChangeEvent<HTMLInputElement>) =>
setFieldData((data) => {
data[i] = ev.target.value;
return [...data];

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { useEffect, useState } from "react";
import React, { ChangeEvent, useEffect, useState } from "react";
import { _t } from "../../../../languageHandler";
import Field from "../../elements/Field";
@ -72,7 +72,7 @@ const FilteredList: React.FC<IProps> = ({ children, query, onChange }) => {
type="text"
autoComplete="off"
value={query}
onChange={(ev) => onChange(ev.target.value)}
onChange={(ev: ChangeEvent<HTMLInputElement>) => onChange(ev.target.value)}
className="mx_TextInputDialog_input mx_DevTools_RoomStateExplorer_query"
// force re-render so that autoFocus is applied when this component is re-used
key={children?.[0]?.key ?? ""}

View file

@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { useContext, useMemo, useState } from "react";
import React, { ChangeEvent, useContext, useMemo, useState } from "react";
import { logger } from "matrix-js-sdk/src/logger";
import { _t } from "../../../../languageHandler";
@ -74,7 +74,7 @@ const CanEditLevelField: React.FC<ICanEditLevelFieldProps> = ({ setting, roomId,
};
function renderExplicitSettingValues(setting: string, roomId: string): string {
const vals = {};
const vals: Record<string, number | null> = {};
for (const level of LEVEL_ORDER) {
try {
vals[level] = SettingsStore.getValueAt(level, setting, roomId, true, true);
@ -283,7 +283,7 @@ const SettingsList: React.FC<ISettingsListProps> = ({ onBack, onView, onEdit })
type="text"
autoComplete="off"
value={query}
onChange={(ev) => setQuery(ev.target.value)}
onChange={(ev: ChangeEvent<HTMLInputElement>) => setQuery(ev.target.value)}
className="mx_TextInputDialog_input mx_DevTools_RoomStateExplorer_query"
/>
<table>

View file

@ -62,7 +62,7 @@ interface IState {
export default class AccessSecretStorageDialog extends React.PureComponent<IProps, IState> {
private fileUpload = React.createRef<HTMLInputElement>();
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.state = {

View file

@ -18,6 +18,7 @@ limitations under the License.
import React from "react";
import { CrossSigningKeys } from "matrix-js-sdk/src/client";
import { logger } from "matrix-js-sdk/src/logger";
import { UIAFlow } from "matrix-js-sdk/src/matrix";
import { MatrixClientPeg } from "../../../../MatrixClientPeg";
import { _t } from "../../../../languageHandler";
@ -82,7 +83,7 @@ export default class CreateCrossSigningDialog extends React.PureComponent<IProps
logger.log("uploadDeviceSigningKeys advertised no flows!");
return;
}
const canUploadKeysWithPasswordOnly = error.data.flows.some((f) => {
const canUploadKeysWithPasswordOnly = error.data.flows.some((f: UIAFlow) => {
return f.stages.length === 1 && f.stages[0] === "m.login.password";
});
this.setState({

View file

@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from "react";
import React, { ChangeEvent } from "react";
import { MatrixClient } from "matrix-js-sdk/src/client";
import { IKeyBackupInfo, IKeyBackupRestoreResult } from "matrix-js-sdk/src/crypto/keybackup";
import { ISecretStorageKeyInfo } from "matrix-js-sdk/src/crypto/api";
@ -81,7 +81,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent<IProps,
showSummary: true,
};
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.state = {
backupInfo: null,
@ -117,7 +117,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent<IProps,
});
};
private progressCallback = (data): void => {
private progressCallback = (data: IState["progress"]): void => {
this.setState({
progress: data,
});
@ -128,7 +128,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent<IProps,
accessSecretStorage(async (): Promise<void> => {}, /* forceReset = */ true);
};
private onRecoveryKeyChange = (e): void => {
private onRecoveryKeyChange = (e: ChangeEvent<HTMLInputElement>): void => {
this.setState({
recoveryKey: e.target.value,
recoveryKeyValid: MatrixClientPeg.get().isValidRecoveryKey(e.target.value),
@ -213,7 +213,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent<IProps,
}
};
private onPassPhraseChange = (e): void => {
private onPassPhraseChange = (e: ChangeEvent<HTMLInputElement>): void => {
this.setState({
passPhrase: e.target.value,
});
@ -247,7 +247,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent<IProps,
}
}
private async restoreWithCachedKey(backupInfo): Promise<boolean> {
private async restoreWithCachedKey(backupInfo?: IKeyBackupInfo): Promise<boolean> {
if (!backupInfo) return false;
try {
const recoverInfo = await MatrixClientPeg.get().restoreKeyBackupWithCache(

View file

@ -77,7 +77,7 @@ import BaseAvatar from "../../avatars/BaseAvatar";
import DecoratedRoomAvatar from "../../avatars/DecoratedRoomAvatar";
import { SearchResultAvatar } from "../../avatars/SearchResultAvatar";
import { NetworkDropdown } from "../../directory/NetworkDropdown";
import AccessibleButton from "../../elements/AccessibleButton";
import AccessibleButton, { ButtonEvent } from "../../elements/AccessibleButton";
import LabelledCheckbox from "../../elements/LabelledCheckbox";
import Spinner from "../../elements/Spinner";
import NotificationBadge from "../../rooms/NotificationBadge";
@ -625,7 +625,7 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", initialFilter = n
const showViewButton =
clientRoom?.getMyMembership() === "join" || result.publicRoom.world_readable || cli.isGuest();
const listener = (ev): void => {
const listener = (ev: ButtonEvent): void => {
const { publicRoom } = result;
viewRoom(
{

View file

@ -18,7 +18,7 @@ limitations under the License.
*/
import url from "url";
import React, { ContextType, createRef, MutableRefObject, ReactNode } from "react";
import React, { ContextType, createRef, CSSProperties, MutableRefObject, ReactNode } from "react";
import classNames from "classnames";
import { MatrixCapabilities } from "matrix-widget-api";
import { Room, RoomEvent } from "matrix-js-sdk/src/models/room";
@ -81,7 +81,7 @@ interface IProps {
// Is this an instance of a user widget
userWidget: boolean;
// sets the pointer-events property on the iframe
pointerEvents?: string;
pointerEvents?: CSSProperties["pointerEvents"];
widgetPageTitle?: string;
showLayoutButtons?: boolean;
// Handle to manually notify the PersistedElement that it needs to move
@ -562,9 +562,9 @@ export default class AppTile extends React.Component<IProps, IState> {
"microphone; camera; encrypted-media; autoplay; display-capture; clipboard-write; " + "clipboard-read;";
const appTileBodyClass = "mx_AppTileBody" + (this.props.miniMode ? "_mini " : " ");
const appTileBodyStyles = {};
const appTileBodyStyles: CSSProperties = {};
if (this.props.pointerEvents) {
appTileBodyStyles["pointerEvents"] = this.props.pointerEvents;
appTileBodyStyles.pointerEvents = this.props.pointerEvents;
}
const loadingElement = (

View file

@ -373,7 +373,7 @@ export default class Dropdown extends React.Component<DropdownProps, IState> {
);
}
const dropdownClasses = {
const dropdownClasses: Record<string, boolean> = {
mx_Dropdown: true,
mx_Dropdown_disabled: this.props.disabled,
};

View file

@ -14,11 +14,11 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from "react";
import React, { ChangeEvent } from "react";
import { _t } from "../../../languageHandler";
import Field from "./Field";
import AccessibleButton from "./AccessibleButton";
import AccessibleButton, { ButtonEvent } from "./AccessibleButton";
interface IItemProps {
index?: number;
@ -35,21 +35,21 @@ export class EditableItem extends React.Component<IItemProps, IItemState> {
verifyRemove: false,
};
private onRemove = (e): void => {
private onRemove = (e: ButtonEvent): void => {
e.stopPropagation();
e.preventDefault();
this.setState({ verifyRemove: true });
};
private onDontRemove = (e): void => {
private onDontRemove = (e: ButtonEvent): void => {
e.stopPropagation();
e.preventDefault();
this.setState({ verifyRemove: false });
};
private onActuallyRemove = (e): void => {
private onActuallyRemove = (e: ButtonEvent): void => {
e.stopPropagation();
e.preventDefault();
@ -105,19 +105,19 @@ interface IProps {
}
export default class EditableItemList<P = {}> extends React.PureComponent<IProps & P> {
protected onItemAdded = (e): void => {
protected onItemAdded = (e: ButtonEvent): void => {
e.stopPropagation();
e.preventDefault();
if (this.props.onItemAdded) this.props.onItemAdded(this.props.newItem);
this.props.onItemAdded?.(this.props.newItem);
};
protected onItemRemoved = (index: number): void => {
if (this.props.onItemRemoved) this.props.onItemRemoved(index);
this.props.onItemRemoved?.(index);
};
protected onNewItemChanged = (e): void => {
if (this.props.onNewItemChanged) this.props.onNewItemChanged(e.target.value);
protected onNewItemChanged = (e: ChangeEvent<HTMLInputElement>): void => {
this.props.onNewItemChanged?.(e.target.value);
};
protected renderNewItemField(): JSX.Element {

View file

@ -32,13 +32,13 @@ const EffectsOverlay: FunctionComponent<IProps> = ({ roomWidth }) => {
const lazyLoadEffectModule = async (name: string): Promise<ICanvasEffect> => {
if (!name) return null;
let effect: ICanvasEffect | null = effectsRef.current[name] || null;
let effect: ICanvasEffect | null = effectsRef.current.get(name) || null;
if (effect === null) {
const options = CHAT_EFFECTS.find((e) => e.command === name)?.options;
try {
const { default: Effect } = await import(`../../../effects/${name}`);
effect = new Effect(options);
effectsRef.current[name] = effect;
effectsRef.current.set(name, effect);
} catch (err) {
logger.warn(`Unable to load effect module at '../../../effects/${name}.`, err);
}
@ -70,7 +70,7 @@ const EffectsOverlay: FunctionComponent<IProps> = ({ roomWidth }) => {
// eslint-disable-next-line react-hooks/exhaustive-deps
const currentEffects = effectsRef.current; // this is not a react node ref, warning can be safely ignored
for (const effect in currentEffects) {
const effectModule: ICanvasEffect = currentEffects[effect];
const effectModule: ICanvasEffect = currentEffects.get(effect);
if (effectModule && effectModule.isRunning) {
effectModule.stop();
}

View file

@ -34,7 +34,7 @@ interface IState {
* catch exceptions during rendering in the component tree below them.
*/
export default class ErrorBoundary extends React.PureComponent<{}, IState> {
public constructor(props) {
public constructor(props: {}) {
super(props);
this.state = {

View file

@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { ComponentProps } from "react";
import React, { ComponentProps, ReactNode } from "react";
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
import { EventType } from "matrix-js-sdk/src/@types/event";
@ -161,7 +161,15 @@ export default class EventListSummary extends React.Component<IProps> {
* @returns {string[]} an array of transitions.
*/
private static getCanonicalTransitions(transitions: TransitionType[]): TransitionType[] {
const modMap = {
const modMap: Partial<
Record<
TransitionType,
{
after: TransitionType;
newTransition: TransitionType;
}
>
> = {
[TransitionType.Joined]: {
after: TransitionType.Left,
newTransition: TransitionType.JoinedAndLeft,
@ -170,10 +178,6 @@ export default class EventListSummary extends React.Component<IProps> {
after: TransitionType.Joined,
newTransition: TransitionType.LeftAndJoined,
},
// $currentTransition : {
// 'after' : $nextTransition,
// 'newTransition' : 'new_transition_type',
// },
};
const res: TransitionType[] = [];
@ -237,15 +241,11 @@ export default class EventListSummary extends React.Component<IProps> {
* @param {number} repeats the number of times the transition was repeated in a row.
* @returns {string} the written Human Readable equivalent of the transition.
*/
private static getDescriptionForTransition(
t: TransitionType,
userCount: number,
count: number,
): string | JSX.Element {
private static getDescriptionForTransition(t: TransitionType, userCount: number, count: number): ReactNode | null {
// The empty interpolations 'severalUsers' and 'oneUser'
// are there only to show translators to non-English languages
// that the verb is conjugated to plural or singular Subject.
let res = null;
let res: ReactNode | undefined;
switch (t) {
case TransitionType.Joined:
res =
@ -377,7 +377,7 @@ export default class EventListSummary extends React.Component<IProps> {
break;
}
return res;
return res ?? null;
}
private static getTransitionSequence(events: IUserEvents[]): TransitionType[] {

View file

@ -145,7 +145,7 @@ export default class Field extends React.PureComponent<PropShapes, IState> {
});
}, VALIDATION_THROTTLE_MS);
public constructor(props) {
public constructor(props: PropShapes) {
super(props);
this.state = {
valid: undefined,
@ -165,7 +165,7 @@ export default class Field extends React.PureComponent<PropShapes, IState> {
});
}
private onFocus = (ev): void => {
private onFocus = (ev: React.FocusEvent<any>): void => {
this.setState({
focused: true,
});
@ -175,22 +175,18 @@ export default class Field extends React.PureComponent<PropShapes, IState> {
});
}
// Parent component may have supplied its own `onFocus` as well
if (this.props.onFocus) {
this.props.onFocus(ev);
}
this.props.onFocus?.(ev);
};
private onChange = (ev): void => {
private onChange = (ev: React.ChangeEvent<any>): void => {
if (this.props.validateOnChange) {
this.validateOnChange();
}
// Parent component may have supplied its own `onChange` as well
if (this.props.onChange) {
this.props.onChange(ev);
}
this.props.onChange?.(ev);
};
private onBlur = (ev): void => {
private onBlur = (ev: React.FocusEvent<any>): void => {
this.setState({
focused: false,
});
@ -200,9 +196,7 @@ export default class Field extends React.PureComponent<PropShapes, IState> {
});
}
// Parent component may have supplied its own `onBlur` as well
if (this.props.onBlur) {
this.props.onBlur(ev);
}
this.props.onBlur?.(ev);
};
public async validate({ focused, allowEmpty = true }: IValidateOpts): Promise<boolean> {

View file

@ -91,7 +91,7 @@ interface IState {
}
export default class ImageView extends React.Component<IProps, IState> {
public constructor(props) {
public constructor(props: IProps) {
super(props);
const { thumbnailInfo } = this.props;

View file

@ -308,8 +308,8 @@ export default class InteractiveTooltip extends React.Component<IProps, IState>
side: Direction.Top,
};
public constructor(props, context) {
super(props, context);
public constructor(props: IProps) {
super(props);
this.state = {
contentRect: null,

View file

@ -30,7 +30,7 @@ interface IState {
}
export default class InviteReason extends React.PureComponent<IProps, IState> {
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.state = {
// We hide the reason for invitation by default, since it can be a

View file

@ -22,22 +22,24 @@ import { Caption } from "../typography/Caption";
interface IProps {
// The value for the toggle switch
value: boolean;
"value": boolean;
// The translated label for the switch
label: string;
"label": string;
// The translated caption for the switch
caption?: string;
"caption"?: string;
// Tooltip to display
tooltip?: string;
"tooltip"?: string;
// Whether or not to disable the toggle switch
disabled?: boolean;
"disabled"?: boolean;
// True to put the toggle in front of the label
// Default false.
toggleInFront?: boolean;
"toggleInFront"?: boolean;
// Additional class names to append to the switch. Optional.
className?: string;
"className"?: string;
// The function to call when the value changes
onChange(checked: boolean): void;
"data-testid"?: string;
}
export default class LabelledToggleSwitch extends React.PureComponent<IProps> {

View file

@ -32,7 +32,7 @@ export default class Measured extends React.PureComponent<IProps> {
breakpoint: 500,
};
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.instanceId = Measured.instanceCount++;

View file

@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { ContextType, MutableRefObject } from "react";
import React, { ContextType, CSSProperties, MutableRefObject } from "react";
import { Room } from "matrix-js-sdk/src/models/room";
import WidgetUtils from "../../../utils/WidgetUtils";
@ -26,7 +26,7 @@ import MatrixClientContext from "../../../contexts/MatrixClientContext";
interface IProps {
persistentWidgetId: string;
persistentRoomId: string;
pointerEvents?: string;
pointerEvents?: CSSProperties["pointerEvents"];
movePersistedElement: MutableRefObject<(() => void) | undefined>;
}

View file

@ -20,6 +20,7 @@ import { Room } from "matrix-js-sdk/src/models/room";
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
import { logger } from "matrix-js-sdk/src/logger";
import { MatrixClient } from "matrix-js-sdk/src/client";
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import dis from "../../../dispatcher/dispatcher";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
@ -30,6 +31,7 @@ import Tooltip, { Alignment } from "./Tooltip";
import RoomAvatar from "../avatars/RoomAvatar";
import MemberAvatar from "../avatars/MemberAvatar";
import { objectHasDiff } from "../../../utils/objects";
import { ButtonEvent } from "./AccessibleButton";
export enum PillType {
UserMention = "TYPE_USER_MENTION",
@ -180,7 +182,7 @@ export default class Pill extends React.Component<IProps, IState> {
});
};
private doProfileLookup(userId: string, member): void {
private doProfileLookup(userId: string, member: RoomMember): void {
MatrixClientPeg.get()
.getProfileInfo(userId)
.then((resp) => {
@ -196,7 +198,7 @@ export default class Pill extends React.Component<IProps, IState> {
getDirectionalContent: function () {
return this.getContent();
},
};
} as MatrixEvent;
this.setState({ member });
})
.catch((err) => {
@ -204,7 +206,7 @@ export default class Pill extends React.Component<IProps, IState> {
});
}
private onUserPillClicked = (e): void => {
private onUserPillClicked = (e: ButtonEvent): void => {
e.preventDefault();
dis.dispatch({
action: Action.ViewUser,

View file

@ -44,7 +44,7 @@ export default class RoomAliasField extends React.PureComponent<IProps, IState>
private fieldRef = createRef<Field>();
public constructor(props, context) {
public constructor(props: IProps, context: React.ContextType<typeof MatrixClientContext>) {
super(props, context);
this.state = {

View file

@ -42,7 +42,7 @@ const RoomFacePile: FC<IProps> = ({ room, onlyKnownUsers = true, numShown = DEFA
const count = members.length;
// sort users with an explicit avatar first
const iteratees = [(member) => (member.getMxcAvatarUrl() ? 0 : 1)];
const iteratees = [(member: RoomMember) => (member.getMxcAvatarUrl() ? 0 : 1)];
if (onlyKnownUsers) {
members = members.filter(isKnownMember);
} else {

View file

@ -23,7 +23,7 @@ import SdkConfig from "../../../SdkConfig";
import dis from "../../../dispatcher/dispatcher";
import { Action } from "../../../dispatcher/actions";
import { UserTab } from "../dialogs/UserTab";
import AccessibleButton from "./AccessibleButton";
import AccessibleButton, { ButtonEvent } from "./AccessibleButton";
export enum WarningKind {
Files,
@ -49,7 +49,7 @@ export default function SearchWarning({ isRoomEncrypted, kind }: IProps): JSX.El
a: (sub) => (
<AccessibleButton
kind="link_inline"
onClick={(evt) => {
onClick={(evt: ButtonEvent) => {
evt.preventDefault();
dis.dispatch({
action: Action.ViewUserSettings,

View file

@ -33,7 +33,7 @@ function languageMatchesSearchQuery(query: string, language: Languages[0]): bool
interface SpellCheckLanguagesDropdownIProps {
className: string;
value: string;
onOptionChange(language: string);
onOptionChange(language: string): void;
}
interface SpellCheckLanguagesDropdownIState {
@ -45,7 +45,7 @@ export default class SpellCheckLanguagesDropdown extends React.Component<
SpellCheckLanguagesDropdownIProps,
SpellCheckLanguagesDropdownIState
> {
public constructor(props) {
public constructor(props: SpellCheckLanguagesDropdownIProps) {
super(props);
this.onSearchChange = this.onSearchChange.bind(this);

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { ReactNode } from "react";
import React, { ChangeEvent, ReactNode } from "react";
import classNames from "classnames";
import StyledRadioButton from "./StyledRadioButton";
@ -47,8 +47,8 @@ function StyledRadioGroup<T extends string>({
disabled,
onChange,
}: IProps<T>): JSX.Element {
const _onChange = (e): void => {
onChange(e.target.value);
const _onChange = (e: ChangeEvent<HTMLInputElement>): void => {
onChange(e.target.value as T);
};
return (

View file

@ -68,7 +68,7 @@ export default class Tooltip extends React.PureComponent<ITooltipProps, State> {
alignment: Alignment.Natural,
};
public constructor(props) {
public constructor(props: ITooltipProps) {
super(props);
this.state = {};
@ -92,7 +92,7 @@ export default class Tooltip extends React.PureComponent<ITooltipProps, State> {
this.updatePosition();
}
public componentDidUpdate(prevProps): void {
public componentDidUpdate(prevProps: ITooltipProps): void {
if (objectHasDiff(prevProps, this.props)) {
this.updatePosition();
}

View file

@ -24,7 +24,7 @@ interface IProps {
}
export default class TooltipButton extends React.Component<IProps> {
public constructor(props) {
public constructor(props: IProps) {
super(props);
}

View file

@ -40,7 +40,7 @@ interface IProps {
export default class TruncatedList extends React.Component<IProps> {
public static defaultProps = {
truncateAt: 2,
createOverflowElement(overflowCount, totalCount) {
createOverflowElement(overflowCount: number, totalCount: number) {
return <div>{_t("And %(count)s more...", { count: overflowCount })}</div>;
},
};

View file

@ -40,7 +40,7 @@ interface IState {
}
class QuickReactions extends React.Component<IProps, IState> {
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.state = {
hover: null,

View file

@ -50,7 +50,7 @@ class ReactionPicker extends React.Component<IProps, IState> {
this.addListeners();
}
public componentDidUpdate(prevProps): void {
public componentDidUpdate(prevProps: IProps): void {
if (prevProps.reactions !== this.props.reactions) {
this.addListeners();
this.onReactionsChange();
@ -78,7 +78,7 @@ class ReactionPicker extends React.Component<IProps, IState> {
return {};
}
const userId = MatrixClientPeg.get().getUserId();
const myAnnotations = this.props.reactions.getAnnotationsBySender()[userId] || [];
const myAnnotations = this.props.reactions.getAnnotationsBySender()[userId] || new Set<MatrixEvent>();
return Object.fromEntries(
[...myAnnotations]
.filter((event) => !event.isRedacted())

View file

@ -38,7 +38,7 @@ type Props = Omit<ILocationPickerProps, "onChoose" | "shareType"> & {
relation?: IEventRelation;
};
const getEnabledShareTypes = (relation): LocationShareType[] => {
const getEnabledShareTypes = (relation?: IEventRelation): LocationShareType[] => {
const enabledShareTypes = [LocationShareType.Own];
// live locations cannot have a relation

View file

@ -53,10 +53,10 @@ interface IState {
}
export default class DateSeparator extends React.Component<IProps, IState> {
private settingWatcherRef = null;
private settingWatcherRef?: string;
public constructor(props, context) {
super(props, context);
public constructor(props: IProps) {
super(props);
this.state = {
jumpToDateEnabled: SettingsStore.getValue("feature_jump_to_date"),
};
@ -116,7 +116,7 @@ export default class DateSeparator extends React.Component<IProps, IState> {
}
}
private pickDate = async (inputTimestamp): Promise<void> => {
private pickDate = async (inputTimestamp: number | string | Date): Promise<void> => {
const unixTimestamp = new Date(inputTimestamp).getTime();
const cli = MatrixClientPeg.get();
@ -175,7 +175,7 @@ export default class DateSeparator extends React.Component<IProps, IState> {
this.closeMenu();
};
private onDatePicked = (dateString): void => {
private onDatePicked = (dateString: string): void => {
this.pickDate(dateString);
this.closeMenu();
};

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { forwardRef, ReactNode, ReactChildren } from "react";
import React, { forwardRef, ReactNode, ReactChild } from "react";
import classNames from "classnames";
interface IProps {
@ -22,7 +22,7 @@ interface IProps {
title: string;
timestamp?: JSX.Element;
subtitle?: ReactNode;
children?: ReactChildren;
children?: ReactChild;
}
const EventTileBubble = forwardRef<HTMLDivElement, IProps>(

View file

@ -16,6 +16,7 @@ limitations under the License.
import React from "react";
import { logger } from "matrix-js-sdk/src/logger";
import { IContent } from "matrix-js-sdk/src/matrix";
import { Playback } from "../../../audio/Playback";
import InlineSpinner from "../elements/InlineSpinner";
@ -66,8 +67,8 @@ export default class MAudioBody extends React.PureComponent<IBodyProps, IState>
// We should have a buffer to work with now: let's set it up
// Note: we don't actually need a waveform to render an audio event, but voice messages do.
const content = this.props.mxEvent.getContent<IMediaEventContent>();
const waveform = content?.["org.matrix.msc1767.audio"]?.waveform?.map((p) => p / 1024);
const content = this.props.mxEvent.getContent<IMediaEventContent & IContent>();
const waveform = content?.["org.matrix.msc1767.audio"]?.waveform?.map((p: number) => p / 1024);
// We should have a buffer to work with now: let's set it up
const playback = PlaybackManager.instance.createPlaybackInstance(buffer, waveform);

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { createRef } from "react";
import React, { AllHTMLAttributes, createRef } from "react";
import { filesize } from "filesize";
import { logger } from "matrix-js-sdk/src/logger";
@ -30,7 +30,7 @@ import { FileDownloader } from "../../../utils/FileDownloader";
import TextWithTooltip from "../elements/TextWithTooltip";
import RoomContext, { TimelineRenderingType } from "../../../contexts/RoomContext";
export let DOWNLOAD_ICON_URL; // cached copy of the download.svg asset for the sandboxed iframe later on
export let DOWNLOAD_ICON_URL: string; // cached copy of the download.svg asset for the sandboxed iframe later on
async function cacheDownloadIcon(): Promise<void> {
if (DOWNLOAD_ICON_URL) return; // cached already
@ -155,7 +155,7 @@ export default class MFileBody extends React.Component<IProps, IState> {
});
}
public componentDidUpdate(prevProps, prevState): void {
public componentDidUpdate(prevProps: IProps, prevState: IState): void {
if (this.props.onHeightChanged && !prevState.decryptedBlob && this.state.decryptedBlob) {
this.props.onHeightChanged();
}
@ -295,7 +295,7 @@ export default class MFileBody extends React.Component<IProps, IState> {
</span>
);
} else if (contentUrl) {
const downloadProps = {
const downloadProps: AllHTMLAttributes<HTMLAnchorElement> = {
target: "_blank",
rel: "noreferrer noopener",

View file

@ -29,7 +29,7 @@ interface IProps {
}
export default class MJitsiWidgetEvent extends React.PureComponent<IProps> {
public constructor(props) {
public constructor(props: IProps) {
super(props);
}

View file

@ -122,9 +122,9 @@ export default class MKeyVerificationRequest extends React.Component<IProps> {
return null;
}
let title;
let subtitle;
let stateNode;
let title: string;
let subtitle: string;
let stateNode: JSX.Element;
if (!request.canAccept) {
let stateLabel;

View file

@ -47,7 +47,7 @@ export default class MVideoBody extends React.PureComponent<IBodyProps, IState>
private videoRef = React.createRef<HTMLVideoElement>();
private sizeWatcher: string;
public constructor(props) {
public constructor(props: IBodyProps) {
super(props);
this.state = {

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React from "react";
import React, { SyntheticEvent } from "react";
import classNames from "classnames";
import { MatrixEvent, MatrixEventEvent } from "matrix-js-sdk/src/models/event";
import { Relations, RelationsEvent } from "matrix-js-sdk/src/models/relations";
@ -52,7 +52,7 @@ const ReactButton: React.FC<IProps> = ({ mxEvent, reactions }) => {
})}
title={_t("Add reaction")}
onClick={openMenu}
onContextMenu={(e) => {
onContextMenu={(e: SyntheticEvent): void => {
e.preventDefault();
openMenu();
}}

View file

@ -35,6 +35,7 @@ interface IProps {
export default class ReactionsRowButtonTooltip extends React.PureComponent<IProps> {
public static contextType = MatrixClientContext;
public context!: React.ContextType<typeof MatrixClientContext>;
public render(): JSX.Element {
const { content, reactionEvents, mxEvent, visible } = this.props;
@ -42,7 +43,7 @@ export default class ReactionsRowButtonTooltip extends React.PureComponent<IProp
const room = this.context.getRoom(mxEvent.getRoomId());
let tooltipLabel;
if (room) {
const senders = [];
const senders: string[] = [];
for (const reactionEvent of reactionEvents) {
const member = room.getMember(reactionEvent.getSender());
const name = member ? member.name : reactionEvent.getSender();

View file

@ -70,7 +70,7 @@ export default class TextualBody extends React.Component<IBodyProps, IState> {
public static contextType = RoomContext;
public context!: React.ContextType<typeof RoomContext>;
public constructor(props) {
public constructor(props: IBodyProps) {
super(props);
this.state = {

View file

@ -37,7 +37,7 @@ interface IState {
}
export default class TileErrorBoundary extends React.Component<IProps, IState> {
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.state = {

View file

@ -31,7 +31,7 @@ interface IState {
}
export default class ViewSourceEvent extends React.PureComponent<IProps, IState> {
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.state = {

View file

@ -26,6 +26,7 @@ import { RightPanelPhases } from "../../../stores/right-panel/RightPanelStorePha
import { IRightPanelCardState } from "../../../stores/right-panel/RightPanelStoreIPanelState";
import { UPDATE_EVENT } from "../../../stores/AsyncStore";
import { NotificationColor } from "../../../stores/notifications/NotificationColor";
import { ActionPayload } from "../../../dispatcher/payloads";
export enum HeaderKind {
Room = "room",
@ -67,7 +68,7 @@ export default abstract class HeaderButtons<P = {}> extends React.Component<IPro
if (this.dispatcherRef) dis.unregister(this.dispatcherRef);
}
protected abstract onAction(payload);
protected abstract onAction(payload: ActionPayload): void;
public setPhase(phase: RightPanelPhases, cardState?: Partial<IRightPanelCardState>): void {
const rps = RightPanelStore.instance;

View file

@ -15,8 +15,9 @@ limitations under the License.
*/
import React, { ChangeEvent, ContextType, createRef, SyntheticEvent } from "react";
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { IContent, MatrixEvent } from "matrix-js-sdk/src/models/event";
import { logger } from "matrix-js-sdk/src/logger";
import { EventType } from "matrix-js-sdk/src/@types/event";
import EditableItemList from "../elements/EditableItemList";
import { _t } from "../../../languageHandler";
@ -52,7 +53,7 @@ class EditableAliasesList extends EditableItemList<IEditableAliasesListProps> {
};
protected renderNewItemField(): JSX.Element {
const onChange = (alias: string): void => this.onNewItemChanged({ target: { value: alias } });
const onChange = (alias: string): void => this.props.onNewItemChanged?.(alias);
return (
<form
onSubmit={this.onAliasAdded}
@ -103,10 +104,10 @@ export default class AliasSettings extends React.Component<IProps, IState> {
canSetCanonicalAlias: false,
};
public constructor(props, context: ContextType<typeof MatrixClientContext>) {
public constructor(props: IProps, context: ContextType<typeof MatrixClientContext>) {
super(props, context);
const state = {
const state: IState = {
altAliases: [], // [ #alias:domain.tld, ... ]
localAliases: [], // [ #alias:my-hs.tld, ... ]
canonicalAlias: null, // #canonical:domain.tld
@ -140,7 +141,7 @@ export default class AliasSettings extends React.Component<IProps, IState> {
try {
const mxClient = this.context;
let localAliases = [];
let localAliases: string[] = [];
const response = await mxClient.getLocalAliases(this.props.roomId);
if (Array.isArray(response?.aliases)) {
localAliases = response.aliases;
@ -164,14 +165,14 @@ export default class AliasSettings extends React.Component<IProps, IState> {
updatingCanonicalAlias: true,
});
const eventContent = {
const eventContent: IContent = {
alt_aliases: this.state.altAliases,
};
if (alias) eventContent["alias"] = alias;
this.context
.sendStateEvent(this.props.roomId, "m.room.canonical_alias", eventContent, "")
.sendStateEvent(this.props.roomId, EventType.RoomCanonicalAlias, eventContent, "")
.catch((err) => {
logger.error(err);
Modal.createDialog(ErrorDialog, {
@ -195,7 +196,7 @@ export default class AliasSettings extends React.Component<IProps, IState> {
updatingCanonicalAlias: true,
});
const eventContent = {};
const eventContent: IContent = {};
if (this.state.canonicalAlias) {
eventContent["alias"] = this.state.canonicalAlias;
@ -205,7 +206,7 @@ export default class AliasSettings extends React.Component<IProps, IState> {
}
this.context
.sendStateEvent(this.props.roomId, "m.room.canonical_alias", eventContent, "")
.sendStateEvent(this.props.roomId, EventType.RoomCanonicalAlias, eventContent, "")
.then(() => {
this.setState({
altAliases,

View file

@ -33,15 +33,15 @@ interface IState {
}
export default class RoomPublishSetting extends React.PureComponent<IProps, IState> {
public constructor(props, context) {
super(props, context);
public constructor(props: IProps) {
super(props);
this.state = {
isRoomPublished: false,
};
}
private onRoomPublishChange = (e): void => {
private onRoomPublishChange = (): void => {
const valueBefore = this.state.isRoomPublished;
const newValue = !valueBefore;
this.setState({ isRoomPublished: newValue });

View file

@ -45,8 +45,7 @@ interface IProps {
}
interface IState {
// @ts-ignore - TS wants a string key, but we know better
apps: { [id: Container]: IApp[] };
apps: Partial<{ [id in Container]: IApp[] }>;
resizingVertical: boolean; // true when changing the height of the apps drawer
resizingHorizontal: boolean; // true when changing the distribution of the width between widgets
resizing: boolean;
@ -203,10 +202,9 @@ export default class AppsDrawer extends React.Component<IProps, IState> {
break;
}
};
// @ts-ignore - TS wants a string key, but we know better
private getApps = (): { [id: Container]: IApp[] } => {
// @ts-ignore
const appsDict: { [id: Container]: IApp[] } = {};
private getApps = (): Partial<{ [id in Container]: IApp[] }> => {
const appsDict: Partial<{ [id in Container]: IApp[] }> = {};
appsDict[Container.Top] = WidgetLayoutStore.instance.getContainerWidgets(this.props.room, Container.Top);
appsDict[Container.Center] = WidgetLayoutStore.instance.getContainerWidgets(this.props.room, Container.Center);
return appsDict;

View file

@ -57,7 +57,7 @@ export default class Autocomplete extends React.PureComponent<IProps, IState> {
public static contextType = RoomContext;
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.state = {

View file

@ -55,7 +55,7 @@ export default class AuxPanel extends React.Component<IProps, IState> {
showApps: true,
};
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.state = {
@ -76,7 +76,7 @@ export default class AuxPanel extends React.Component<IProps, IState> {
}
}
public shouldComponentUpdate(nextProps, nextState): boolean {
public shouldComponentUpdate(nextProps: IProps, nextState: IState): boolean {
return objectHasDiff(this.props, nextProps) || objectHasDiff(this.state, nextState);
}
@ -146,9 +146,9 @@ export default class AuxPanel extends React.Component<IProps, IState> {
);
}
let stateViews = null;
let stateViews: JSX.Element | null = null;
if (this.state.counters && SettingsStore.getValue("feature_state_counters")) {
const counters = [];
const counters: JSX.Element[] = [];
this.state.counters.forEach((counter, idx) => {
const title = counter.title;

View file

@ -32,7 +32,7 @@ import {
} from "../../../editor/operations";
import { getCaretOffsetAndText, getRangeForSelection } from "../../../editor/dom";
import Autocomplete, { generateCompletionDomId } from "../rooms/Autocomplete";
import { getAutoCompleteCreator, Part, Type } from "../../../editor/parts";
import { getAutoCompleteCreator, Part, SerializedPart, Type } from "../../../editor/parts";
import { parseEvent, parsePlainTextMessage } from "../../../editor/deserialize";
import { renderModel } from "../../../editor/render";
import SettingsStore from "../../../settings/SettingsStore";
@ -107,7 +107,7 @@ interface IProps {
initialCaret?: DocumentOffset;
disabled?: boolean;
onChange?();
onChange?(): void;
onPaste?(event: ClipboardEvent<HTMLDivElement>, model: EditorModel): boolean;
}
@ -140,7 +140,7 @@ export default class BasicMessageEditor extends React.Component<IProps, IState>
private readonly surroundWithHandle: string;
private readonly historyManager = new HistoryManager();
public constructor(props) {
public constructor(props: IProps) {
super(props);
this.state = {
showPillAvatar: SettingsStore.getValue("Pill.shouldShowPillAvatar"),
@ -367,7 +367,7 @@ export default class BasicMessageEditor extends React.Component<IProps, IState>
let parts: Part[];
if (partsText) {
const serializedTextParts = JSON.parse(partsText);
parts = serializedTextParts.map((p) => partCreator.deserializePart(p));
parts = serializedTextParts.map((p: SerializedPart) => partCreator.deserializePart(p));
} else {
parts = parsePlainTextMessage(plainText, partCreator, { shouldEscape: false });
}

View file

@ -29,7 +29,7 @@ import { getCaretOffsetAndText } from "../../../editor/dom";
import { htmlSerializeIfNeeded, textSerialize, containsEmote, stripEmoteCommand } from "../../../editor/serialize";
import { findEditableEvent } from "../../../utils/EventUtils";
import { parseEvent } from "../../../editor/deserialize";
import { CommandPartCreator, Part, PartCreator } from "../../../editor/parts";
import { CommandPartCreator, Part, PartCreator, SerializedPart } from "../../../editor/parts";
import EditorStateTransfer from "../../../utils/EditorStateTransfer";
import BasicMessageComposer, { REGEX_EMOTICON } from "./BasicMessageComposer";
import { CommandCategories } from "../../../SlashCommands";
@ -59,7 +59,7 @@ function getHtmlReplyFallback(mxEvent: MatrixEvent): string {
}
function getTextReplyFallback(mxEvent: MatrixEvent): string {
const body = mxEvent.getContent().body;
const body: string = mxEvent.getContent().body;
const lines = body.split("\n").map((l) => l.trim());
if (lines.length > 2 && lines[0].startsWith("> ") && lines[1].length === 0) {
return `${lines[0]}\n\n`;
@ -253,7 +253,7 @@ class EditMessageComposer extends React.Component<IEditMessageComposerProps, ISt
if (json) {
try {
const { parts: serializedParts } = JSON.parse(json);
const parts: Part[] = serializedParts.map((p) => partCreator.deserializePart(p));
const parts: Part[] = serializedParts.map((p: SerializedPart) => partCreator.deserializePart(p));
return parts;
} catch (e) {
logger.error("Error parsing editing state: ", e);

Some files were not shown because too many files have changed in this diff Show more