Enable @typescript-eslint/explicit-function-return-type in /src (#9788)

* Enable `@typescript-eslint/explicit-member-accessibility` on /src

* Prettier

* Enable `@typescript-eslint/explicit-function-return-type` in /src

* Fix types

* tsc strict fixes

* Delint

* Fix test

* Fix bad merge
This commit is contained in:
Michael Telatynski 2023-01-12 13:25:14 +00:00 committed by GitHub
parent 7a36ba0fde
commit 030b7e90bf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
683 changed files with 3459 additions and 3013 deletions

View file

@ -102,7 +102,7 @@ export default function AccessibleButton<T extends keyof JSX.IntrinsicElements>(
onKeyUp,
triggerOnMouseDown,
...restProps
}: IProps<T>) {
}: IProps<T>): JSX.Element {
const newProps: IAccessibleButtonProps = restProps;
if (disabled) {
newProps["aria-disabled"] = true;

View file

@ -43,7 +43,7 @@ export default class AccessibleTooltipButton extends React.PureComponent<IProps,
};
}
public componentDidUpdate(prevProps: Readonly<IProps>) {
public componentDidUpdate(prevProps: Readonly<IProps>): void {
if (!prevProps.forceHide && this.props.forceHide && this.state.hover) {
this.setState({
hover: false,
@ -51,7 +51,7 @@ export default class AccessibleTooltipButton extends React.PureComponent<IProps,
}
}
private showTooltip = () => {
private showTooltip = (): void => {
if (this.props.onHover) this.props.onHover(true);
if (this.props.forceHide) return;
this.setState({
@ -59,7 +59,7 @@ export default class AccessibleTooltipButton extends React.PureComponent<IProps,
});
};
private hideTooltip = (ev: SyntheticEvent) => {
private hideTooltip = (ev: SyntheticEvent): void => {
if (this.props.onHover) this.props.onHover(false);
this.setState({
hover: false,
@ -67,13 +67,13 @@ export default class AccessibleTooltipButton extends React.PureComponent<IProps,
this.props.onHideTooltip?.(ev);
};
private onFocus = (ev: FocusEvent) => {
private onFocus = (ev: FocusEvent): void => {
// We only show the tooltip if focus arrived here from some other
// element, to avoid leaving tooltips hanging around when a modal closes
if (ev.relatedTarget) this.showTooltip();
};
public render() {
public render(): JSX.Element {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { title, tooltip, children, tooltipClassName, forceHide, alignment, onHideTooltip, ...props } =
this.props;

View file

@ -88,7 +88,7 @@ export default class AppPermission extends React.Component<IProps, IState> {
}
}
public render() {
public render(): JSX.Element {
const brand = SdkConfig.get().brand;
const displayName = this.state.roomMember ? this.state.roomMember.name : this.props.creatorUserId;

View file

@ -147,7 +147,7 @@ export default class AppTile extends React.Component<IProps, IState> {
this.state = this.getNewState(props);
}
private watchUserReady = () => {
private watchUserReady = (): void => {
if (OwnProfileStore.instance.isProfileInfoFetched) {
return;
}
@ -168,7 +168,7 @@ export default class AppTile extends React.Component<IProps, IState> {
return allowed || props.userId === props.creatorUserId;
};
private onUserLeftRoom() {
private onUserLeftRoom(): void {
const isActiveWidget = ActiveWidgetStore.instance.getWidgetPersistence(
this.props.app.id,
this.props.app.roomId,
@ -304,13 +304,13 @@ export default class AppTile extends React.Component<IProps, IState> {
OwnProfileStore.instance.removeListener(UPDATE_EVENT, this.onUserReady);
}
private setupSgListeners() {
private setupSgListeners(): void {
this.sgWidget.on("preparing", this.onWidgetPreparing);
// emits when the capabilities have been set up or changed
this.sgWidget.on("capabilitiesNotified", this.onWidgetCapabilitiesNotified);
}
private stopSgListeners() {
private stopSgListeners(): void {
if (!this.sgWidget) return;
this.sgWidget.off("preparing", this.onWidgetPreparing);
this.sgWidget.off("capabilitiesNotified", this.onWidgetCapabilitiesNotified);
@ -337,7 +337,7 @@ export default class AppTile extends React.Component<IProps, IState> {
});
}
private startMessaging() {
private startMessaging(): void {
try {
this.sgWidget?.startMessaging(this.iframe);
} catch (e) {
@ -490,7 +490,7 @@ export default class AppTile extends React.Component<IProps, IState> {
);
}
private reload() {
private reload(): void {
this.endWidgetActions().then(() => {
// reset messaging
this.resetWidget(this.props);

View file

@ -33,13 +33,13 @@ interface IProps {
const CopyableText: React.FC<IProps> = ({ children, getTextToCopy, border = true, className }) => {
const [tooltip, setTooltip] = useState<string | undefined>(undefined);
const onCopyClickInternal = async (e: ButtonEvent) => {
const onCopyClickInternal = async (e: ButtonEvent): Promise<void> => {
e.preventDefault();
const successful = await copyPlaintext(getTextToCopy());
setTooltip(successful ? _t("Copied!") : _t("Failed to copy"));
};
const onHideTooltip = () => {
const onHideTooltip = (): void => {
if (tooltip) {
setTooltip(undefined);
}

View file

@ -55,7 +55,7 @@ export class ExistingSource extends React.Component<ExistingSourceIProps> {
this.props.onSelect(this.props.source);
};
public render() {
public render(): JSX.Element {
const thumbnailClasses = classNames({
mx_desktopCapturerSourcePicker_source_thumbnail: true,
mx_desktopCapturerSourcePicker_source_thumbnail_selected: this.props.selected,
@ -96,7 +96,7 @@ export default class DesktopCapturerSourcePicker extends React.Component<PickerI
};
}
public async componentDidMount() {
public async componentDidMount(): Promise<void> {
// window.setInterval() first waits and then executes, therefore
// we call getDesktopCapturerSources() here without any delay.
// Otherwise the dialog would be left empty for some time.
@ -105,14 +105,14 @@ export default class DesktopCapturerSourcePicker extends React.Component<PickerI
});
// We update the sources every 500ms to get newer thumbnails
this.interval = window.setInterval(async () => {
this.interval = window.setInterval(async (): Promise<void> => {
this.setState({
sources: await getDesktopCapturerSources(),
});
}, 500);
}
public componentWillUnmount() {
public componentWillUnmount(): void {
clearInterval(this.interval);
}
@ -149,7 +149,7 @@ export default class DesktopCapturerSourcePicker extends React.Component<PickerI
return new Tab(type, label, null, <div className="mx_desktopCapturerSourcePicker_tab">{sources}</div>);
}
public render() {
public render(): JSX.Element {
const tabs = [
this.getTab("screen", _t("Share entire screen")),
this.getTab("window", _t("Application window")),

View file

@ -25,7 +25,7 @@ interface IProps {
}
export default class DialPadBackspaceButton extends React.PureComponent<IProps> {
public render() {
public render(): JSX.Element {
return (
<div className="mx_DialPadBackspaceButtonWrapper">
<AccessibleButton

View file

@ -73,7 +73,7 @@ export default class Draggable extends React.Component<IProps, IState> {
});
}
public render() {
public render(): JSX.Element {
return <div className={this.props.className} onMouseDown={this.onMouseDown} />;
}
}

View file

@ -39,17 +39,17 @@ class MenuOption extends React.Component<IMenuOptionProps> {
disabled: false,
};
private onMouseEnter = () => {
private onMouseEnter = (): void => {
this.props.onMouseEnter(this.props.dropdownKey);
};
private onClick = (e: React.MouseEvent) => {
private onClick = (e: React.MouseEvent): void => {
e.preventDefault();
e.stopPropagation();
this.props.onClick(this.props.dropdownKey);
};
public render() {
public render(): JSX.Element {
const optClasses = classnames({
mx_Dropdown_option: true,
mx_Dropdown_option_highlight: this.props.highlighted,
@ -139,7 +139,7 @@ export default class Dropdown extends React.Component<DropdownProps, IState> {
document.addEventListener("click", this.onDocumentClick, false);
}
public componentDidUpdate(prevProps: Readonly<DropdownProps>) {
public componentDidUpdate(prevProps: Readonly<DropdownProps>): void {
if (objectHasDiff(this.props, prevProps) && this.props.children?.length) {
this.reindexChildren(this.props.children);
const firstChild = this.props.children[0];
@ -149,7 +149,7 @@ export default class Dropdown extends React.Component<DropdownProps, IState> {
}
}
public componentWillUnmount() {
public componentWillUnmount(): void {
document.removeEventListener("click", this.onDocumentClick, false);
}
@ -160,7 +160,7 @@ export default class Dropdown extends React.Component<DropdownProps, IState> {
});
}
private onDocumentClick = (ev: MouseEvent) => {
private onDocumentClick = (ev: MouseEvent): void => {
// Close the dropdown if the user clicks anywhere that isn't
// within our root element
if (ev !== this.ignoreEvent) {
@ -170,7 +170,7 @@ export default class Dropdown extends React.Component<DropdownProps, IState> {
}
};
private onRootClick = (ev: MouseEvent) => {
private onRootClick = (ev: MouseEvent): void => {
// This captures any clicks that happen within our elements,
// such that we can then ignore them when they're seen by the
// click listener on the document handler, ie. not close the
@ -180,7 +180,7 @@ export default class Dropdown extends React.Component<DropdownProps, IState> {
this.ignoreEvent = ev;
};
private onAccessibleButtonClick = (ev: ButtonEvent) => {
private onAccessibleButtonClick = (ev: ButtonEvent): void => {
if (this.props.disabled) return;
const action = getKeyBindingsManager().getAccessibilityAction(ev as React.KeyboardEvent);
@ -199,7 +199,7 @@ export default class Dropdown extends React.Component<DropdownProps, IState> {
}
};
private close() {
private close(): void {
this.setState({
expanded: false,
});
@ -209,12 +209,12 @@ export default class Dropdown extends React.Component<DropdownProps, IState> {
}
}
private onMenuOptionClick = (dropdownKey: string) => {
private onMenuOptionClick = (dropdownKey: string): void => {
this.close();
this.props.onOptionChange(dropdownKey);
};
private onKeyDown = (e: React.KeyboardEvent) => {
private onKeyDown = (e: React.KeyboardEvent): void => {
let handled = true;
// These keys don't generate keypress events and so needs to be on keyup
@ -254,7 +254,7 @@ export default class Dropdown extends React.Component<DropdownProps, IState> {
}
};
private onInputChange = (e: ChangeEvent<HTMLInputElement>) => {
private onInputChange = (e: ChangeEvent<HTMLInputElement>): void => {
this.setState({
searchQuery: e.currentTarget.value,
});
@ -263,7 +263,7 @@ export default class Dropdown extends React.Component<DropdownProps, IState> {
}
};
private collectRoot = (e: HTMLDivElement) => {
private collectRoot = (e: HTMLDivElement): void => {
if (this.dropdownRootElement) {
this.dropdownRootElement.removeEventListener("click", this.onRootClick, false);
}
@ -273,7 +273,7 @@ export default class Dropdown extends React.Component<DropdownProps, IState> {
this.dropdownRootElement = e;
};
private setHighlightedOption = (optionKey: string) => {
private setHighlightedOption = (optionKey: string): void => {
this.setState({
highlightedOption: optionKey,
});
@ -291,7 +291,7 @@ export default class Dropdown extends React.Component<DropdownProps, IState> {
return keys[index <= 0 ? keys.length - 1 : (index - 1) % keys.length];
}
private scrollIntoView(node: Element) {
private scrollIntoView(node: Element): void {
if (node) {
node.scrollIntoView({
block: "nearest",
@ -300,7 +300,7 @@ export default class Dropdown extends React.Component<DropdownProps, IState> {
}
}
private getMenuOptions() {
private getMenuOptions(): JSX.Element[] {
const options = React.Children.map(this.props.children, (child: ReactElement) => {
const highlighted = this.state.highlightedOption === child.key;
return (
@ -327,7 +327,7 @@ export default class Dropdown extends React.Component<DropdownProps, IState> {
return options;
}
public render() {
public render(): JSX.Element {
let currentValue;
const menuStyle: CSSProperties = {};

View file

@ -35,21 +35,21 @@ export class EditableItem extends React.Component<IItemProps, IItemState> {
verifyRemove: false,
};
private onRemove = (e) => {
private onRemove = (e): void => {
e.stopPropagation();
e.preventDefault();
this.setState({ verifyRemove: true });
};
private onDontRemove = (e) => {
private onDontRemove = (e): void => {
e.stopPropagation();
e.preventDefault();
this.setState({ verifyRemove: false });
};
private onActuallyRemove = (e) => {
private onActuallyRemove = (e): void => {
e.stopPropagation();
e.preventDefault();
@ -57,7 +57,7 @@ export class EditableItem extends React.Component<IItemProps, IItemState> {
this.setState({ verifyRemove: false });
};
public render() {
public render(): JSX.Element {
if (this.state.verifyRemove) {
return (
<div className="mx_EditableItem">
@ -105,22 +105,22 @@ interface IProps {
}
export default class EditableItemList<P = {}> extends React.PureComponent<IProps & P> {
protected onItemAdded = (e) => {
protected onItemAdded = (e): void => {
e.stopPropagation();
e.preventDefault();
if (this.props.onItemAdded) this.props.onItemAdded(this.props.newItem);
};
protected onItemRemoved = (index) => {
protected onItemRemoved = (index: number): void => {
if (this.props.onItemRemoved) this.props.onItemRemoved(index);
};
protected onNewItemChanged = (e) => {
protected onNewItemChanged = (e): void => {
if (this.props.onNewItemChanged) this.props.onNewItemChanged(e.target.value);
};
protected renderNewItemField() {
protected renderNewItemField(): JSX.Element {
return (
<form
onSubmit={this.onItemAdded}
@ -148,7 +148,7 @@ export default class EditableItemList<P = {}> extends React.PureComponent<IProps
);
}
public render() {
public render(): JSX.Element {
const editableItems = this.props.items.map((item, index) => {
if (!this.props.canRemove) {
return <li key={item}>{item}</li>;

View file

@ -47,12 +47,12 @@ const EffectsOverlay: FunctionComponent<IProps> = ({ roomWidth }) => {
};
useEffect(() => {
const resize = () => {
const resize = (): void => {
if (canvasRef.current && canvasRef.current?.height !== UIStore.instance.windowHeight) {
canvasRef.current.height = UIStore.instance.windowHeight;
}
};
const onAction = (payload: { action: string }) => {
const onAction = (payload: { action: string }): void => {
const actionPrefix = "effects.";
if (payload.action.indexOf(actionPrefix) === 0) {
const effect = payload.action.slice(actionPrefix.length);

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { ErrorInfo } from "react";
import React, { ErrorInfo, ReactNode } from "react";
import { logger } from "matrix-js-sdk/src/logger";
import { _t } from "../../../languageHandler";
@ -73,7 +73,7 @@ export default class ErrorBoundary extends React.PureComponent<{}, IState> {
});
};
public render() {
public render(): ReactNode {
if (this.state.error) {
const newIssueUrl = "https://github.com/vector-im/element-web/issues/new/choose";

View file

@ -149,7 +149,7 @@ export default class EventListSummary extends React.Component<IProps> {
* more items in `users` than `this.props.summaryLength`, which is the number of names
* included before "and [n] others".
*/
private renderNameList(users: string[]) {
private renderNameList(users: string[]): string {
return formatCommaSeparatedList(users, this.props.summaryLength);
}
@ -207,7 +207,10 @@ export default class EventListSummary extends React.Component<IProps> {
* @param {string[]} transitions the array of transitions to transform.
* @returns {object[]} an array of coalesced transitions.
*/
private static coalesceRepeatedTransitions(transitions: TransitionType[]) {
private static coalesceRepeatedTransitions(transitions: TransitionType[]): {
transitionType: TransitionType;
repeats: number;
}[] {
const res: {
transitionType: TransitionType;
repeats: number;
@ -377,7 +380,7 @@ export default class EventListSummary extends React.Component<IProps> {
return res;
}
private static getTransitionSequence(events: IUserEvents[]) {
private static getTransitionSequence(events: IUserEvents[]): TransitionType[] {
return events.map(EventListSummary.getTransition);
}
@ -451,7 +454,10 @@ export default class EventListSummary extends React.Component<IProps> {
}
}
public getAggregate(userEvents: Record<string, IUserEvents[]>) {
public getAggregate(userEvents: Record<string, IUserEvents[]>): {
names: Record<string, string[]>;
indices: Record<string, number>;
} {
// A map of aggregate type to arrays of display names. Each aggregate type
// is a comma-delimited string of transitions, e.g. "joined,left,kicked".
// The array of display names is the array of users who went through that
@ -489,7 +495,7 @@ export default class EventListSummary extends React.Component<IProps> {
};
}
public render() {
public render(): JSX.Element {
const eventsToRender = this.props.events;
// Map user IDs to latest Avatar Member. ES6 Maps are ordered by when the key was created,

View file

@ -70,7 +70,7 @@ export default class EventTilePreview extends React.Component<IProps, IState> {
};
}
private fakeEvent({ message }: IState) {
private fakeEvent({ message }: IState): MatrixEvent {
// Fake it till we make it
/* eslint-disable quote-props */
const rawEvent = {
@ -111,7 +111,7 @@ export default class EventTilePreview extends React.Component<IProps, IState> {
return event;
}
public render() {
public render(): JSX.Element {
const className = classnames(this.props.className, {
mx_IRCLayout: this.props.layout == Layout.IRC,
mx_EventTilePreview_loader: !this.props.userId,

View file

@ -26,7 +26,7 @@ const VALIDATION_THROTTLE_MS = 200;
const BASE_ID = "mx_Field";
let count = 1;
function getId() {
function getId(): string {
return `${BASE_ID}_${count++}`;
}
@ -157,7 +157,7 @@ export default class Field extends React.PureComponent<PropShapes, IState> {
this.id = this.props.id || getId();
}
public focus() {
public focus(): void {
this.inputRef.current?.focus();
// programmatic does not fire onFocus handler
this.setState({
@ -165,7 +165,7 @@ export default class Field extends React.PureComponent<PropShapes, IState> {
});
}
private onFocus = (ev) => {
private onFocus = (ev): void => {
this.setState({
focused: true,
});
@ -180,7 +180,7 @@ export default class Field extends React.PureComponent<PropShapes, IState> {
}
};
private onChange = (ev) => {
private onChange = (ev): void => {
if (this.props.validateOnChange) {
this.validateOnChange();
}
@ -190,7 +190,7 @@ export default class Field extends React.PureComponent<PropShapes, IState> {
}
};
private onBlur = (ev) => {
private onBlur = (ev): void => {
this.setState({
focused: false,
});
@ -205,7 +205,7 @@ export default class Field extends React.PureComponent<PropShapes, IState> {
}
};
public async validate({ focused, allowEmpty = true }: IValidateOpts) {
public async validate({ focused, allowEmpty = true }: IValidateOpts): Promise<boolean> {
if (!this.props.onValidate) {
return;
}
@ -238,7 +238,7 @@ export default class Field extends React.PureComponent<PropShapes, IState> {
return valid;
}
public render() {
public render(): JSX.Element {
/* eslint @typescript-eslint/no-unused-vars: ["error", { "ignoreRestSiblings": true }] */
const {
element,

View file

@ -42,7 +42,7 @@ export default class IRCTimelineProfileResizer extends React.Component<IProps, I
};
}
public componentDidMount() {
public componentDidMount(): void {
this.setState(
{
IRCLayoutRoot: document.querySelector(".mx_IRCLayout"),
@ -76,11 +76,11 @@ export default class IRCTimelineProfileResizer extends React.Component<IProps, I
};
};
private updateCSSWidth(newWidth: number) {
private updateCSSWidth(newWidth: number): void {
this.state.IRCLayoutRoot.style.setProperty("--name-width", newWidth + "px");
}
private onMoueUp = () => {
private onMoueUp = (): void => {
if (this.props.roomId) {
SettingsStore.setValue(
"ircDisplayNameWidth",
@ -91,7 +91,7 @@ export default class IRCTimelineProfileResizer extends React.Component<IProps, I
}
};
public render() {
public render(): JSX.Element {
return <Draggable className="mx_ProfileResizer" dragFunc={this.dragFunc} onMouseUp={this.onMoueUp} />;
}
}

View file

@ -126,7 +126,7 @@ export default class ImageView extends React.Component<IProps, IState> {
private animatingLoading = false;
private imageIsLoaded = false;
public componentDidMount() {
public componentDidMount(): void {
// We have to use addEventListener() because the listener
// needs to be passive in order to work with Chromium
this.focusLock.current.addEventListener("wheel", this.onWheel, { passive: false });
@ -136,13 +136,13 @@ export default class ImageView extends React.Component<IProps, IState> {
this.image.current.addEventListener("load", this.imageLoaded);
}
public componentWillUnmount() {
public componentWillUnmount(): void {
this.focusLock.current.removeEventListener("wheel", this.onWheel);
window.removeEventListener("resize", this.recalculateZoom);
this.image.current.removeEventListener("load", this.imageLoaded);
}
private imageLoaded = () => {
private imageLoaded = (): void => {
// First, we calculate the zoom, so that the image has the same size as
// the thumbnail
const { thumbnailInfo } = this.props;
@ -164,11 +164,11 @@ export default class ImageView extends React.Component<IProps, IState> {
this.animatingLoading = false;
};
private recalculateZoom = () => {
private recalculateZoom = (): void => {
this.setZoomAndRotation();
};
private setZoomAndRotation = (inputRotation?: number) => {
private setZoomAndRotation = (inputRotation?: number): void => {
const image = this.image.current;
const imageWrapper = this.imageWrapper.current;
@ -210,11 +210,11 @@ export default class ImageView extends React.Component<IProps, IState> {
});
};
private zoomDelta(delta: number, anchorX?: number, anchorY?: number) {
private zoomDelta(delta: number, anchorX?: number, anchorY?: number): void {
this.zoom(this.state.zoom + delta, anchorX, anchorY);
}
private zoom(zoomLevel: number, anchorX?: number, anchorY?: number) {
private zoom(zoomLevel: number, anchorX?: number, anchorY?: number): void {
const oldZoom = this.state.zoom;
const maxZoom = this.state.maxZoom === this.state.minZoom ? 2 * this.state.maxZoom : this.state.maxZoom;
const newZoom = Math.min(zoomLevel, maxZoom);
@ -267,7 +267,7 @@ export default class ImageView extends React.Component<IProps, IState> {
}
}
private onWheel = (ev: WheelEvent) => {
private onWheel = (ev: WheelEvent): void => {
if (ev.target === this.image.current) {
ev.stopPropagation();
ev.preventDefault();
@ -278,15 +278,15 @@ export default class ImageView extends React.Component<IProps, IState> {
}
};
private onZoomInClick = () => {
private onZoomInClick = (): void => {
this.zoomDelta(ZOOM_STEP);
};
private onZoomOutClick = () => {
private onZoomOutClick = (): void => {
this.zoomDelta(-ZOOM_STEP);
};
private onKeyDown = (ev: KeyboardEvent) => {
private onKeyDown = (ev: KeyboardEvent): void => {
const action = getKeyBindingsManager().getAccessibilityAction(ev);
switch (action) {
case KeyBindingAction.Escape:
@ -297,17 +297,17 @@ export default class ImageView extends React.Component<IProps, IState> {
}
};
private onRotateCounterClockwiseClick = () => {
private onRotateCounterClockwiseClick = (): void => {
const cur = this.state.rotation;
this.setZoomAndRotation(cur - 90);
};
private onRotateClockwiseClick = () => {
private onRotateClockwiseClick = (): void => {
const cur = this.state.rotation;
this.setZoomAndRotation(cur + 90);
};
private onDownloadClick = () => {
private onDownloadClick = (): void => {
const a = document.createElement("a");
a.href = this.props.src;
a.download = this.props.name;
@ -316,19 +316,19 @@ export default class ImageView extends React.Component<IProps, IState> {
a.click();
};
private onOpenContextMenu = () => {
private onOpenContextMenu = (): void => {
this.setState({
contextMenuDisplayed: true,
});
};
private onCloseContextMenu = () => {
private onCloseContextMenu = (): void => {
this.setState({
contextMenuDisplayed: false,
});
};
private onPermalinkClicked = (ev: React.MouseEvent) => {
private onPermalinkClicked = (ev: React.MouseEvent): void => {
// This allows the permalink to be opened in a new tab/window or copied as
// matrix.to, but also for it to enable routing within Element when clicked.
ev.preventDefault();
@ -342,7 +342,7 @@ export default class ImageView extends React.Component<IProps, IState> {
this.props.onFinished();
};
private onStartMoving = (ev: React.MouseEvent) => {
private onStartMoving = (ev: React.MouseEvent): void => {
ev.stopPropagation();
ev.preventDefault();
@ -368,7 +368,7 @@ export default class ImageView extends React.Component<IProps, IState> {
this.initY = ev.pageY - this.state.translationY;
};
private onMoving = (ev: React.MouseEvent) => {
private onMoving = (ev: React.MouseEvent): void => {
ev.stopPropagation();
ev.preventDefault();
@ -380,7 +380,7 @@ export default class ImageView extends React.Component<IProps, IState> {
});
};
private onEndMoving = () => {
private onEndMoving = (): void => {
// Zoom out if we haven't moved much
if (
this.state.moving === true &&
@ -394,7 +394,7 @@ export default class ImageView extends React.Component<IProps, IState> {
this.setState({ moving: false });
};
private renderContextMenu() {
private renderContextMenu(): JSX.Element {
let contextMenu = null;
if (this.state.contextMenuDisplayed) {
contextMenu = (
@ -411,7 +411,7 @@ export default class ImageView extends React.Component<IProps, IState> {
return <React.Fragment>{contextMenu}</React.Fragment>;
}
public render() {
public render(): JSX.Element {
const showEventMeta = !!this.props.mxEvent;
let transitionClassName;

View file

@ -39,7 +39,7 @@ export default class InfoTooltip extends React.PureComponent<ITooltipProps> {
super(props);
}
public render() {
public render(): JSX.Element {
const { tooltip, children, tooltipClassName, className, kind } = this.props;
const title = _t("Information");
const iconClassName =

View file

@ -30,7 +30,7 @@ export default class InlineSpinner extends React.PureComponent<IProps> {
h: 16,
};
public render() {
public render(): JSX.Element {
return (
<div className="mx_InlineSpinner">
<div

View file

@ -317,7 +317,7 @@ export default class InteractiveTooltip extends React.Component<IProps, IState>
};
}
public componentDidUpdate() {
public componentDidUpdate(): void {
// Whenever this passthrough component updates, also render the tooltip
// in a separate DOM tree. This allows the tooltip content to participate
// the normal React rendering cycle: when this component re-renders, the
@ -327,7 +327,7 @@ export default class InteractiveTooltip extends React.Component<IProps, IState>
this.renderTooltip();
}
public componentWillUnmount() {
public componentWillUnmount(): void {
document.removeEventListener("mousemove", this.onMouseMove);
}
@ -340,7 +340,7 @@ export default class InteractiveTooltip extends React.Component<IProps, IState>
});
};
private collectTarget = (element: HTMLElement) => {
private collectTarget = (element: HTMLElement): void => {
this.target = element;
};
@ -376,7 +376,7 @@ export default class InteractiveTooltip extends React.Component<IProps, IState>
return this.props.direction === Direction.Left || this.props.direction === Direction.Right;
}
private onMouseMove = (ev: MouseEvent) => {
private onMouseMove = (ev: MouseEvent): void => {
const { clientX: x, clientY: y } = ev;
const { contentRect } = this.state;
const targetRect = this.target.getBoundingClientRect();
@ -408,7 +408,7 @@ export default class InteractiveTooltip extends React.Component<IProps, IState>
document.addEventListener("mousemove", this.onMouseMove);
}
public hideTooltip() {
public hideTooltip(): void {
this.setState({
visible: false,
});
@ -416,7 +416,7 @@ export default class InteractiveTooltip extends React.Component<IProps, IState>
document.removeEventListener("mousemove", this.onMouseMove);
}
private renderTooltip() {
private renderTooltip(): JSX.Element {
const { contentRect, visible } = this.state;
if (!visible) {
ReactDOM.unmountComponentAtNode(getOrCreateContainer());
@ -486,7 +486,7 @@ export default class InteractiveTooltip extends React.Component<IProps, IState>
ReactDOM.render(tooltip, getOrCreateContainer());
}
public render() {
public render(): ReactNode {
return this.props.children({
ref: this.collectTarget,
onMouseOver: this.onTargetMouseOver,

View file

@ -39,13 +39,13 @@ export default class InviteReason extends React.PureComponent<IProps, IState> {
};
}
public onViewClick = () => {
public onViewClick = (): void => {
this.setState({
hidden: false,
});
};
public render() {
public render(): JSX.Element {
const classes = classNames({
mx_InviteReason: true,
mx_InviteReason_hidden: this.state.hidden,

View file

@ -29,7 +29,7 @@ interface IProps {
onChange(value: JoinRule): void;
}
const JoinRuleDropdown = ({
const JoinRuleDropdown: React.FC<IProps> = ({
label,
labelInvite,
labelPublic,
@ -37,7 +37,7 @@ const JoinRuleDropdown = ({
value,
width = 448,
onChange,
}: IProps) => {
}) => {
const options = [
<div key={JoinRule.Invite} className="mx_JoinRuleDropdown_invite">
{labelInvite}

View file

@ -41,7 +41,7 @@ interface IProps {
}
export default class LabelledToggleSwitch extends React.PureComponent<IProps> {
public render() {
public render(): JSX.Element {
// This is a minimal version of a SettingsFlag
const { label, caption } = this.props;
let firstPart = (

View file

@ -23,7 +23,9 @@ import { _t } from "../../../languageHandler";
import Spinner from "./Spinner";
import Dropdown from "./Dropdown";
function languageMatchesSearchQuery(query, language) {
type Languages = Awaited<ReturnType<typeof languageHandler.getAllLanguagesFromJson>>;
function languageMatchesSearchQuery(query: string, language: Languages[0]): boolean {
if (language.label.toUpperCase().includes(query.toUpperCase())) return true;
if (language.value.toUpperCase() === query.toUpperCase()) return true;
return false;
@ -38,7 +40,7 @@ interface IProps {
interface IState {
searchQuery: string;
langs: Awaited<ReturnType<typeof languageHandler.getAllLanguagesFromJson>>;
langs: Languages;
}
export default class LanguageDropdown extends React.Component<IProps, IState> {

View file

@ -27,7 +27,7 @@ export interface LearnMoreProps extends IAccessibleButtonProps {
}
const LearnMore: React.FC<LearnMoreProps> = ({ title, description, ...rest }) => {
const onClick = () => {
const onClick = (): void => {
Modal.createDialog(InfoDialog, {
title,
description,

View file

@ -38,11 +38,11 @@ export default class Measured extends React.PureComponent<IProps> {
this.instanceId = Measured.instanceCount++;
}
public componentDidMount() {
public componentDidMount(): void {
UIStore.instance.on(`Measured${this.instanceId}`, this.onResize);
}
public componentDidUpdate(prevProps: Readonly<IProps>) {
public componentDidUpdate(prevProps: Readonly<IProps>): void {
const previous = prevProps.sensor;
const current = this.props.sensor;
if (previous === current) return;
@ -54,17 +54,17 @@ export default class Measured extends React.PureComponent<IProps> {
}
}
public componentWillUnmount() {
public componentWillUnmount(): void {
UIStore.instance.off(`Measured${this.instanceId}`, this.onResize);
UIStore.instance.stopTrackingElementDimensions(`Measured${this.instanceId}`);
}
private onResize = (type: UI_EVENTS, entry: ResizeObserverEntry) => {
private onResize = (type: UI_EVENTS, entry: ResizeObserverEntry): void => {
if (type !== UI_EVENTS.Resize) return;
this.props.onMeasurement(entry.contentRect.width <= this.props.breakpoint);
};
public render() {
public render(): JSX.Element {
return null;
}
}

View file

@ -77,7 +77,7 @@ const MiniAvatarUploader: React.FC<IProps> = ({
chromeFileInputFix(ev);
onClick?.(ev);
}}
onChange={async (ev) => {
onChange={async (ev): Promise<void> => {
if (!ev.target.files?.length) return;
setBusy(true);
const file = ev.target.files[0];

View file

@ -23,7 +23,7 @@ import MatrixClientContext from "../../../contexts/MatrixClientContext";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
import { ActionPayload } from "../../../dispatcher/payloads";
export const getPersistKey = (appId: string) => "widget_" + appId;
export const getPersistKey = (appId: string): string => "widget_" + appId;
// Shamelessly ripped off Modal.js. There's probably a better way
// of doing reusable widgets like dialog boxes & menus where we go and
@ -106,7 +106,7 @@ export default class PersistedElement extends React.Component<IProps> {
}
}
public static isMounted(persistKey) {
public static isMounted(persistKey: string): boolean {
return Boolean(getContainer("mx_persistedElement_" + persistKey));
}

View file

@ -158,7 +158,7 @@ export default class Pill extends React.Component<IProps, IState> {
this.load();
}
public componentDidUpdate(prevProps: Readonly<IProps>) {
public componentDidUpdate(prevProps: Readonly<IProps>): void {
if (objectHasDiff(this.props, prevProps)) {
this.load();
}

View file

@ -99,7 +99,7 @@ export default class PollCreateDialog extends ScrollableBaseModal<IProps, IState
this.state = props.editingMxEvent ? editingInitialState(props.editingMxEvent) : creatingInitialState();
}
private checkCanSubmit() {
private checkCanSubmit(): void {
this.setState({
canSubmit:
!this.state.busy &&
@ -108,23 +108,23 @@ export default class PollCreateDialog extends ScrollableBaseModal<IProps, IState
});
}
private onQuestionChange = (e: ChangeEvent<HTMLInputElement>) => {
private onQuestionChange = (e: ChangeEvent<HTMLInputElement>): void => {
this.setState({ question: e.target.value }, () => this.checkCanSubmit());
};
private onOptionChange = (i: number, e: ChangeEvent<HTMLInputElement>) => {
private onOptionChange = (i: number, e: ChangeEvent<HTMLInputElement>): void => {
const newOptions = arrayFastClone(this.state.options);
newOptions[i] = e.target.value;
this.setState({ options: newOptions }, () => this.checkCanSubmit());
};
private onOptionRemove = (i: number) => {
private onOptionRemove = (i: number): void => {
const newOptions = arrayFastClone(this.state.options);
newOptions.splice(i, 1);
this.setState({ options: newOptions }, () => this.checkCanSubmit());
};
private onOptionAdd = () => {
private onOptionAdd = (): void => {
const newOptions = arrayFastClone(this.state.options);
newOptions.push("");
this.setState({ options: newOptions, autoFocusTarget: FocusTarget.NewOption }, () => {
@ -256,7 +256,7 @@ export default class PollCreateDialog extends ScrollableBaseModal<IProps, IState
);
}
public onPollTypeChange = (e: ChangeEvent<HTMLSelectElement>) => {
public onPollTypeChange = (e: ChangeEvent<HTMLSelectElement>): void => {
this.setState({
kind: M_POLL_KIND_DISCLOSED.matches(e.target.value) ? M_POLL_KIND_DISCLOSED : M_POLL_KIND_UNDISCLOSED,
});

View file

@ -73,11 +73,11 @@ export default class PowerSelector extends React.Component<IProps, IState> {
};
}
public componentDidMount() {
public componentDidMount(): void {
this.initStateFromProps();
}
public componentDidUpdate(prevProps: Readonly<IProps>) {
public componentDidUpdate(prevProps: Readonly<IProps>): void {
if (objectHasDiff(this.props, prevProps)) {
this.initStateFromProps();
}

View file

@ -98,21 +98,21 @@ export default class ReplyChain extends React.Component<IProps, IState> {
return MatrixClientPeg.get();
}
public componentDidMount() {
public componentDidMount(): void {
this.initialize();
this.trySetExpandableQuotes();
}
public componentDidUpdate() {
public componentDidUpdate(): void {
this.props.onHeightChanged();
this.trySetExpandableQuotes();
}
public componentWillUnmount() {
public componentWillUnmount(): void {
this.unmounted = true;
}
private trySetExpandableQuotes() {
private trySetExpandableQuotes(): void {
if (this.props.isQuoteExpanded === undefined && this.blockquoteRef.current) {
const el: HTMLElement | null = this.blockquoteRef.current.querySelector(".mx_EventTile_body");
if (el) {
@ -199,7 +199,7 @@ export default class ReplyChain extends React.Component<IProps, IState> {
return getUserNameColorClass(ev.getSender()).replace("Username", "ReplyChain");
}
public render() {
public render(): JSX.Element {
let header = null;
if (this.state.err) {
header = (

View file

@ -17,7 +17,7 @@ limitations under the License.
import React, { createRef, KeyboardEventHandler } from "react";
import { _t } from "../../../languageHandler";
import withValidation from "./Validation";
import withValidation, { IFieldState, IValidationResult } from "./Validation";
import Field, { IValidateOpts } from "./Field";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
@ -60,7 +60,12 @@ export default class RoomAliasField extends React.PureComponent<IProps, IState>
return hashAlias;
}
private get domainProps() {
private get domainProps(): {
prefix: JSX.Element;
postfix: JSX.Element;
value: string;
maxlength: number;
} {
const { domain } = this.props;
const prefix = <span>#</span>;
const postfix = domain ? <span title={`:${domain}`}>{`:${domain}`}</span> : <span />;
@ -72,7 +77,7 @@ export default class RoomAliasField extends React.PureComponent<IProps, IState>
return { prefix, postfix, value, maxlength };
}
public render() {
public render(): JSX.Element {
const { prefix, postfix, value, maxlength } = this.domainProps;
return (
<Field
@ -93,13 +98,11 @@ export default class RoomAliasField extends React.PureComponent<IProps, IState>
);
}
private onChange = (ev) => {
if (this.props.onChange) {
this.props.onChange(this.asFullAlias(ev.target.value));
}
private onChange = (ev: React.ChangeEvent<HTMLInputElement>): void => {
this.props.onChange?.(this.asFullAlias(ev.target.value));
};
private onValidate = async (fieldState) => {
private onValidate = async (fieldState: IFieldState): Promise<IValidationResult> => {
const result = await this.validationRules(fieldState);
this.setState({ isValid: result.valid });
return result;
@ -109,7 +112,7 @@ export default class RoomAliasField extends React.PureComponent<IProps, IState>
rules: [
{
key: "hasDomain",
test: async ({ value }) => {
test: async ({ value }): Promise<boolean> => {
// Ignore if we have passed domain
if (!value || this.props.domain) {
return true;
@ -124,7 +127,7 @@ export default class RoomAliasField extends React.PureComponent<IProps, IState>
},
{
key: "hasLocalpart",
test: async ({ value }) => {
test: async ({ value }): Promise<boolean> => {
if (!value || this.props.domain) {
return true;
}
@ -144,7 +147,7 @@ export default class RoomAliasField extends React.PureComponent<IProps, IState>
},
{
key: "safeLocalpart",
test: async ({ value }) => {
test: async ({ value }): Promise<boolean> => {
if (!value) {
return true;
}
@ -174,7 +177,7 @@ export default class RoomAliasField extends React.PureComponent<IProps, IState>
? {
key: "matches",
final: true,
test: async ({ value }) => {
test: async ({ value }): Promise<boolean> => {
if (!value) {
return true;
}
@ -192,7 +195,7 @@ export default class RoomAliasField extends React.PureComponent<IProps, IState>
: {
key: "taken",
final: true,
test: async ({ value }) => {
test: async ({ value }): Promise<boolean> => {
if (!value) {
return true;
}
@ -218,15 +221,15 @@ export default class RoomAliasField extends React.PureComponent<IProps, IState>
],
});
public get isValid() {
public get isValid(): boolean {
return this.state.isValid;
}
public validate(options: IValidateOpts) {
public validate(options: IValidateOpts): Promise<boolean> {
return this.fieldRef.current?.validate(options);
}
public focus() {
public focus(): void {
this.fieldRef.current?.focus();
}
}

View file

@ -27,7 +27,7 @@ import MatrixClientContext from "../../../contexts/MatrixClientContext";
const DEFAULT_NUM_FACES = 5;
const isKnownMember = (member: RoomMember) => !!DMRoomMap.shared().getDMRoomsForUserId(member.userId)?.length;
const isKnownMember = (member: RoomMember): boolean => !!DMRoomMap.shared().getDMRoomsForUserId(member.userId)?.length;
interface IProps extends HTMLAttributes<HTMLSpanElement> {
room: Room;

View file

@ -37,7 +37,7 @@ interface IProps extends React.HTMLProps<HTMLDivElement> {
room?: Room;
}
export default function RoomTopic({ room, ...props }: IProps) {
export default function RoomTopic({ room, ...props }: IProps): JSX.Element {
const client = useContext(MatrixClientContext);
const ref = useRef<HTMLDivElement>();

View file

@ -33,7 +33,7 @@ interface ISSOButtonProps extends Omit<IProps, "flow"> {
mini?: boolean;
}
const getIcon = (brand: IdentityProviderBrand | string) => {
const getIcon = (brand: IdentityProviderBrand | string): string | null => {
switch (brand) {
case IdentityProviderBrand.Apple:
return require(`../../../../res/img/element-icons/brands/apple.svg`).default;
@ -83,7 +83,7 @@ const SSOButton: React.FC<ISSOButtonProps> = ({
}) => {
const label = idp ? _t("Continue with %(provider)s", { provider: idp.name }) : _t("Sign in with single sign-on");
const onClick = () => {
const onClick = (): void => {
const authenticationType = getAuthenticationType(idp?.brand ?? "");
PosthogAnalytics.instance.setAuthenticationType(authenticationType);
PlatformPeg.get().startSingleSignOn(matrixClient, loginType, fragmentAfterLogin, idp?.id);

View file

@ -35,7 +35,7 @@ interface IProps {
kind: WarningKind;
}
export default function SearchWarning({ isRoomEncrypted, kind }: IProps) {
export default function SearchWarning({ isRoomEncrypted, kind }: IProps): JSX.Element {
if (!isRoomEncrypted) return null;
if (EventIndexPeg.get()) return null;

View file

@ -36,11 +36,11 @@ const showPickerDialog = (
title: string,
serverConfig: ValidatedServerConfig,
onFinished: (config: ValidatedServerConfig) => void,
) => {
): void => {
Modal.createDialog(ServerPickerDialog, { title, serverConfig, onFinished });
};
const onHelpClick = () => {
const onHelpClick = (): void => {
const brand = SdkConfig.get().brand;
Modal.createDialog(
InfoDialog,
@ -60,12 +60,12 @@ const onHelpClick = () => {
);
};
const ServerPicker = ({ title, dialogTitle, serverConfig, onServerConfigChange }: IProps) => {
const ServerPicker: React.FC<IProps> = ({ title, dialogTitle, serverConfig, onServerConfigChange }) => {
const disableCustomUrls = SdkConfig.get("disable_custom_urls");
let editBtn;
if (!disableCustomUrls && onServerConfigChange) {
const onClick = () => {
const onClick = (): void => {
showPickerDialog(dialogTitle, serverConfig, (config?: ValidatedServerConfig) => {
if (config) {
onServerConfigChange(config);

View file

@ -56,17 +56,17 @@ export default class SettingsFlag extends React.Component<IProps, IState> {
};
}
private onChange = async (checked: boolean) => {
private onChange = async (checked: boolean): Promise<void> => {
await this.save(checked);
this.setState({ value: checked });
if (this.props.onChange) this.props.onChange(checked);
};
private checkBoxOnChange = (e: React.ChangeEvent<HTMLInputElement>) => {
private checkBoxOnChange = (e: React.ChangeEvent<HTMLInputElement>): void => {
this.onChange(e.target.checked);
};
private save = async (val?: boolean) => {
private save = async (val?: boolean): Promise<void> => {
await SettingsStore.setValue(
this.props.name,
this.props.roomId,
@ -75,7 +75,7 @@ export default class SettingsFlag extends React.Component<IProps, IState> {
);
};
public render() {
public render(): JSX.Element {
const canChange = SettingsStore.canSetValue(this.props.name, this.props.roomId, this.props.level);
if (!canChange && this.props.hideIfCannotSet) return null;

View file

@ -108,7 +108,7 @@ export default class Slider extends React.Component<IProps> {
);
}
public onClick(event: React.MouseEvent) {
public onClick(event: React.MouseEvent): void {
const width = (event.target as HTMLElement).clientWidth;
// nativeEvent is safe to use because https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/offsetX
// is supported by all modern browsers

View file

@ -21,8 +21,10 @@ import PlatformPeg from "../../../PlatformPeg";
import SettingsStore from "../../../settings/SettingsStore";
import { _t } from "../../../languageHandler";
import Spinner from "./Spinner";
import * as languageHandler from "../../../languageHandler";
function languageMatchesSearchQuery(query, language) {
type Languages = Awaited<ReturnType<typeof languageHandler.getAllLanguagesFromJson>>;
function languageMatchesSearchQuery(query: string, language: Languages[0]): boolean {
if (language.label.toUpperCase().includes(query.toUpperCase())) return true;
if (language.value.toUpperCase() === query.toUpperCase()) return true;
return false;
@ -36,7 +38,7 @@ interface SpellCheckLanguagesDropdownIProps {
interface SpellCheckLanguagesDropdownIState {
searchQuery: string;
languages: any;
languages: Languages;
}
export default class SpellCheckLanguagesDropdown extends React.Component<
@ -53,7 +55,7 @@ export default class SpellCheckLanguagesDropdown extends React.Component<
};
}
public componentDidMount() {
public componentDidMount(): void {
const plaf = PlatformPeg.get();
if (plaf) {
plaf.getAvailableSpellCheckLanguages()
@ -63,7 +65,7 @@ export default class SpellCheckLanguagesDropdown extends React.Component<
if (a > b) return 1;
return 0;
});
const langs = [];
const langs: Languages = [];
languages.forEach((language) => {
langs.push({
label: language,
@ -73,16 +75,23 @@ export default class SpellCheckLanguagesDropdown extends React.Component<
this.setState({ languages: langs });
})
.catch((e) => {
this.setState({ languages: ["en"] });
this.setState({
languages: [
{
value: "en",
label: "English",
},
],
});
});
}
}
private onSearchChange(searchQuery: string) {
private onSearchChange(searchQuery: string): void {
this.setState({ searchQuery });
}
public render() {
public render(): JSX.Element {
if (this.state.languages === null) {
return <Spinner />;
}

View file

@ -30,7 +30,7 @@ export default class Spinner extends React.PureComponent<IProps> {
h: 32,
};
public render() {
public render(): JSX.Element {
const { w, h, message } = this.props;
return (
<div className="mx_Spinner">

View file

@ -44,7 +44,7 @@ export default class StyledCheckbox extends React.PureComponent<IProps, IState>
this.id = this.props.id || "checkbox_" + randomString(10);
}
public render() {
public render(): JSX.Element {
/* eslint @typescript-eslint/no-unused-vars: ["error", { "ignoreRestSiblings": true }] */
const { children, className, kind = CheckboxStyle.Solid, inputRef, ...otherProps } = this.props;

View file

@ -34,7 +34,7 @@ export default class StyledRadioButton extends React.PureComponent<IProps, IStat
childrenInLabel: true,
};
public render() {
public render(): JSX.Element {
const { children, className, disabled, outlined, childrenInLabel, inputRef, ...otherProps } = this.props;
const _className = classnames("mx_StyledRadioButton", className, {
mx_StyledRadioButton_disabled: disabled,

View file

@ -46,8 +46,8 @@ function StyledRadioGroup<T extends string>({
outlined,
disabled,
onChange,
}: IProps<T>) {
const _onChange = (e) => {
}: IProps<T>): JSX.Element {
const _onChange = (e): void => {
onChange(e.target.value);
};

View file

@ -26,7 +26,7 @@ interface IProps {
disabled?: boolean;
}
export const Tag = ({ icon, label, onDeleteClick, disabled = false }: IProps) => {
export const Tag: React.FC<IProps> = ({ icon, label, onDeleteClick, disabled = false }) => {
return (
<div className="mx_Tag">
{icon?.()}

View file

@ -47,11 +47,11 @@ export default class TagComposer extends React.PureComponent<IProps, IState> {
};
}
private onInputChange = (ev: ChangeEvent<HTMLInputElement>) => {
private onInputChange = (ev: ChangeEvent<HTMLInputElement>): void => {
this.setState({ newTag: ev.target.value });
};
private onAdd = (ev: FormEvent) => {
private onAdd = (ev: FormEvent): void => {
ev.preventDefault();
if (!this.state.newTag) return;
@ -59,13 +59,13 @@ export default class TagComposer extends React.PureComponent<IProps, IState> {
this.setState({ newTag: "" });
};
private onRemove(tag: string) {
private onRemove(tag: string): void {
// We probably don't need to proxy this, but for
// sanity of `this` we'll do so anyways.
this.props.onRemove(tag);
}
public render() {
public render(): JSX.Element {
return (
<div className="mx_TagComposer">
<form className="mx_TagComposer_input" onSubmit={this.onAdd}>

View file

@ -38,8 +38,8 @@ interface IProps {
}
// Controlled Toggle Switch element, written with Accessibility in mind
export default ({ checked, disabled = false, title, tooltip, onChange, ...props }: IProps) => {
const _onClick = () => {
export default ({ checked, disabled = false, title, tooltip, onChange, ...props }: IProps): JSX.Element => {
const _onClick = (): void => {
if (disabled) return;
onChange(!checked);
};

View file

@ -81,7 +81,7 @@ export default class Tooltip extends React.PureComponent<ITooltipProps, State> {
}
}
public componentDidMount() {
public componentDidMount(): void {
window.addEventListener("scroll", this.updatePosition, {
passive: true,
capture: true,
@ -92,14 +92,14 @@ export default class Tooltip extends React.PureComponent<ITooltipProps, State> {
this.updatePosition();
}
public componentDidUpdate(prevProps) {
public componentDidUpdate(prevProps): void {
if (objectHasDiff(prevProps, this.props)) {
this.updatePosition();
}
}
// Remove the wrapper element, as the tooltip has finished using it
public componentWillUnmount() {
public componentWillUnmount(): void {
window.removeEventListener("scroll", this.updatePosition, {
capture: true,
});
@ -174,7 +174,7 @@ export default class Tooltip extends React.PureComponent<ITooltipProps, State> {
this.setState(style);
};
public render() {
public render(): JSX.Element {
const tooltipClasses = classNames("mx_Tooltip", this.props.tooltipClassName, {
mx_Tooltip_visible: this.props.visible,
mx_Tooltip_invisible: !this.props.visible,

View file

@ -28,7 +28,7 @@ export default class TooltipButton extends React.Component<IProps> {
super(props);
}
public render() {
public render(): JSX.Element {
return (
<TooltipTarget
className="mx_TooltipButton_container"

View file

@ -70,7 +70,7 @@ export default class TruncatedList extends React.Component<IProps> {
}
}
public render() {
public render(): JSX.Element {
let overflowNode = null;
const totalChildren = this.getChildCount();

View file

@ -29,7 +29,7 @@ interface Props {
const TIMEOUT = 1500;
export function UseCaseSelection({ onFinished }: Props) {
export function UseCaseSelection({ onFinished }: Props): JSX.Element {
const [selection, setSelected] = useState<UseCase | null>(null);
// Call onFinished 1.5s after `selection` becomes truthy, to give time for the animation to run

View file

@ -27,7 +27,7 @@ interface Props {
onClick: (useCase: UseCase) => void;
}
export function UseCaseSelectionButton({ useCase, onClick, selected }: Props) {
export function UseCaseSelectionButton({ useCase, onClick, selected }: Props): JSX.Element {
let label: string;
switch (useCase) {
case UseCase.PersonalMessaging: