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:
parent
7a36ba0fde
commit
030b7e90bf
683 changed files with 3459 additions and 3013 deletions
|
@ -22,7 +22,7 @@ type DynamicHtmlElementProps<T extends keyof JSX.IntrinsicElements> =
|
|||
JSX.IntrinsicElements[T] extends HTMLAttributes<{}> ? DynamicElementProps<T> : DynamicElementProps<"div">;
|
||||
type DynamicElementProps<T extends keyof JSX.IntrinsicElements> = Partial<Omit<JSX.IntrinsicElements[T], "ref">>;
|
||||
|
||||
export type IProps<T extends keyof JSX.IntrinsicElements> = DynamicHtmlElementProps<T> & {
|
||||
export type IProps<T extends keyof JSX.IntrinsicElements> = Omit<DynamicHtmlElementProps<T>, "onScroll"> & {
|
||||
element?: T;
|
||||
className?: string;
|
||||
onScroll?: (event: Event) => void;
|
||||
|
@ -39,7 +39,7 @@ export default class AutoHideScrollbar<T extends keyof JSX.IntrinsicElements> ex
|
|||
|
||||
public readonly containerRef: React.RefObject<HTMLDivElement> = React.createRef();
|
||||
|
||||
public componentDidMount() {
|
||||
public componentDidMount(): void {
|
||||
if (this.containerRef.current && this.props.onScroll) {
|
||||
// Using the passive option to not block the main thread
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#improving_scrolling_performance_with_passive_listeners
|
||||
|
@ -49,13 +49,13 @@ export default class AutoHideScrollbar<T extends keyof JSX.IntrinsicElements> ex
|
|||
this.props.wrappedRef?.(this.containerRef.current);
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
public componentWillUnmount(): void {
|
||||
if (this.containerRef.current && this.props.onScroll) {
|
||||
this.containerRef.current.removeEventListener("scroll", this.props.onScroll);
|
||||
}
|
||||
}
|
||||
|
||||
public render() {
|
||||
public render(): JSX.Element {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const { element, className, onScroll, tabIndex, wrappedRef, children, ...otherProps } = this.props;
|
||||
|
||||
|
|
|
@ -52,11 +52,11 @@ export const AutocompleteInput: React.FC<AutocompleteInputProps> = ({
|
|||
const editorContainerRef = useRef<HTMLDivElement>(null);
|
||||
const editorRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const focusEditor = () => {
|
||||
const focusEditor = (): void => {
|
||||
editorRef?.current?.focus();
|
||||
};
|
||||
|
||||
const onQueryChange = async (e: ChangeEvent<HTMLInputElement>) => {
|
||||
const onQueryChange = async (e: ChangeEvent<HTMLInputElement>): Promise<void> => {
|
||||
const value = e.target.value.trim();
|
||||
setQuery(value);
|
||||
|
||||
|
@ -74,11 +74,11 @@ export const AutocompleteInput: React.FC<AutocompleteInputProps> = ({
|
|||
setSuggestions(matches);
|
||||
};
|
||||
|
||||
const onClickInputArea = () => {
|
||||
const onClickInputArea = (): void => {
|
||||
focusEditor();
|
||||
};
|
||||
|
||||
const onKeyDown = (e: KeyboardEvent) => {
|
||||
const onKeyDown = (e: KeyboardEvent): void => {
|
||||
const hasModifiers = e.ctrlKey || e.shiftKey || e.metaKey;
|
||||
|
||||
// when the field is empty and the user hits backspace remove the right-most target
|
||||
|
@ -87,7 +87,7 @@ export const AutocompleteInput: React.FC<AutocompleteInputProps> = ({
|
|||
}
|
||||
};
|
||||
|
||||
const toggleSelection = (completion: ICompletion) => {
|
||||
const toggleSelection = (completion: ICompletion): void => {
|
||||
const newSelection = [...selection];
|
||||
const index = selection.findIndex((selection) => selection.completionId === completion.completionId);
|
||||
|
||||
|
@ -101,7 +101,7 @@ export const AutocompleteInput: React.FC<AutocompleteInputProps> = ({
|
|||
focusEditor();
|
||||
};
|
||||
|
||||
const removeSelection = (completion: ICompletion) => {
|
||||
const removeSelection = (completion: ICompletion): void => {
|
||||
const newSelection = [...selection];
|
||||
const index = selection.findIndex((selection) => selection.completionId === completion.completionId);
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ export enum ChevronFace {
|
|||
None = "none",
|
||||
}
|
||||
|
||||
export interface IProps extends IPosition {
|
||||
export interface MenuProps extends IPosition {
|
||||
menuWidth?: number;
|
||||
menuHeight?: number;
|
||||
|
||||
|
@ -77,7 +77,9 @@ export interface IProps extends IPosition {
|
|||
menuPaddingRight?: number;
|
||||
|
||||
zIndex?: number;
|
||||
}
|
||||
|
||||
export interface IProps extends MenuProps {
|
||||
// If true, insert an invisible screen-sized element behind the menu that when clicked will close it.
|
||||
hasBackground?: boolean;
|
||||
// whether this context menu should be focus managed. If false it must handle itself
|
||||
|
@ -128,21 +130,21 @@ export default class ContextMenu extends React.PureComponent<IProps, IState> {
|
|||
this.initialFocus = document.activeElement as HTMLElement;
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
public componentDidMount(): void {
|
||||
Modal.on(ModalManagerEvent.Opened, this.onModalOpen);
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
public componentWillUnmount(): void {
|
||||
Modal.off(ModalManagerEvent.Opened, this.onModalOpen);
|
||||
// return focus to the thing which had it before us
|
||||
this.initialFocus.focus();
|
||||
}
|
||||
|
||||
private onModalOpen = () => {
|
||||
private onModalOpen = (): void => {
|
||||
this.props.onFinished?.();
|
||||
};
|
||||
|
||||
private collectContextMenuRect = (element: HTMLDivElement) => {
|
||||
private collectContextMenuRect = (element: HTMLDivElement): void => {
|
||||
// We don't need to clean up when unmounting, so ignore
|
||||
if (!element) return;
|
||||
|
||||
|
@ -159,7 +161,7 @@ export default class ContextMenu extends React.PureComponent<IProps, IState> {
|
|||
});
|
||||
};
|
||||
|
||||
private onContextMenu = (e) => {
|
||||
private onContextMenu = (e: React.MouseEvent): void => {
|
||||
if (this.props.onFinished) {
|
||||
this.props.onFinished();
|
||||
|
||||
|
@ -184,20 +186,20 @@ export default class ContextMenu extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
};
|
||||
|
||||
private onContextMenuPreventBubbling = (e) => {
|
||||
private onContextMenuPreventBubbling = (e: React.MouseEvent): void => {
|
||||
// stop propagation so that any context menu handlers don't leak out of this context menu
|
||||
// but do not inhibit the default browser menu
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
// Prevent clicks on the background from going through to the component which opened the menu.
|
||||
private onFinished = (ev: React.MouseEvent) => {
|
||||
private onFinished = (ev: React.MouseEvent): void => {
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
this.props.onFinished?.();
|
||||
};
|
||||
|
||||
private onClick = (ev: React.MouseEvent) => {
|
||||
private onClick = (ev: React.MouseEvent): void => {
|
||||
// Don't allow clicks to escape the context menu wrapper
|
||||
ev.stopPropagation();
|
||||
|
||||
|
@ -208,7 +210,7 @@ export default class ContextMenu extends React.PureComponent<IProps, IState> {
|
|||
|
||||
// We now only handle closing the ContextMenu in this keyDown handler.
|
||||
// All of the item/option navigation is delegated to RovingTabIndex.
|
||||
private onKeyDown = (ev: React.KeyboardEvent) => {
|
||||
private onKeyDown = (ev: React.KeyboardEvent): void => {
|
||||
ev.stopPropagation(); // prevent keyboard propagating out of the context menu, we're focus-locked
|
||||
|
||||
const action = getKeyBindingsManager().getAccessibilityAction(ev);
|
||||
|
@ -243,7 +245,7 @@ export default class ContextMenu extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
};
|
||||
|
||||
protected renderMenu(hasBackground = this.props.hasBackground) {
|
||||
protected renderMenu(hasBackground = this.props.hasBackground): JSX.Element {
|
||||
const position: Partial<Writeable<DOMRect>> = {};
|
||||
const {
|
||||
top,
|
||||
|
@ -501,17 +503,13 @@ export const toLeftOrRightOf = (elementRect: DOMRect, chevronOffset = 12): ToRig
|
|||
return toRightOf(elementRect, chevronOffset);
|
||||
};
|
||||
|
||||
export type AboveLeftOf = IPosition & {
|
||||
chevronFace: ChevronFace;
|
||||
};
|
||||
|
||||
// Placement method for <ContextMenu /> to position context menu right-aligned and flowing to the left of elementRect,
|
||||
// and either above or below: wherever there is more space (maybe this should be aboveOrBelowLeftOf?)
|
||||
export const aboveLeftOf = (
|
||||
elementRect: Pick<DOMRect, "right" | "top" | "bottom">,
|
||||
chevronFace = ChevronFace.None,
|
||||
vPadding = 0,
|
||||
): AboveLeftOf => {
|
||||
): MenuProps => {
|
||||
const menuOptions: IPosition & { chevronFace: ChevronFace } = { chevronFace };
|
||||
|
||||
const buttonRight = elementRect.right + window.scrollX;
|
||||
|
@ -535,7 +533,7 @@ export const aboveRightOf = (
|
|||
elementRect: Pick<DOMRect, "left" | "top" | "bottom">,
|
||||
chevronFace = ChevronFace.None,
|
||||
vPadding = 0,
|
||||
): AboveLeftOf => {
|
||||
): MenuProps => {
|
||||
const menuOptions: IPosition & { chevronFace: ChevronFace } = { chevronFace };
|
||||
|
||||
const buttonLeft = elementRect.left + window.scrollX;
|
||||
|
@ -555,11 +553,11 @@ export const aboveRightOf = (
|
|||
|
||||
// Placement method for <ContextMenu /> to position context menu right-aligned and flowing to the left of elementRect
|
||||
// and always above elementRect
|
||||
export const alwaysAboveLeftOf = (
|
||||
export const alwaysMenuProps = (
|
||||
elementRect: Pick<DOMRect, "right" | "bottom" | "top">,
|
||||
chevronFace = ChevronFace.None,
|
||||
vPadding = 0,
|
||||
) => {
|
||||
): IPosition & { chevronFace: ChevronFace } => {
|
||||
const menuOptions: IPosition & { chevronFace: ChevronFace } = { chevronFace };
|
||||
|
||||
const buttonRight = elementRect.right + window.scrollX;
|
||||
|
@ -578,7 +576,7 @@ export const alwaysAboveRightOf = (
|
|||
elementRect: Pick<DOMRect, "left" | "top">,
|
||||
chevronFace = ChevronFace.None,
|
||||
vPadding = 0,
|
||||
) => {
|
||||
): IPosition & { chevronFace: ChevronFace } => {
|
||||
const menuOptions: IPosition & { chevronFace: ChevronFace } = { chevronFace };
|
||||
|
||||
const buttonLeft = elementRect.left + window.scrollX;
|
||||
|
@ -607,12 +605,12 @@ export const useContextMenu = <T extends any = HTMLElement>(inputRef?: RefObject
|
|||
}
|
||||
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const open = (ev?: SyntheticEvent) => {
|
||||
const open = (ev?: SyntheticEvent): void => {
|
||||
ev?.preventDefault();
|
||||
ev?.stopPropagation();
|
||||
setIsOpen(true);
|
||||
};
|
||||
const close = (ev?: SyntheticEvent) => {
|
||||
const close = (ev?: SyntheticEvent): void => {
|
||||
ev?.preventDefault();
|
||||
ev?.stopPropagation();
|
||||
setIsOpen(false);
|
||||
|
@ -622,8 +620,11 @@ export const useContextMenu = <T extends any = HTMLElement>(inputRef?: RefObject
|
|||
};
|
||||
|
||||
// XXX: Deprecated, used only for dynamic Tooltips. Avoid using at all costs.
|
||||
export function createMenu(ElementClass, props) {
|
||||
const onFinished = function (...args) {
|
||||
export function createMenu(
|
||||
ElementClass: typeof React.Component,
|
||||
props: Record<string, any>,
|
||||
): { close: (...args: any[]) => void } {
|
||||
const onFinished = function (...args): void {
|
||||
ReactDOM.unmountComponentAtNode(getOrCreateContainer());
|
||||
props?.onFinished?.apply(null, args);
|
||||
};
|
||||
|
|
|
@ -60,7 +60,7 @@ export default class EmbeddedPage extends React.PureComponent<IProps, IState> {
|
|||
return sanitizeHtml(_t(s));
|
||||
}
|
||||
|
||||
private async fetchEmbed() {
|
||||
private async fetchEmbed(): Promise<void> {
|
||||
let res: Response;
|
||||
|
||||
try {
|
||||
|
|
|
@ -37,7 +37,7 @@ const FileDropTarget: React.FC<IProps> = ({ parent, onFileDrop }) => {
|
|||
useEffect(() => {
|
||||
if (!parent || parent.ondrop) return;
|
||||
|
||||
const onDragEnter = (ev: DragEvent) => {
|
||||
const onDragEnter = (ev: DragEvent): void => {
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
|
||||
|
@ -55,7 +55,7 @@ const FileDropTarget: React.FC<IProps> = ({ parent, onFileDrop }) => {
|
|||
}));
|
||||
};
|
||||
|
||||
const onDragLeave = (ev: DragEvent) => {
|
||||
const onDragLeave = (ev: DragEvent): void => {
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
|
||||
|
@ -65,7 +65,7 @@ const FileDropTarget: React.FC<IProps> = ({ parent, onFileDrop }) => {
|
|||
}));
|
||||
};
|
||||
|
||||
const onDragOver = (ev: DragEvent) => {
|
||||
const onDragOver = (ev: DragEvent): void => {
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
|
||||
|
@ -79,7 +79,7 @@ const FileDropTarget: React.FC<IProps> = ({ parent, onFileDrop }) => {
|
|||
}
|
||||
};
|
||||
|
||||
const onDrop = (ev: DragEvent) => {
|
||||
const onDrop = (ev: DragEvent): void => {
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
onFileDrop(ev.dataTransfer);
|
||||
|
|
|
@ -223,7 +223,7 @@ class FilePanel extends React.Component<IProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
public render() {
|
||||
public render(): JSX.Element {
|
||||
if (MatrixClientPeg.get().isGuest()) {
|
||||
return (
|
||||
<BaseCard className="mx_FilePanel mx_RoomView_messageListWrapper" onClose={this.props.onClose}>
|
||||
|
|
|
@ -22,7 +22,7 @@ interface IProps {
|
|||
}
|
||||
|
||||
export default class GenericErrorPage extends React.PureComponent<IProps> {
|
||||
public render() {
|
||||
public render(): JSX.Element {
|
||||
return (
|
||||
<div className="mx_GenericErrorPage">
|
||||
<div className="mx_GenericErrorPage_box">
|
||||
|
|
|
@ -33,17 +33,17 @@ import MiniAvatarUploader, { AVATAR_SIZE } from "../views/elements/MiniAvatarUpl
|
|||
import PosthogTrackers from "../../PosthogTrackers";
|
||||
import EmbeddedPage from "./EmbeddedPage";
|
||||
|
||||
const onClickSendDm = (ev: ButtonEvent) => {
|
||||
const onClickSendDm = (ev: ButtonEvent): void => {
|
||||
PosthogTrackers.trackInteraction("WebHomeCreateChatButton", ev);
|
||||
dis.dispatch({ action: "view_create_chat" });
|
||||
};
|
||||
|
||||
const onClickExplore = (ev: ButtonEvent) => {
|
||||
const onClickExplore = (ev: ButtonEvent): void => {
|
||||
PosthogTrackers.trackInteraction("WebHomeExploreRoomsButton", ev);
|
||||
dis.fire(Action.ViewRoomDirectory);
|
||||
};
|
||||
|
||||
const onClickNewRoom = (ev: ButtonEvent) => {
|
||||
const onClickNewRoom = (ev: ButtonEvent): void => {
|
||||
PosthogTrackers.trackInteraction("WebHomeCreateRoomButton", ev);
|
||||
dis.dispatch({ action: "view_create_room" });
|
||||
};
|
||||
|
@ -52,12 +52,17 @@ interface IProps {
|
|||
justRegistered?: boolean;
|
||||
}
|
||||
|
||||
const getOwnProfile = (userId: string) => ({
|
||||
const getOwnProfile = (
|
||||
userId: string,
|
||||
): {
|
||||
displayName: string;
|
||||
avatarUrl: string;
|
||||
} => ({
|
||||
displayName: OwnProfileStore.instance.displayName || userId,
|
||||
avatarUrl: OwnProfileStore.instance.getHttpAvatarUrl(AVATAR_SIZE),
|
||||
});
|
||||
|
||||
const UserWelcomeTop = () => {
|
||||
const UserWelcomeTop: React.FC = () => {
|
||||
const cli = useContext(MatrixClientContext);
|
||||
const userId = cli.getUserId();
|
||||
const [ownProfile, setOwnProfile] = useState(getOwnProfile(userId));
|
||||
|
|
|
@ -28,7 +28,7 @@ interface IProps {
|
|||
interface IState {}
|
||||
|
||||
export default class HostSignupAction extends React.PureComponent<IProps, IState> {
|
||||
private openDialog = async () => {
|
||||
private openDialog = async (): Promise<void> => {
|
||||
this.props.onClick?.();
|
||||
await HostSignupStore.instance.setHostSignupActive(true);
|
||||
};
|
||||
|
|
|
@ -130,7 +130,7 @@ export default class InteractiveAuthComponent extends React.Component<IProps, IS
|
|||
}
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
public componentDidMount(): void {
|
||||
this.authLogic
|
||||
.attemptAuth()
|
||||
.then((result) => {
|
||||
|
@ -155,7 +155,7 @@ export default class InteractiveAuthComponent extends React.Component<IProps, IS
|
|||
});
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
public componentWillUnmount(): void {
|
||||
this.unmounted = true;
|
||||
|
||||
if (this.intervalId !== null) {
|
||||
|
@ -249,7 +249,7 @@ export default class InteractiveAuthComponent extends React.Component<IProps, IS
|
|||
this.authLogic.setEmailSid(sid);
|
||||
};
|
||||
|
||||
public render() {
|
||||
public render(): JSX.Element {
|
||||
const stage = this.state.authStage;
|
||||
if (!stage) {
|
||||
if (this.state.busy) {
|
||||
|
|
|
@ -89,7 +89,7 @@ export default class LeftPanel extends React.Component<IProps, IState> {
|
|||
return SettingsStore.getValue("feature_breadcrumbs_v2") ? BreadcrumbsMode.Labs : BreadcrumbsMode.Legacy;
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
public componentDidMount(): void {
|
||||
UIStore.instance.trackElementDimensions("ListContainer", this.listContainerRef.current);
|
||||
UIStore.instance.on("ListContainer", this.refreshStickyHeaders);
|
||||
// Using the passive option to not block the main thread
|
||||
|
@ -97,7 +97,7 @@ export default class LeftPanel extends React.Component<IProps, IState> {
|
|||
this.listContainerRef.current?.addEventListener("scroll", this.onScroll, { passive: true });
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
public componentWillUnmount(): void {
|
||||
BreadcrumbsStore.instance.off(UPDATE_EVENT, this.onBreadcrumbsUpdate);
|
||||
RoomListStore.instance.off(LISTS_UPDATE_EVENT, this.onBreadcrumbsUpdate);
|
||||
SpaceStore.instance.off(UPDATE_SELECTED_SPACE, this.updateActiveSpace);
|
||||
|
@ -112,25 +112,25 @@ export default class LeftPanel extends React.Component<IProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
private updateActiveSpace = (activeSpace: SpaceKey) => {
|
||||
private updateActiveSpace = (activeSpace: SpaceKey): void => {
|
||||
this.setState({ activeSpace });
|
||||
};
|
||||
|
||||
private onDialPad = () => {
|
||||
private onDialPad = (): void => {
|
||||
dis.fire(Action.OpenDialPad);
|
||||
};
|
||||
|
||||
private onExplore = (ev: ButtonEvent) => {
|
||||
private onExplore = (ev: ButtonEvent): void => {
|
||||
dis.fire(Action.ViewRoomDirectory);
|
||||
PosthogTrackers.trackInteraction("WebLeftPanelExploreRoomsButton", ev);
|
||||
};
|
||||
|
||||
private refreshStickyHeaders = () => {
|
||||
private refreshStickyHeaders = (): void => {
|
||||
if (!this.listContainerRef.current) return; // ignore: no headers to sticky
|
||||
this.handleStickyHeaders(this.listContainerRef.current);
|
||||
};
|
||||
|
||||
private onBreadcrumbsUpdate = () => {
|
||||
private onBreadcrumbsUpdate = (): void => {
|
||||
const newVal = LeftPanel.breadcrumbsMode;
|
||||
if (newVal !== this.state.showBreadcrumbs) {
|
||||
this.setState({ showBreadcrumbs: newVal });
|
||||
|
@ -141,7 +141,7 @@ export default class LeftPanel extends React.Component<IProps, IState> {
|
|||
}
|
||||
};
|
||||
|
||||
private handleStickyHeaders(list: HTMLDivElement) {
|
||||
private handleStickyHeaders(list: HTMLDivElement): void {
|
||||
if (this.isDoingStickyHeaders) return;
|
||||
this.isDoingStickyHeaders = true;
|
||||
window.requestAnimationFrame(() => {
|
||||
|
@ -150,7 +150,7 @@ export default class LeftPanel extends React.Component<IProps, IState> {
|
|||
});
|
||||
}
|
||||
|
||||
private doStickyHeaders(list: HTMLDivElement) {
|
||||
private doStickyHeaders(list: HTMLDivElement): void {
|
||||
const topEdge = list.scrollTop;
|
||||
const bottomEdge = list.offsetHeight + list.scrollTop;
|
||||
const sublists = list.querySelectorAll<HTMLDivElement>(".mx_RoomSublist:not(.mx_RoomSublist_hidden)");
|
||||
|
@ -282,20 +282,20 @@ export default class LeftPanel extends React.Component<IProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
private onScroll = (ev: Event) => {
|
||||
private onScroll = (ev: Event): void => {
|
||||
const list = ev.target as HTMLDivElement;
|
||||
this.handleStickyHeaders(list);
|
||||
};
|
||||
|
||||
private onFocus = (ev: React.FocusEvent) => {
|
||||
private onFocus = (ev: React.FocusEvent): void => {
|
||||
this.focusedElement = ev.target;
|
||||
};
|
||||
|
||||
private onBlur = () => {
|
||||
private onBlur = (): void => {
|
||||
this.focusedElement = null;
|
||||
};
|
||||
|
||||
private onKeyDown = (ev: React.KeyboardEvent, state?: IRovingTabIndexState) => {
|
||||
private onKeyDown = (ev: React.KeyboardEvent, state?: IRovingTabIndexState): void => {
|
||||
if (!this.focusedElement) return;
|
||||
|
||||
const action = getKeyBindingsManager().getRoomListAction(ev);
|
||||
|
|
|
@ -142,7 +142,7 @@ export default class LegacyCallEventGrouper extends EventEmitter {
|
|||
return [...this.events][0]?.getRoomId();
|
||||
}
|
||||
|
||||
private onSilencedCallsChanged = () => {
|
||||
private onSilencedCallsChanged = (): void => {
|
||||
const newState = LegacyCallHandler.instance.isCallSilenced(this.callId);
|
||||
this.emit(LegacyCallEventGrouperEvent.SilencedChanged, newState);
|
||||
};
|
||||
|
@ -163,20 +163,20 @@ export default class LegacyCallEventGrouper extends EventEmitter {
|
|||
LegacyCallHandler.instance.placeCall(this.roomId, this.isVoice ? CallType.Voice : CallType.Video);
|
||||
};
|
||||
|
||||
public toggleSilenced = () => {
|
||||
public toggleSilenced = (): void => {
|
||||
const silenced = LegacyCallHandler.instance.isCallSilenced(this.callId);
|
||||
silenced
|
||||
? LegacyCallHandler.instance.unSilenceCall(this.callId)
|
||||
: LegacyCallHandler.instance.silenceCall(this.callId);
|
||||
};
|
||||
|
||||
private setCallListeners() {
|
||||
private setCallListeners(): void {
|
||||
if (!this.call) return;
|
||||
this.call.addListener(CallEvent.State, this.setState);
|
||||
this.call.addListener(CallEvent.LengthChanged, this.onLengthChanged);
|
||||
}
|
||||
|
||||
private setState = () => {
|
||||
private setState = (): void => {
|
||||
if (CONNECTING_STATES.includes(this.call?.state)) {
|
||||
this.state = CallState.Connecting;
|
||||
} else if (SUPPORTED_STATES.includes(this.call?.state)) {
|
||||
|
@ -190,7 +190,7 @@ export default class LegacyCallEventGrouper extends EventEmitter {
|
|||
this.emit(LegacyCallEventGrouperEvent.StateChanged, this.state);
|
||||
};
|
||||
|
||||
private setCall = () => {
|
||||
private setCall = (): void => {
|
||||
if (this.call) return;
|
||||
|
||||
this.call = LegacyCallHandler.instance.getCallById(this.callId);
|
||||
|
@ -198,7 +198,7 @@ export default class LegacyCallEventGrouper extends EventEmitter {
|
|||
this.setState();
|
||||
};
|
||||
|
||||
public add(event: MatrixEvent) {
|
||||
public add(event: MatrixEvent): void {
|
||||
if (this.events.has(event)) return; // nothing to do
|
||||
this.events.add(event);
|
||||
this.setCall();
|
||||
|
|
|
@ -159,7 +159,7 @@ class LoggedInView extends React.Component<IProps, IState> {
|
|||
this.resizeHandler = React.createRef();
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
public componentDidMount(): void {
|
||||
document.addEventListener("keydown", this.onNativeKeyDown, false);
|
||||
LegacyCallHandler.instance.addListener(LegacyCallHandlerEvent.CallState, this.onCallState);
|
||||
|
||||
|
@ -191,7 +191,7 @@ class LoggedInView extends React.Component<IProps, IState> {
|
|||
this.refreshBackgroundImage();
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
public componentWillUnmount(): void {
|
||||
document.removeEventListener("keydown", this.onNativeKeyDown, false);
|
||||
LegacyCallHandler.instance.removeListener(LegacyCallHandlerEvent.CallState, this.onCallState);
|
||||
this._matrixClient.removeListener(ClientEvent.AccountData, this.onAccountData);
|
||||
|
@ -221,14 +221,14 @@ class LoggedInView extends React.Component<IProps, IState> {
|
|||
this.setState({ backgroundImage });
|
||||
};
|
||||
|
||||
public canResetTimelineInRoom = (roomId: string) => {
|
||||
public canResetTimelineInRoom = (roomId: string): boolean => {
|
||||
if (!this._roomView.current) {
|
||||
return true;
|
||||
}
|
||||
return this._roomView.current.canResetTimeline();
|
||||
};
|
||||
|
||||
private createResizer() {
|
||||
private createResizer(): Resizer {
|
||||
let panelSize;
|
||||
let panelCollapsed;
|
||||
const collapseConfig: ICollapseConfig = {
|
||||
|
@ -268,7 +268,7 @@ class LoggedInView extends React.Component<IProps, IState> {
|
|||
return resizer;
|
||||
}
|
||||
|
||||
private loadResizerPreferences() {
|
||||
private loadResizerPreferences(): void {
|
||||
let lhsSize = parseInt(window.localStorage.getItem("mx_lhs_size"), 10);
|
||||
if (isNaN(lhsSize)) {
|
||||
lhsSize = 350;
|
||||
|
@ -276,13 +276,13 @@ class LoggedInView extends React.Component<IProps, IState> {
|
|||
this.resizer.forHandleWithId("lp-resizer").resize(lhsSize);
|
||||
}
|
||||
|
||||
private onAccountData = (event: MatrixEvent) => {
|
||||
private onAccountData = (event: MatrixEvent): void => {
|
||||
if (event.getType() === "m.ignored_user_list") {
|
||||
dis.dispatch({ action: "ignore_state_changed" });
|
||||
}
|
||||
};
|
||||
|
||||
private onCompactLayoutChanged = () => {
|
||||
private onCompactLayoutChanged = (): void => {
|
||||
this.setState({
|
||||
useCompactLayout: SettingsStore.getValue("useCompactLayout"),
|
||||
});
|
||||
|
@ -311,13 +311,13 @@ class LoggedInView extends React.Component<IProps, IState> {
|
|||
}
|
||||
};
|
||||
|
||||
private onUsageLimitDismissed = () => {
|
||||
private onUsageLimitDismissed = (): void => {
|
||||
this.setState({
|
||||
usageLimitDismissed: true,
|
||||
});
|
||||
};
|
||||
|
||||
private calculateServerLimitToast(syncError: IState["syncErrorData"], usageLimitEventContent?: IUsageLimit) {
|
||||
private calculateServerLimitToast(syncError: IState["syncErrorData"], usageLimitEventContent?: IUsageLimit): void {
|
||||
const error = (syncError?.error as MatrixError)?.errcode === "M_RESOURCE_LIMIT_EXCEEDED";
|
||||
if (error) {
|
||||
usageLimitEventContent = (syncError?.error as MatrixError).data as IUsageLimit;
|
||||
|
@ -337,9 +337,9 @@ class LoggedInView extends React.Component<IProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
private updateServerNoticeEvents = async () => {
|
||||
private updateServerNoticeEvents = async (): Promise<void> => {
|
||||
const serverNoticeList = RoomListStore.instance.orderedLists[DefaultTagID.ServerNotice];
|
||||
if (!serverNoticeList) return [];
|
||||
if (!serverNoticeList) return;
|
||||
|
||||
const events = [];
|
||||
let pinnedEventTs = 0;
|
||||
|
@ -379,7 +379,7 @@ class LoggedInView extends React.Component<IProps, IState> {
|
|||
});
|
||||
};
|
||||
|
||||
private onPaste = (ev: ClipboardEvent) => {
|
||||
private onPaste = (ev: ClipboardEvent): void => {
|
||||
const element = ev.target as HTMLElement;
|
||||
const inputableElement = getInputableElement(element);
|
||||
if (inputableElement === document.activeElement) return; // nothing to do
|
||||
|
@ -422,13 +422,13 @@ class LoggedInView extends React.Component<IProps, IState> {
|
|||
We also listen with a native listener on the document to get keydown events when no element is focused.
|
||||
Bubbling is irrelevant here as the target is the body element.
|
||||
*/
|
||||
private onReactKeyDown = (ev) => {
|
||||
private onReactKeyDown = (ev): void => {
|
||||
// events caught while bubbling up on the root element
|
||||
// of this component, so something must be focused.
|
||||
this.onKeyDown(ev);
|
||||
};
|
||||
|
||||
private onNativeKeyDown = (ev) => {
|
||||
private onNativeKeyDown = (ev): void => {
|
||||
// only pass this if there is no focused element.
|
||||
// if there is, onKeyDown will be called by the
|
||||
// react keydown handler that respects the react bubbling order.
|
||||
|
@ -437,7 +437,7 @@ class LoggedInView extends React.Component<IProps, IState> {
|
|||
}
|
||||
};
|
||||
|
||||
private onKeyDown = (ev) => {
|
||||
private onKeyDown = (ev): void => {
|
||||
let handled = false;
|
||||
|
||||
const roomAction = getKeyBindingsManager().getRoomAction(ev);
|
||||
|
@ -615,13 +615,13 @@ class LoggedInView extends React.Component<IProps, IState> {
|
|||
* dispatch a page-up/page-down/etc to the appropriate component
|
||||
* @param {Object} ev The key event
|
||||
*/
|
||||
private onScrollKeyPressed = (ev) => {
|
||||
private onScrollKeyPressed = (ev): void => {
|
||||
if (this._roomView.current) {
|
||||
this._roomView.current.handleScrollKey(ev);
|
||||
}
|
||||
};
|
||||
|
||||
public render() {
|
||||
public render(): JSX.Element {
|
||||
let pageElement;
|
||||
|
||||
switch (this.props.page_type) {
|
||||
|
|
|
@ -216,7 +216,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
realQueryParams: {},
|
||||
startingFragmentQueryParams: {},
|
||||
config: {},
|
||||
onTokenLoginCompleted: () => {},
|
||||
onTokenLoginCompleted: (): void => {},
|
||||
};
|
||||
|
||||
private firstSyncComplete = false;
|
||||
|
@ -317,7 +317,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
this.props.realQueryParams,
|
||||
this.props.defaultDeviceDisplayName,
|
||||
this.getFragmentAfterLogin(),
|
||||
).then(async (loggedIn) => {
|
||||
).then(async (loggedIn): Promise<boolean | void> => {
|
||||
if (this.props.realQueryParams?.loginToken) {
|
||||
// remove the loginToken from the URL regardless
|
||||
this.props.onTokenLoginCompleted();
|
||||
|
@ -353,7 +353,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
initSentry(SdkConfig.get("sentry"));
|
||||
}
|
||||
|
||||
private async postLoginSetup() {
|
||||
private async postLoginSetup(): Promise<void> {
|
||||
const cli = MatrixClientPeg.get();
|
||||
const cryptoEnabled = cli.isCryptoEnabled();
|
||||
if (!cryptoEnabled) {
|
||||
|
@ -367,7 +367,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
// as a proxy to figure out if it's worth prompting the user to verify
|
||||
// from another device.
|
||||
promisesList.push(
|
||||
(async () => {
|
||||
(async (): Promise<void> => {
|
||||
crossSigningIsSetUp = await cli.userHasCrossSigningKeys();
|
||||
})(),
|
||||
);
|
||||
|
@ -417,7 +417,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
window.addEventListener("resize", this.onWindowResized);
|
||||
}
|
||||
|
||||
public componentDidUpdate(prevProps, prevState) {
|
||||
public componentDidUpdate(prevProps, prevState): void {
|
||||
if (this.shouldTrackPageChange(prevState, this.state)) {
|
||||
const durationMs = this.stopPageChangeTimer();
|
||||
PosthogTrackers.instance.trackPageChange(this.state.view, this.state.page_type, durationMs);
|
||||
|
@ -428,7 +428,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
public componentWillUnmount(): void {
|
||||
Lifecycle.stopMatrixClient();
|
||||
dis.unregister(this.dispatcherRef);
|
||||
this.themeWatcher.stop();
|
||||
|
@ -477,7 +477,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
private getServerProperties() {
|
||||
private getServerProperties(): { serverConfig: ValidatedServerConfig } {
|
||||
let props = this.state.serverConfig;
|
||||
if (!props) props = this.props.serverConfig; // for unit tests
|
||||
if (!props) props = SdkConfig.get("validated_server_config");
|
||||
|
@ -513,11 +513,11 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
// to try logging out.
|
||||
}
|
||||
|
||||
private startPageChangeTimer() {
|
||||
private startPageChangeTimer(): void {
|
||||
PerformanceMonitor.instance.start(PerformanceEntryNames.PAGE_CHANGE);
|
||||
}
|
||||
|
||||
private stopPageChangeTimer() {
|
||||
private stopPageChangeTimer(): number | null {
|
||||
const perfMonitor = PerformanceMonitor.instance;
|
||||
|
||||
perfMonitor.stop(PerformanceEntryNames.PAGE_CHANGE);
|
||||
|
@ -876,13 +876,13 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
};
|
||||
|
||||
private setPage(pageType: PageType) {
|
||||
private setPage(pageType: PageType): void {
|
||||
this.setState({
|
||||
page_type: pageType,
|
||||
});
|
||||
}
|
||||
|
||||
private async startRegistration(params: { [key: string]: string }) {
|
||||
private async startRegistration(params: { [key: string]: string }): Promise<void> {
|
||||
const newState: Partial<IState> = {
|
||||
view: Views.REGISTER,
|
||||
};
|
||||
|
@ -916,7 +916,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
|
||||
// switch view to the given room
|
||||
private async viewRoom(roomInfo: ViewRoomPayload) {
|
||||
private async viewRoom(roomInfo: ViewRoomPayload): Promise<void> {
|
||||
this.focusComposer = true;
|
||||
|
||||
if (roomInfo.room_alias) {
|
||||
|
@ -992,7 +992,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
);
|
||||
}
|
||||
|
||||
private viewSomethingBehindModal() {
|
||||
private viewSomethingBehindModal(): void {
|
||||
if (this.state.view !== Views.LOGGED_IN) {
|
||||
this.viewWelcome();
|
||||
return;
|
||||
|
@ -1002,7 +1002,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
private viewWelcome() {
|
||||
private viewWelcome(): void {
|
||||
if (shouldUseLoginForWelcome(SdkConfig.get())) {
|
||||
return this.viewLogin();
|
||||
}
|
||||
|
@ -1014,7 +1014,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
this.themeWatcher.recheck();
|
||||
}
|
||||
|
||||
private viewLogin(otherState?: any) {
|
||||
private viewLogin(otherState?: any): void {
|
||||
this.setStateForNewView({
|
||||
view: Views.LOGIN,
|
||||
...otherState,
|
||||
|
@ -1024,7 +1024,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
this.themeWatcher.recheck();
|
||||
}
|
||||
|
||||
private viewHome(justRegistered = false) {
|
||||
private viewHome(justRegistered = false): void {
|
||||
// The home page requires the "logged in" view, so we'll set that.
|
||||
this.setStateForNewView({
|
||||
view: Views.LOGGED_IN,
|
||||
|
@ -1037,7 +1037,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
this.themeWatcher.recheck();
|
||||
}
|
||||
|
||||
private viewUser(userId: string, subAction: string) {
|
||||
private viewUser(userId: string, subAction: string): void {
|
||||
// Wait for the first sync so that `getRoom` gives us a room object if it's
|
||||
// in the sync response
|
||||
const waitForSync = this.firstSyncPromise ? this.firstSyncPromise.promise : Promise.resolve();
|
||||
|
@ -1052,7 +1052,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
});
|
||||
}
|
||||
|
||||
private async createRoom(defaultPublic = false, defaultName?: string, type?: RoomType) {
|
||||
private async createRoom(defaultPublic = false, defaultName?: string, type?: RoomType): Promise<void> {
|
||||
const modal = Modal.createDialog(CreateRoomDialog, {
|
||||
type,
|
||||
defaultPublic,
|
||||
|
@ -1065,7 +1065,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
private chatCreateOrReuse(userId: string) {
|
||||
private chatCreateOrReuse(userId: string): void {
|
||||
const snakedConfig = new SnakedObject<IConfigOptions>(this.props.config);
|
||||
// Use a deferred action to reshow the dialog once the user has registered
|
||||
if (MatrixClientPeg.get().isGuest()) {
|
||||
|
@ -1115,11 +1115,11 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
private leaveRoomWarnings(roomId: string) {
|
||||
private leaveRoomWarnings(roomId: string): JSX.Element[] {
|
||||
const roomToLeave = MatrixClientPeg.get().getRoom(roomId);
|
||||
const isSpace = roomToLeave?.isSpaceRoom();
|
||||
// Show a warning if there are additional complications.
|
||||
const warnings = [];
|
||||
const warnings: JSX.Element[] = [];
|
||||
|
||||
const memberCount = roomToLeave.currentState.getJoinedMemberCount();
|
||||
if (memberCount === 1) {
|
||||
|
@ -1153,7 +1153,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
return warnings;
|
||||
}
|
||||
|
||||
private leaveRoom(roomId: string) {
|
||||
private leaveRoom(roomId: string): void {
|
||||
const roomToLeave = MatrixClientPeg.get().getRoom(roomId);
|
||||
const warnings = this.leaveRoomWarnings(roomId);
|
||||
|
||||
|
@ -1184,7 +1184,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
});
|
||||
}
|
||||
|
||||
private forgetRoom(roomId: string) {
|
||||
private forgetRoom(roomId: string): void {
|
||||
const room = MatrixClientPeg.get().getRoom(roomId);
|
||||
MatrixClientPeg.get()
|
||||
.forget(roomId)
|
||||
|
@ -1208,7 +1208,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
});
|
||||
}
|
||||
|
||||
private async copyRoom(roomId: string) {
|
||||
private async copyRoom(roomId: string): Promise<void> {
|
||||
const roomLink = makeRoomPermalink(roomId);
|
||||
const success = await copyPlaintext(roomLink);
|
||||
if (!success) {
|
||||
|
@ -1223,13 +1223,13 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
* Starts a chat with the welcome user, if the user doesn't already have one
|
||||
* @returns {string} The room ID of the new room, or null if no room was created
|
||||
*/
|
||||
private async startWelcomeUserChat() {
|
||||
private async startWelcomeUserChat(): Promise<string | null> {
|
||||
// We can end up with multiple tabs post-registration where the user
|
||||
// might then end up with a session and we don't want them all making
|
||||
// a chat with the welcome user: try to de-dupe.
|
||||
// We need to wait for the first sync to complete for this to
|
||||
// work though.
|
||||
let waitFor;
|
||||
let waitFor: Promise<void>;
|
||||
if (!this.firstSyncComplete) {
|
||||
waitFor = this.firstSyncPromise.promise;
|
||||
} else {
|
||||
|
@ -1254,7 +1254,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
// run without the update to m.direct, making another welcome
|
||||
// user room (it doesn't wait for new data from the server, just
|
||||
// the saved sync to be loaded).
|
||||
const saveWelcomeUser = (ev: MatrixEvent) => {
|
||||
const saveWelcomeUser = (ev: MatrixEvent): void => {
|
||||
if (ev.getType() === EventType.Direct && ev.getContent()[snakedConfig.get("welcome_user_id")]) {
|
||||
MatrixClientPeg.get().store.save(true);
|
||||
MatrixClientPeg.get().removeListener(ClientEvent.AccountData, saveWelcomeUser);
|
||||
|
@ -1270,7 +1270,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
/**
|
||||
* Called when a new logged in session has started
|
||||
*/
|
||||
private async onLoggedIn() {
|
||||
private async onLoggedIn(): Promise<void> {
|
||||
ThemeController.isLogin = false;
|
||||
this.themeWatcher.recheck();
|
||||
StorageManager.tryPersistStorage();
|
||||
|
@ -1301,7 +1301,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
private async onShowPostLoginScreen(useCase?: UseCase) {
|
||||
private async onShowPostLoginScreen(useCase?: UseCase): Promise<void> {
|
||||
if (useCase) {
|
||||
PosthogAnalytics.instance.setProperty("ftueUseCaseSelection", useCase);
|
||||
SettingsStore.setValue("FTUE.useCaseSelection", null, SettingLevel.ACCOUNT, useCase);
|
||||
|
@ -1370,7 +1370,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
private initPosthogAnalyticsToast() {
|
||||
private initPosthogAnalyticsToast(): void {
|
||||
// Show the analytics toast if necessary
|
||||
if (SettingsStore.getValue("pseudonymousAnalyticsOptIn") === null) {
|
||||
showAnalyticsToast();
|
||||
|
@ -1397,7 +1397,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
);
|
||||
}
|
||||
|
||||
private showScreenAfterLogin() {
|
||||
private showScreenAfterLogin(): void {
|
||||
// If screenAfterLogin is set, use that, then null it so that a second login will
|
||||
// result in view_home_page, _user_settings or _room_directory
|
||||
if (this.screenAfterLogin && this.screenAfterLogin.screen) {
|
||||
|
@ -1415,7 +1415,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
private viewLastRoom() {
|
||||
private viewLastRoom(): void {
|
||||
dis.dispatch<ViewRoomPayload>({
|
||||
action: Action.ViewRoom,
|
||||
room_id: localStorage.getItem("mx_last_room_id"),
|
||||
|
@ -1426,7 +1426,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
/**
|
||||
* Called when the session is logged out
|
||||
*/
|
||||
private onLoggedOut() {
|
||||
private onLoggedOut(): void {
|
||||
this.viewLogin({
|
||||
ready: false,
|
||||
collapseLhs: false,
|
||||
|
@ -1439,7 +1439,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
/**
|
||||
* Called when the session is softly logged out
|
||||
*/
|
||||
private onSoftLogout() {
|
||||
private onSoftLogout(): void {
|
||||
this.notifyNewScreen("soft_logout");
|
||||
this.setStateForNewView({
|
||||
view: Views.SOFT_LOGOUT,
|
||||
|
@ -1455,7 +1455,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
* Called just before the matrix client is started
|
||||
* (useful for setting listeners)
|
||||
*/
|
||||
private onWillStartClient() {
|
||||
private onWillStartClient(): void {
|
||||
// reset the 'have completed first sync' flag,
|
||||
// since we're about to start the client and therefore about
|
||||
// to do the first sync
|
||||
|
@ -1610,7 +1610,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
break;
|
||||
}
|
||||
});
|
||||
cli.on(CryptoEvent.KeyBackupFailed, async (errcode) => {
|
||||
cli.on(CryptoEvent.KeyBackupFailed, async (errcode): Promise<void> => {
|
||||
let haveNewVersion;
|
||||
let newVersionInfo;
|
||||
// if key backup is still enabled, there must be a new backup in place
|
||||
|
@ -1678,7 +1678,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
* setting up anything that requires the client to be started.
|
||||
* @private
|
||||
*/
|
||||
private onClientStarted() {
|
||||
private onClientStarted(): void {
|
||||
const cli = MatrixClientPeg.get();
|
||||
|
||||
if (cli.isCryptoEnabled()) {
|
||||
|
@ -1700,7 +1700,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
public showScreen(screen: string, params?: { [key: string]: any }) {
|
||||
public showScreen(screen: string, params?: { [key: string]: any }): void {
|
||||
const cli = MatrixClientPeg.get();
|
||||
const isLoggedOutOrGuest = !cli || cli.isGuest();
|
||||
if (!isLoggedOutOrGuest && AUTH_SCREENS.includes(screen)) {
|
||||
|
@ -1861,14 +1861,14 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
private notifyNewScreen(screen: string, replaceLast = false) {
|
||||
private notifyNewScreen(screen: string, replaceLast = false): void {
|
||||
if (this.props.onNewScreen) {
|
||||
this.props.onNewScreen(screen, replaceLast);
|
||||
}
|
||||
this.setPageSubtitle();
|
||||
}
|
||||
|
||||
private onLogoutClick(event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) {
|
||||
private onLogoutClick(event: React.MouseEvent<HTMLAnchorElement, MouseEvent>): void {
|
||||
dis.dispatch({
|
||||
action: "logout",
|
||||
});
|
||||
|
@ -1876,7 +1876,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
event.preventDefault();
|
||||
}
|
||||
|
||||
private handleResize = () => {
|
||||
private handleResize = (): void => {
|
||||
const LHS_THRESHOLD = 1000;
|
||||
const width = UIStore.instance.windowWidth;
|
||||
|
||||
|
@ -1892,19 +1892,19 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
this.state.resizeNotifier.notifyWindowResized();
|
||||
};
|
||||
|
||||
private dispatchTimelineResize() {
|
||||
private dispatchTimelineResize(): void {
|
||||
dis.dispatch({ action: "timeline_resize" });
|
||||
}
|
||||
|
||||
private onRegisterClick = () => {
|
||||
private onRegisterClick = (): void => {
|
||||
this.showScreen("register");
|
||||
};
|
||||
|
||||
private onLoginClick = () => {
|
||||
private onLoginClick = (): void => {
|
||||
this.showScreen("login");
|
||||
};
|
||||
|
||||
private onForgotPasswordClick = () => {
|
||||
private onForgotPasswordClick = (): void => {
|
||||
this.showScreen("forgot_password");
|
||||
};
|
||||
|
||||
|
@ -1926,7 +1926,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
});
|
||||
}
|
||||
|
||||
private setPageSubtitle(subtitle = "") {
|
||||
private setPageSubtitle(subtitle = ""): void {
|
||||
if (this.state.currentRoomId) {
|
||||
const client = MatrixClientPeg.get();
|
||||
const room = client && client.getRoom(this.state.currentRoomId);
|
||||
|
@ -1963,11 +1963,11 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
this.setPageSubtitle();
|
||||
};
|
||||
|
||||
private onServerConfigChange = (serverConfig: ValidatedServerConfig) => {
|
||||
private onServerConfigChange = (serverConfig: ValidatedServerConfig): void => {
|
||||
this.setState({ serverConfig });
|
||||
};
|
||||
|
||||
private makeRegistrationUrl = (params: QueryDict) => {
|
||||
private makeRegistrationUrl = (params: QueryDict): string => {
|
||||
if (this.props.startingFragmentQueryParams.referrer) {
|
||||
params.referrer = this.props.startingFragmentQueryParams.referrer;
|
||||
}
|
||||
|
@ -2016,7 +2016,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
return fragmentAfterLogin;
|
||||
}
|
||||
|
||||
public render() {
|
||||
public render(): JSX.Element {
|
||||
const fragmentAfterLogin = this.getFragmentAfterLogin();
|
||||
let view = null;
|
||||
|
||||
|
@ -2132,7 +2132,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||
/>
|
||||
);
|
||||
} else if (this.state.view === Views.USE_CASE_SELECTION) {
|
||||
view = <UseCaseSelection onFinished={(useCase) => this.onShowPostLoginScreen(useCase)} />;
|
||||
view = <UseCaseSelection onFinished={(useCase): Promise<void> => this.onShowPostLoginScreen(useCase)} />;
|
||||
} else {
|
||||
logger.error(`Unknown view ${this.state.view}`);
|
||||
}
|
||||
|
|
|
@ -296,19 +296,19 @@ export default class MessagePanel extends React.Component<IProps, IState> {
|
|||
);
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
public componentDidMount(): void {
|
||||
this.calculateRoomMembersCount();
|
||||
this.props.room?.currentState.on(RoomStateEvent.Update, this.calculateRoomMembersCount);
|
||||
this.isMounted = true;
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
public componentWillUnmount(): void {
|
||||
this.isMounted = false;
|
||||
this.props.room?.currentState.off(RoomStateEvent.Update, this.calculateRoomMembersCount);
|
||||
SettingsStore.unwatchSetting(this.showTypingNotificationsWatcherRef);
|
||||
}
|
||||
|
||||
public componentDidUpdate(prevProps, prevState) {
|
||||
public componentDidUpdate(prevProps, prevState): void {
|
||||
if (prevProps.layout !== this.props.layout) {
|
||||
this.calculateRoomMembersCount();
|
||||
}
|
||||
|
@ -752,7 +752,7 @@ export default class MessagePanel extends React.Component<IProps, IState> {
|
|||
const readReceipts = this.readReceiptsByEvent[eventId];
|
||||
|
||||
let isLastSuccessful = false;
|
||||
const isSentState = (s) => !s || s === "sent";
|
||||
const isSentState = (s): boolean => !s || s === "sent";
|
||||
const isSent = isSentState(mxEv.getAssociatedStatus());
|
||||
const hasNextEvent = nextEvent && this.shouldShowEvent(nextEvent);
|
||||
if (!hasNextEvent && isSent) {
|
||||
|
@ -982,7 +982,7 @@ export default class MessagePanel extends React.Component<IProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
public render() {
|
||||
public render(): JSX.Element {
|
||||
let topSpinner;
|
||||
let bottomSpinner;
|
||||
if (this.props.backPaginating) {
|
||||
|
|
|
@ -37,15 +37,15 @@ export default class NonUrgentToastContainer extends React.PureComponent<IProps,
|
|||
NonUrgentToastStore.instance.on(UPDATE_EVENT, this.onUpdateToasts);
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
public componentWillUnmount(): void {
|
||||
NonUrgentToastStore.instance.off(UPDATE_EVENT, this.onUpdateToasts);
|
||||
}
|
||||
|
||||
private onUpdateToasts = () => {
|
||||
private onUpdateToasts = (): void => {
|
||||
this.setState({ toasts: NonUrgentToastStore.instance.components });
|
||||
};
|
||||
|
||||
public render() {
|
||||
public render(): JSX.Element {
|
||||
const toasts = this.state.toasts.map((t, i) => {
|
||||
return (
|
||||
<div className="mx_NonUrgentToastContainer_toast" key={`toast-${i}`}>
|
||||
|
|
|
@ -55,7 +55,7 @@ export default class NotificationPanel extends React.PureComponent<IProps, IStat
|
|||
this.setState({ narrow });
|
||||
};
|
||||
|
||||
public render() {
|
||||
public render(): JSX.Element {
|
||||
const emptyState = (
|
||||
<div className="mx_RightPanel_empty mx_NotificationPanel_empty">
|
||||
<h2>{_t("You're all caught up")}</h2>
|
||||
|
|
|
@ -79,7 +79,7 @@ export default class PictureInPictureDragger extends React.Component<IProps> {
|
|||
this._moving = value;
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
public componentDidMount(): void {
|
||||
document.addEventListener("mousemove", this.onMoving);
|
||||
document.addEventListener("mouseup", this.onEndMoving);
|
||||
UIStore.instance.on(UI_EVENTS.Resize, this.onResize);
|
||||
|
@ -87,7 +87,7 @@ export default class PictureInPictureDragger extends React.Component<IProps> {
|
|||
this.snap();
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
public componentWillUnmount(): void {
|
||||
document.removeEventListener("mousemove", this.onMoving);
|
||||
document.removeEventListener("mouseup", this.onEndMoving);
|
||||
UIStore.instance.off(UI_EVENTS.Resize, this.onResize);
|
||||
|
@ -97,7 +97,7 @@ export default class PictureInPictureDragger extends React.Component<IProps> {
|
|||
if (prevProps.children !== this.props.children) this.snap(true);
|
||||
}
|
||||
|
||||
private animationCallback = () => {
|
||||
private animationCallback = (): void => {
|
||||
if (
|
||||
!this.moving &&
|
||||
Math.abs(this.translationX - this.desiredTranslationX) <= 1 &&
|
||||
|
@ -119,13 +119,13 @@ export default class PictureInPictureDragger extends React.Component<IProps> {
|
|||
this.props.onMove?.();
|
||||
};
|
||||
|
||||
private setStyle = () => {
|
||||
private setStyle = (): void => {
|
||||
if (!this.callViewWrapper.current) return;
|
||||
// Set the element's style directly, bypassing React for efficiency
|
||||
this.callViewWrapper.current.style.transform = `translateX(${this.translationX}px) translateY(${this.translationY}px)`;
|
||||
};
|
||||
|
||||
private setTranslation(inTranslationX: number, inTranslationY: number) {
|
||||
private setTranslation(inTranslationX: number, inTranslationY: number): void {
|
||||
const width = this.callViewWrapper.current?.clientWidth || PIP_VIEW_WIDTH;
|
||||
const height = this.callViewWrapper.current?.clientHeight || PIP_VIEW_HEIGHT;
|
||||
|
||||
|
@ -152,7 +152,7 @@ export default class PictureInPictureDragger extends React.Component<IProps> {
|
|||
this.snap(false);
|
||||
};
|
||||
|
||||
private snap = (animate = false) => {
|
||||
private snap = (animate = false): void => {
|
||||
const translationX = this.desiredTranslationX;
|
||||
const translationY = this.desiredTranslationY;
|
||||
// We subtract the PiP size from the window size in order to calculate
|
||||
|
@ -187,14 +187,14 @@ export default class PictureInPictureDragger extends React.Component<IProps> {
|
|||
this.scheduledUpdate.mark();
|
||||
};
|
||||
|
||||
private onStartMoving = (event: React.MouseEvent | MouseEvent) => {
|
||||
private onStartMoving = (event: React.MouseEvent | MouseEvent): void => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
this.mouseHeld = true;
|
||||
};
|
||||
|
||||
private onMoving = (event: MouseEvent) => {
|
||||
private onMoving = (event: MouseEvent): void => {
|
||||
if (!this.mouseHeld) return;
|
||||
|
||||
event.preventDefault();
|
||||
|
@ -210,7 +210,7 @@ export default class PictureInPictureDragger extends React.Component<IProps> {
|
|||
this.setTranslation(event.pageX - this.initX, event.pageY - this.initY);
|
||||
};
|
||||
|
||||
private onEndMoving = (event: MouseEvent) => {
|
||||
private onEndMoving = (event: MouseEvent): void => {
|
||||
if (!this.mouseHeld) return;
|
||||
|
||||
event.preventDefault();
|
||||
|
@ -223,7 +223,7 @@ export default class PictureInPictureDragger extends React.Component<IProps> {
|
|||
this.snap(true);
|
||||
};
|
||||
|
||||
private onClickCapture = (event: React.MouseEvent) => {
|
||||
private onClickCapture = (event: React.MouseEvent): void => {
|
||||
// To prevent mouse up events during dragging from being double-counted
|
||||
// as clicks, we cancel clicks before they ever reach the target
|
||||
if (this.moving) {
|
||||
|
@ -232,7 +232,7 @@ export default class PictureInPictureDragger extends React.Component<IProps> {
|
|||
}
|
||||
};
|
||||
|
||||
public render() {
|
||||
public render(): JSX.Element {
|
||||
const style = {
|
||||
transform: `translateX(${this.translationX}px) translateY(${this.translationY}px)`,
|
||||
};
|
||||
|
|
|
@ -135,7 +135,7 @@ class PipContainerInner extends React.Component<IProps, IState> {
|
|||
};
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
public componentDidMount(): void {
|
||||
LegacyCallHandler.instance.addListener(LegacyCallHandlerEvent.CallChangeRoom, this.updateCalls);
|
||||
LegacyCallHandler.instance.addListener(LegacyCallHandlerEvent.CallState, this.updateCalls);
|
||||
SdkContextClass.instance.roomViewStore.addListener(UPDATE_EVENT, this.onRoomViewStoreUpdate);
|
||||
|
@ -149,7 +149,7 @@ class PipContainerInner extends React.Component<IProps, IState> {
|
|||
ActiveWidgetStore.instance.on(ActiveWidgetStoreEvent.Undock, this.onWidgetDockChanges);
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
public componentWillUnmount(): void {
|
||||
LegacyCallHandler.instance.removeListener(LegacyCallHandlerEvent.CallChangeRoom, this.updateCalls);
|
||||
LegacyCallHandler.instance.removeListener(LegacyCallHandlerEvent.CallState, this.updateCalls);
|
||||
const cli = MatrixClientPeg.get();
|
||||
|
@ -164,9 +164,9 @@ class PipContainerInner extends React.Component<IProps, IState> {
|
|||
ActiveWidgetStore.instance.off(ActiveWidgetStoreEvent.Undock, this.onWidgetDockChanges);
|
||||
}
|
||||
|
||||
private onMove = () => this.props.movePersistedElement.current?.();
|
||||
private onMove = (): void => this.props.movePersistedElement.current?.();
|
||||
|
||||
private onRoomViewStoreUpdate = () => {
|
||||
private onRoomViewStoreUpdate = (): void => {
|
||||
const newRoomId = SdkContextClass.instance.roomViewStore.getRoomId();
|
||||
const oldRoomId = this.state.viewedRoomId;
|
||||
if (newRoomId === oldRoomId) return;
|
||||
|
@ -213,7 +213,7 @@ class PipContainerInner extends React.Component<IProps, IState> {
|
|||
this.updateShowWidgetInPip();
|
||||
};
|
||||
|
||||
private onCallRemoteHold = () => {
|
||||
private onCallRemoteHold = (): void => {
|
||||
if (!this.state.viewedRoomId) return;
|
||||
const [primaryCall, secondaryCalls] = getPrimarySecondaryCallsForPip(this.state.viewedRoomId);
|
||||
|
||||
|
@ -238,7 +238,7 @@ class PipContainerInner extends React.Component<IProps, IState> {
|
|||
public updateShowWidgetInPip(
|
||||
persistentWidgetId = this.state.persistentWidgetId,
|
||||
persistentRoomId = this.state.persistentRoomId,
|
||||
) {
|
||||
): void {
|
||||
let fromAnotherRoom = false;
|
||||
let notDocked = false;
|
||||
// Sanity check the room - the widget may have been destroyed between render cycles, and
|
||||
|
@ -293,7 +293,7 @@ class PipContainerInner extends React.Component<IProps, IState> {
|
|||
);
|
||||
}
|
||||
|
||||
public render() {
|
||||
public render(): JSX.Element {
|
||||
const pipMode = true;
|
||||
let pipContent: Array<CreatePipChildren> = [];
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@ export default class RightPanel extends React.Component<IProps, IState> {
|
|||
};
|
||||
}
|
||||
|
||||
private onRoomStateMember = (ev: MatrixEvent, state: RoomState, member: RoomMember) => {
|
||||
private onRoomStateMember = (ev: MatrixEvent, state: RoomState, member: RoomMember): void => {
|
||||
if (!this.props.room || member.roomId !== this.props.room.roomId) {
|
||||
return;
|
||||
}
|
||||
|
@ -118,11 +118,11 @@ export default class RightPanel extends React.Component<IProps, IState> {
|
|||
}
|
||||
};
|
||||
|
||||
private onRightPanelStoreUpdate = () => {
|
||||
private onRightPanelStoreUpdate = (): void => {
|
||||
this.setState({ ...(RightPanel.getDerivedStateFromProps(this.props) as IState) });
|
||||
};
|
||||
|
||||
private onClose = () => {
|
||||
private onClose = (): void => {
|
||||
// XXX: There are three different ways of 'closing' this panel depending on what state
|
||||
// things are in... this knows far more than it should do about the state of the rest
|
||||
// of the app and is generally a bit silly.
|
||||
|
|
|
@ -39,15 +39,15 @@ export default class RoomSearch extends React.PureComponent<IProps> {
|
|||
this.dispatcherRef = defaultDispatcher.register(this.onAction);
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
public componentWillUnmount(): void {
|
||||
defaultDispatcher.unregister(this.dispatcherRef);
|
||||
}
|
||||
|
||||
private openSpotlight() {
|
||||
private openSpotlight(): void {
|
||||
Modal.createDialog(SpotlightDialog, {}, "mx_SpotlightDialog_wrapper", false, true);
|
||||
}
|
||||
|
||||
private onAction = (payload: ActionPayload) => {
|
||||
private onAction = (payload: ActionPayload): void => {
|
||||
if (payload.action === "focus_room_filter") {
|
||||
this.openSpotlight();
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ import RoomContext from "../../contexts/RoomContext";
|
|||
import SettingsStore from "../../settings/SettingsStore";
|
||||
|
||||
const DEBUG = false;
|
||||
let debuglog = function (msg: string) {};
|
||||
let debuglog = function (msg: string): void {};
|
||||
|
||||
/* istanbul ignore next */
|
||||
if (DEBUG) {
|
||||
|
@ -76,7 +76,7 @@ export const RoomSearchView = forwardRef<ScrollPanel, Props>(
|
|||
|
||||
return searchPromise
|
||||
.then(
|
||||
async (results) => {
|
||||
async (results): Promise<boolean> => {
|
||||
debuglog("search complete");
|
||||
if (aborted.current) {
|
||||
logger.error("Discarding stale search results");
|
||||
|
@ -209,7 +209,7 @@ export const RoomSearchView = forwardRef<ScrollPanel, Props>(
|
|||
|
||||
// once dynamic content in the search results load, make the scrollPanel check
|
||||
// the scroll offsets.
|
||||
const onHeightChanged = () => {
|
||||
const onHeightChanged = (): void => {
|
||||
const scrollPanel = ref.current;
|
||||
scrollPanel?.checkScroll();
|
||||
};
|
||||
|
|
|
@ -146,7 +146,7 @@ export default class RoomStatusBar extends React.PureComponent<IProps, IState> {
|
|||
dis.fire(Action.FocusSendMessageComposer);
|
||||
};
|
||||
|
||||
private onRoomLocalEchoUpdated = (ev: MatrixEvent, room: Room) => {
|
||||
private onRoomLocalEchoUpdated = (ev: MatrixEvent, room: Room): void => {
|
||||
if (room.roomId !== this.props.room.roomId) return;
|
||||
const messages = getUnsentMessages(this.props.room);
|
||||
this.setState({
|
||||
|
|
|
@ -115,7 +115,7 @@ import VoipUserMapper from "../../VoipUserMapper";
|
|||
import { isCallEvent } from "./LegacyCallEventGrouper";
|
||||
|
||||
const DEBUG = false;
|
||||
let debuglog = function (msg: string) {};
|
||||
let debuglog = function (msg: string): void {};
|
||||
|
||||
const BROWSER_SUPPORTS_SANDBOX = "sandbox" in document.createElement("iframe");
|
||||
|
||||
|
@ -248,7 +248,7 @@ function LocalRoomView(props: LocalRoomViewProps): ReactElement {
|
|||
encryptionTile = <EncryptionEvent mxEvent={encryptionEvent} />;
|
||||
}
|
||||
|
||||
const onRetryClicked = () => {
|
||||
const onRetryClicked = (): void => {
|
||||
room.state = LocalRoomState.NEW;
|
||||
defaultDispatcher.dispatch({
|
||||
action: "local_room_event",
|
||||
|
@ -470,21 +470,21 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
];
|
||||
}
|
||||
|
||||
private onIsResizing = (resizing: boolean) => {
|
||||
private onIsResizing = (resizing: boolean): void => {
|
||||
this.setState({ resizing });
|
||||
};
|
||||
|
||||
private onWidgetStoreUpdate = () => {
|
||||
private onWidgetStoreUpdate = (): void => {
|
||||
if (!this.state.room) return;
|
||||
this.checkWidgets(this.state.room);
|
||||
};
|
||||
|
||||
private onWidgetEchoStoreUpdate = () => {
|
||||
private onWidgetEchoStoreUpdate = (): void => {
|
||||
if (!this.state.room) return;
|
||||
this.checkWidgets(this.state.room);
|
||||
};
|
||||
|
||||
private onWidgetLayoutChange = () => {
|
||||
private onWidgetLayoutChange = (): void => {
|
||||
if (!this.state.room) return;
|
||||
dis.dispatch({
|
||||
action: "appsDrawer",
|
||||
|
@ -505,7 +505,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
});
|
||||
};
|
||||
|
||||
private getMainSplitContentType = (room: Room) => {
|
||||
private getMainSplitContentType = (room: Room): MainSplitContentType => {
|
||||
if (
|
||||
(SettingsStore.getValue("feature_group_calls") && this.context.roomViewStore.isViewingCall()) ||
|
||||
isVideoRoom(room)
|
||||
|
@ -707,7 +707,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
}
|
||||
};
|
||||
|
||||
private onActiveCalls = () => {
|
||||
private onActiveCalls = (): void => {
|
||||
if (this.state.roomId === undefined) return;
|
||||
const activeCall = CallStore.instance.getActiveCall(this.state.roomId);
|
||||
|
||||
|
@ -727,7 +727,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
this.setState({ activeCall });
|
||||
};
|
||||
|
||||
private getRoomId = () => {
|
||||
private getRoomId = (): string => {
|
||||
// According to `onRoomViewStoreUpdate`, `state.roomId` can be null
|
||||
// if we have a room alias we haven't resolved yet. To work around this,
|
||||
// first we'll try the room object if it's there, and then fallback to
|
||||
|
@ -736,7 +736,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
return this.state.room ? this.state.room.roomId : this.state.roomId;
|
||||
};
|
||||
|
||||
private getPermalinkCreatorForRoom(room: Room) {
|
||||
private getPermalinkCreatorForRoom(room: Room): RoomPermalinkCreator {
|
||||
if (this.permalinkCreators[room.roomId]) return this.permalinkCreators[room.roomId];
|
||||
|
||||
this.permalinkCreators[room.roomId] = new RoomPermalinkCreator(room);
|
||||
|
@ -750,14 +750,14 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
return this.permalinkCreators[room.roomId];
|
||||
}
|
||||
|
||||
private stopAllPermalinkCreators() {
|
||||
private stopAllPermalinkCreators(): void {
|
||||
if (!this.permalinkCreators) return;
|
||||
for (const roomId of Object.keys(this.permalinkCreators)) {
|
||||
this.permalinkCreators[roomId].stop();
|
||||
}
|
||||
}
|
||||
|
||||
private setupRoom(room: Room, roomId: string, joining: boolean, shouldPeek: boolean) {
|
||||
private setupRoom(room: Room, roomId: string, joining: boolean, shouldPeek: boolean): void {
|
||||
// if this is an unknown room then we're in one of three states:
|
||||
// - This is a room we can peek into (search engine) (we can /peek)
|
||||
// - This is a room we can publicly join or were invited to. (we can /join)
|
||||
|
@ -822,7 +822,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
}
|
||||
}
|
||||
|
||||
private shouldShowApps(room: Room) {
|
||||
private shouldShowApps(room: Room): boolean {
|
||||
if (!BROWSER_SUPPORTS_SANDBOX || !room) return false;
|
||||
|
||||
// Check if user has previously chosen to hide the app drawer for this
|
||||
|
@ -838,7 +838,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
return isManuallyShown && widgets.length > 0;
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
public componentDidMount(): void {
|
||||
this.onRoomViewStoreUpdate(true);
|
||||
|
||||
const call = this.getCallForRoom();
|
||||
|
@ -851,7 +851,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
window.addEventListener("beforeunload", this.onPageUnload);
|
||||
}
|
||||
|
||||
public shouldComponentUpdate(nextProps, nextState) {
|
||||
public shouldComponentUpdate(nextProps, nextState): boolean {
|
||||
const hasPropsDiff = objectHasDiff(this.props, nextProps);
|
||||
|
||||
const { upgradeRecommendation, ...state } = this.state;
|
||||
|
@ -864,7 +864,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
return hasPropsDiff || hasStateDiff;
|
||||
}
|
||||
|
||||
public componentDidUpdate() {
|
||||
public componentDidUpdate(): void {
|
||||
// Note: We check the ref here with a flag because componentDidMount, despite
|
||||
// documentation, does not define our messagePanel ref. It looks like our spinner
|
||||
// in render() prevents the ref from being set on first mount, so we try and
|
||||
|
@ -877,7 +877,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
}
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
public componentWillUnmount(): void {
|
||||
// set a boolean to say we've been unmounted, which any pending
|
||||
// promises can use to throw away their results.
|
||||
//
|
||||
|
@ -947,13 +947,13 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
}
|
||||
}
|
||||
|
||||
private onRightPanelStoreUpdate = () => {
|
||||
private onRightPanelStoreUpdate = (): void => {
|
||||
this.setState({
|
||||
showRightPanel: this.context.rightPanelStore.isOpenForRoom(this.state.roomId),
|
||||
});
|
||||
};
|
||||
|
||||
private onPageUnload = (event) => {
|
||||
private onPageUnload = (event): string => {
|
||||
if (ContentMessages.sharedInstance().getCurrentUploads().length > 0) {
|
||||
return (event.returnValue = _t("You seem to be uploading files, are you sure you want to quit?"));
|
||||
} else if (this.getCallForRoom() && this.state.callState !== "ended") {
|
||||
|
@ -961,7 +961,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
}
|
||||
};
|
||||
|
||||
private onReactKeyDown = (ev) => {
|
||||
private onReactKeyDown = (ev): void => {
|
||||
let handled = false;
|
||||
|
||||
const action = getKeyBindingsManager().getRoomAction(ev);
|
||||
|
@ -1120,12 +1120,12 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
}
|
||||
};
|
||||
|
||||
private onLocalRoomEvent(roomId: string) {
|
||||
private onLocalRoomEvent(roomId: string): void {
|
||||
if (roomId !== this.state.room.roomId) return;
|
||||
createRoomFromLocalRoom(this.context.client, this.state.room as LocalRoom);
|
||||
}
|
||||
|
||||
private onRoomTimeline = (ev: MatrixEvent, room: Room | null, toStartOfTimeline: boolean, removed, data) => {
|
||||
private onRoomTimeline = (ev: MatrixEvent, room: Room | null, toStartOfTimeline: boolean, removed, data): void => {
|
||||
if (this.unmounted) return;
|
||||
|
||||
// ignore events for other rooms or the notification timeline set
|
||||
|
@ -1167,7 +1167,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
}
|
||||
};
|
||||
|
||||
private onEventDecrypted = (ev: MatrixEvent) => {
|
||||
private onEventDecrypted = (ev: MatrixEvent): void => {
|
||||
if (!this.state.room || !this.state.matrixClientIsReady) return; // not ready at all
|
||||
if (ev.getRoomId() !== this.state.room.roomId) return; // not for us
|
||||
this.updateVisibleDecryptionFailures();
|
||||
|
@ -1175,7 +1175,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
this.handleEffects(ev);
|
||||
};
|
||||
|
||||
private handleEffects = (ev: MatrixEvent) => {
|
||||
private handleEffects = (ev: MatrixEvent): void => {
|
||||
const notifState = this.context.roomNotificationStateStore.getRoomState(this.state.room);
|
||||
if (!notifState.isUnread) return;
|
||||
|
||||
|
@ -1189,19 +1189,19 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
});
|
||||
};
|
||||
|
||||
private onRoomName = (room: Room) => {
|
||||
private onRoomName = (room: Room): void => {
|
||||
if (this.state.room && room.roomId == this.state.room.roomId) {
|
||||
this.forceUpdate();
|
||||
}
|
||||
};
|
||||
|
||||
private onKeyBackupStatus = () => {
|
||||
private onKeyBackupStatus = (): void => {
|
||||
// Key backup status changes affect whether the in-room recovery
|
||||
// reminder is displayed.
|
||||
this.forceUpdate();
|
||||
};
|
||||
|
||||
public canResetTimeline = () => {
|
||||
public canResetTimeline = (): boolean => {
|
||||
if (!this.messagePanel) {
|
||||
return true;
|
||||
}
|
||||
|
@ -1216,7 +1216,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
|
||||
// called when state.room is first initialised (either at initial load,
|
||||
// after a successful peek, or after we join the room).
|
||||
private onRoomLoaded = (room: Room) => {
|
||||
private onRoomLoaded = (room: Room): void => {
|
||||
if (this.unmounted) return;
|
||||
// Attach a widget store listener only when we get a room
|
||||
this.context.widgetLayoutStore.on(WidgetLayoutStore.emissionForRoom(room), this.onWidgetLayoutChange);
|
||||
|
@ -1251,17 +1251,17 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
}
|
||||
};
|
||||
|
||||
private getRoomTombstone(room = this.state.room) {
|
||||
private getRoomTombstone(room = this.state.room): MatrixEvent | undefined {
|
||||
return room?.currentState.getStateEvents(EventType.RoomTombstone, "");
|
||||
}
|
||||
|
||||
private async calculateRecommendedVersion(room: Room) {
|
||||
private async calculateRecommendedVersion(room: Room): Promise<void> {
|
||||
const upgradeRecommendation = await room.getRecommendedVersion();
|
||||
if (this.unmounted) return;
|
||||
this.setState({ upgradeRecommendation });
|
||||
}
|
||||
|
||||
private async loadMembersIfJoined(room: Room) {
|
||||
private async loadMembersIfJoined(room: Room): Promise<void> {
|
||||
// lazy load members if enabled
|
||||
if (this.context.client.hasLazyLoadMembersEnabled()) {
|
||||
if (room && room.getMyMembership() === "join") {
|
||||
|
@ -1280,14 +1280,14 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
}
|
||||
}
|
||||
|
||||
private calculatePeekRules(room: Room) {
|
||||
private calculatePeekRules(room: Room): void {
|
||||
const historyVisibility = room.currentState.getStateEvents(EventType.RoomHistoryVisibility, "");
|
||||
this.setState({
|
||||
canPeek: historyVisibility?.getContent().history_visibility === HistoryVisibility.WorldReadable,
|
||||
});
|
||||
}
|
||||
|
||||
private updatePreviewUrlVisibility({ roomId }: Room) {
|
||||
private updatePreviewUrlVisibility({ roomId }: Room): void {
|
||||
// URL Previews in E2EE rooms can be a privacy leak so use a different setting which is per-room explicit
|
||||
const key = this.context.client.isRoomEncrypted(roomId) ? "urlPreviewsEnabled_e2ee" : "urlPreviewsEnabled";
|
||||
this.setState({
|
||||
|
@ -1295,7 +1295,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
});
|
||||
}
|
||||
|
||||
private onRoom = (room: Room) => {
|
||||
private onRoom = (room: Room): void => {
|
||||
if (!room || room.roomId !== this.state.roomId) {
|
||||
return;
|
||||
}
|
||||
|
@ -1318,7 +1318,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
);
|
||||
};
|
||||
|
||||
private onDeviceVerificationChanged = (userId: string) => {
|
||||
private onDeviceVerificationChanged = (userId: string): void => {
|
||||
const room = this.state.room;
|
||||
if (!room?.currentState.getMember(userId)) {
|
||||
return;
|
||||
|
@ -1326,7 +1326,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
this.updateE2EStatus(room);
|
||||
};
|
||||
|
||||
private onUserVerificationChanged = (userId: string) => {
|
||||
private onUserVerificationChanged = (userId: string): void => {
|
||||
const room = this.state.room;
|
||||
if (!room || !room.currentState.getMember(userId)) {
|
||||
return;
|
||||
|
@ -1334,14 +1334,14 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
this.updateE2EStatus(room);
|
||||
};
|
||||
|
||||
private onCrossSigningKeysChanged = () => {
|
||||
private onCrossSigningKeysChanged = (): void => {
|
||||
const room = this.state.room;
|
||||
if (room) {
|
||||
this.updateE2EStatus(room);
|
||||
}
|
||||
};
|
||||
|
||||
private async updateE2EStatus(room: Room) {
|
||||
private async updateE2EStatus(room: Room): Promise<void> {
|
||||
if (!this.context.client.isRoomEncrypted(room.roomId)) return;
|
||||
|
||||
// If crypto is not currently enabled, we aren't tracking devices at all,
|
||||
|
@ -1357,13 +1357,13 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
this.setState({ e2eStatus });
|
||||
}
|
||||
|
||||
private onUrlPreviewsEnabledChange = () => {
|
||||
private onUrlPreviewsEnabledChange = (): void => {
|
||||
if (this.state.room) {
|
||||
this.updatePreviewUrlVisibility(this.state.room);
|
||||
}
|
||||
};
|
||||
|
||||
private onRoomStateEvents = (ev: MatrixEvent, state: RoomState) => {
|
||||
private onRoomStateEvents = (ev: MatrixEvent, state: RoomState): void => {
|
||||
// ignore if we don't have a room yet
|
||||
if (!this.state.room || this.state.room.roomId !== state.roomId) return;
|
||||
|
||||
|
@ -1377,7 +1377,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
}
|
||||
};
|
||||
|
||||
private onRoomStateUpdate = (state: RoomState) => {
|
||||
private onRoomStateUpdate = (state: RoomState): void => {
|
||||
// ignore members in other rooms
|
||||
if (state.roomId !== this.state.room?.roomId) {
|
||||
return;
|
||||
|
@ -1386,7 +1386,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
this.updateRoomMembers();
|
||||
};
|
||||
|
||||
private onMyMembership = (room: Room, membership: string, oldMembership: string) => {
|
||||
private onMyMembership = (room: Room, membership: string, oldMembership: string): void => {
|
||||
if (room.roomId === this.state.roomId) {
|
||||
this.forceUpdate();
|
||||
this.loadMembersIfJoined(room);
|
||||
|
@ -1394,7 +1394,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
}
|
||||
};
|
||||
|
||||
private updatePermissions(room: Room) {
|
||||
private updatePermissions(room: Room): void {
|
||||
if (room) {
|
||||
const me = this.context.client.getUserId();
|
||||
const canReact =
|
||||
|
@ -1420,7 +1420,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
{ leading: true, trailing: true },
|
||||
);
|
||||
|
||||
private checkDesktopNotifications() {
|
||||
private checkDesktopNotifications(): void {
|
||||
const memberCount = this.state.room.getJoinedMemberCount() + this.state.room.getInvitedMemberCount();
|
||||
// if they are not alone prompt the user about notifications so they don't miss replies
|
||||
if (memberCount > 1 && Notifier.shouldShowPrompt()) {
|
||||
|
@ -1428,7 +1428,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
}
|
||||
}
|
||||
|
||||
private updateDMState() {
|
||||
private updateDMState(): void {
|
||||
const room = this.state.room;
|
||||
if (room.getMyMembership() != "join") {
|
||||
return;
|
||||
|
@ -1439,7 +1439,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
}
|
||||
}
|
||||
|
||||
private onInviteClick = () => {
|
||||
private onInviteClick = (): void => {
|
||||
// open the room inviter
|
||||
dis.dispatch({
|
||||
action: "view_invite",
|
||||
|
@ -1447,7 +1447,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
});
|
||||
};
|
||||
|
||||
private onJoinButtonClicked = () => {
|
||||
private onJoinButtonClicked = (): void => {
|
||||
// If the user is a ROU, allow them to transition to a PWLU
|
||||
if (this.context.client?.isGuest()) {
|
||||
// Join this room once the user has registered and logged in
|
||||
|
@ -1489,7 +1489,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
{ leading: false, trailing: true },
|
||||
);
|
||||
|
||||
private onMessageListScroll = () => {
|
||||
private onMessageListScroll = (): void => {
|
||||
if (this.messagePanel.isAtEndOfLiveTimeline()) {
|
||||
this.setState({
|
||||
numUnreadMessages: 0,
|
||||
|
@ -1504,7 +1504,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
this.updateVisibleDecryptionFailures();
|
||||
};
|
||||
|
||||
private resetJumpToEvent = (eventId?: string) => {
|
||||
private resetJumpToEvent = (eventId?: string): void => {
|
||||
if (
|
||||
this.state.initialEventId &&
|
||||
this.state.initialEventScrollIntoView &&
|
||||
|
@ -1523,7 +1523,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
}
|
||||
};
|
||||
|
||||
private injectSticker(url: string, info: object, text: string, threadId: string | null) {
|
||||
private injectSticker(url: string, info: object, text: string, threadId: string | null): void {
|
||||
if (this.context.client.isGuest()) {
|
||||
dis.dispatch({ action: "require_registration" });
|
||||
return;
|
||||
|
@ -1539,7 +1539,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
});
|
||||
}
|
||||
|
||||
private onSearch = (term: string, scope: SearchScope) => {
|
||||
private onSearch = (term: string, scope: SearchScope): void => {
|
||||
const roomId = scope === SearchScope.Room ? this.state.room.roomId : undefined;
|
||||
debuglog("sending search request");
|
||||
const abortController = new AbortController();
|
||||
|
@ -1569,21 +1569,21 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
});
|
||||
};
|
||||
|
||||
private onAppsClick = () => {
|
||||
private onAppsClick = (): void => {
|
||||
dis.dispatch({
|
||||
action: "appsDrawer",
|
||||
show: !this.state.showApps,
|
||||
});
|
||||
};
|
||||
|
||||
private onForgetClick = () => {
|
||||
private onForgetClick = (): void => {
|
||||
dis.dispatch({
|
||||
action: "forget_room",
|
||||
room_id: this.state.room.roomId,
|
||||
});
|
||||
};
|
||||
|
||||
private onRejectButtonClicked = () => {
|
||||
private onRejectButtonClicked = (): void => {
|
||||
this.setState({
|
||||
rejecting: true,
|
||||
});
|
||||
|
@ -1611,7 +1611,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
);
|
||||
};
|
||||
|
||||
private onRejectAndIgnoreClick = async () => {
|
||||
private onRejectAndIgnoreClick = async (): Promise<void> => {
|
||||
this.setState({
|
||||
rejecting: true,
|
||||
});
|
||||
|
@ -1644,7 +1644,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
}
|
||||
};
|
||||
|
||||
private onRejectThreepidInviteButtonClicked = () => {
|
||||
private onRejectThreepidInviteButtonClicked = (): void => {
|
||||
// We can reject 3pid invites in the same way that we accept them,
|
||||
// using /leave rather than /join. In the short term though, we
|
||||
// just ignore them.
|
||||
|
@ -1652,7 +1652,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
dis.fire(Action.ViewRoomDirectory);
|
||||
};
|
||||
|
||||
private onSearchClick = () => {
|
||||
private onSearchClick = (): void => {
|
||||
this.setState({
|
||||
timelineRenderingType:
|
||||
this.state.timelineRenderingType === TimelineRenderingType.Search
|
||||
|
@ -1674,7 +1674,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
};
|
||||
|
||||
// jump down to the bottom of this room, where new events are arriving
|
||||
private jumpToLiveTimeline = () => {
|
||||
private jumpToLiveTimeline = (): void => {
|
||||
if (this.state.initialEventId && this.state.isInitialEventHighlighted) {
|
||||
// If we were viewing a highlighted event, firing view_room without
|
||||
// an event will take care of both clearing the URL fragment and
|
||||
|
@ -1692,18 +1692,18 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
};
|
||||
|
||||
// jump up to wherever our read marker is
|
||||
private jumpToReadMarker = () => {
|
||||
private jumpToReadMarker = (): void => {
|
||||
this.messagePanel.jumpToReadMarker();
|
||||
};
|
||||
|
||||
// update the read marker to match the read-receipt
|
||||
private forgetReadMarker = (ev) => {
|
||||
private forgetReadMarker = (ev): void => {
|
||||
ev.stopPropagation();
|
||||
this.messagePanel.forgetReadMarker();
|
||||
};
|
||||
|
||||
// decide whether or not the top 'unread messages' bar should be shown
|
||||
private updateTopUnreadMessagesBar = () => {
|
||||
private updateTopUnreadMessagesBar = (): void => {
|
||||
if (!this.messagePanel) {
|
||||
return;
|
||||
}
|
||||
|
@ -1754,12 +1754,12 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
};
|
||||
}
|
||||
|
||||
private onStatusBarVisible = () => {
|
||||
private onStatusBarVisible = (): void => {
|
||||
if (this.unmounted || this.state.statusBarVisible) return;
|
||||
this.setState({ statusBarVisible: true });
|
||||
};
|
||||
|
||||
private onStatusBarHidden = () => {
|
||||
private onStatusBarHidden = (): void => {
|
||||
// This is currently not desired as it is annoying if it keeps expanding and collapsing
|
||||
if (this.unmounted || !this.state.statusBarVisible) return;
|
||||
this.setState({ statusBarVisible: false });
|
||||
|
@ -1770,7 +1770,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
*
|
||||
* We pass it down to the scroll panel.
|
||||
*/
|
||||
public handleScrollKey = (ev) => {
|
||||
public handleScrollKey = (ev): void => {
|
||||
let panel: ScrollPanel | TimelinePanel;
|
||||
if (this.searchResultsPanel.current) {
|
||||
panel = this.searchResultsPanel.current;
|
||||
|
@ -1793,24 +1793,24 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
|
||||
// this has to be a proper method rather than an unnamed function,
|
||||
// otherwise react calls it with null on each update.
|
||||
private gatherTimelinePanelRef = (r) => {
|
||||
private gatherTimelinePanelRef = (r): void => {
|
||||
this.messagePanel = r;
|
||||
};
|
||||
|
||||
private getOldRoom() {
|
||||
private getOldRoom(): Room | null {
|
||||
const createEvent = this.state.room.currentState.getStateEvents(EventType.RoomCreate, "");
|
||||
if (!createEvent || !createEvent.getContent()["predecessor"]) return null;
|
||||
|
||||
return this.context.client.getRoom(createEvent.getContent()["predecessor"]["room_id"]);
|
||||
}
|
||||
|
||||
public getHiddenHighlightCount() {
|
||||
public getHiddenHighlightCount(): number {
|
||||
const oldRoom = this.getOldRoom();
|
||||
if (!oldRoom) return 0;
|
||||
return oldRoom.getUnreadNotificationCount(NotificationCountType.Highlight);
|
||||
}
|
||||
|
||||
public onHiddenHighlightsClick = () => {
|
||||
public onHiddenHighlightsClick = (): void => {
|
||||
const oldRoom = this.getOldRoom();
|
||||
if (!oldRoom) return;
|
||||
dis.dispatch<ViewRoomPayload>({
|
||||
|
@ -1826,7 +1826,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
});
|
||||
}
|
||||
|
||||
private onFileDrop = (dataTransfer: DataTransfer) =>
|
||||
private onFileDrop = (dataTransfer: DataTransfer): Promise<void> =>
|
||||
ContentMessages.sharedInstance().sendContentListToRoom(
|
||||
Array.from(dataTransfer.files),
|
||||
this.state.room?.roomId ?? this.state.roomId,
|
||||
|
@ -1869,7 +1869,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||
);
|
||||
}
|
||||
|
||||
public render() {
|
||||
public render(): JSX.Element {
|
||||
if (this.state.room instanceof LocalRoom) {
|
||||
if (this.state.room.state === LocalRoomState.CREATING) {
|
||||
return this.renderLocalRoomCreateLoader();
|
||||
|
|
|
@ -35,7 +35,7 @@ const UNFILL_REQUEST_DEBOUNCE_MS = 200;
|
|||
// much while the content loads.
|
||||
const PAGE_SIZE = 400;
|
||||
|
||||
const debuglog = (...args: any[]) => {
|
||||
const debuglog = (...args: any[]): void => {
|
||||
if (SettingsStore.getValue("debug_scroll_panel")) {
|
||||
logger.log.call(console, "ScrollPanel debuglog:", ...args);
|
||||
}
|
||||
|
@ -227,14 +227,14 @@ export default class ScrollPanel extends React.Component<IProps> {
|
|||
this.props.resizeNotifier?.removeListener("middlePanelResizedNoisy", this.onResize);
|
||||
}
|
||||
|
||||
private onScroll = (ev: Event | React.UIEvent): void => {
|
||||
private onScroll = (ev: Event): void => {
|
||||
// skip scroll events caused by resizing
|
||||
if (this.props.resizeNotifier && this.props.resizeNotifier.isResizing) return;
|
||||
debuglog("onScroll called past resize gate; scroll node top:", this.getScrollNode().scrollTop);
|
||||
this.scrollTimeout.restart();
|
||||
this.saveScrollState();
|
||||
this.updatePreventShrinking();
|
||||
this.props.onScroll?.(ev as Event);
|
||||
this.props.onScroll?.(ev);
|
||||
// noinspection JSIgnoredPromiseFromCall
|
||||
this.checkFillState();
|
||||
};
|
||||
|
@ -587,7 +587,7 @@ export default class ScrollPanel extends React.Component<IProps> {
|
|||
* Scroll up/down in response to a scroll key
|
||||
* @param {object} ev the keyboard event
|
||||
*/
|
||||
public handleScrollKey = (ev: KeyboardEvent) => {
|
||||
public handleScrollKey = (ev: KeyboardEvent): void => {
|
||||
const roomAction = getKeyBindingsManager().getRoomAction(ev);
|
||||
switch (roomAction) {
|
||||
case KeyBindingAction.ScrollUp:
|
||||
|
@ -853,7 +853,7 @@ export default class ScrollPanel extends React.Component<IProps> {
|
|||
return this.divScroll;
|
||||
}
|
||||
|
||||
private collectScroll = (divScroll: HTMLDivElement) => {
|
||||
private collectScroll = (divScroll: HTMLDivElement): void => {
|
||||
this.divScroll = divScroll;
|
||||
};
|
||||
|
||||
|
|
|
@ -114,12 +114,12 @@ const Tile: React.FC<ITileProps> = ({
|
|||
const [onFocus, isActive, ref] = useRovingTabIndex();
|
||||
const [busy, setBusy] = useState(false);
|
||||
|
||||
const onPreviewClick = (ev: ButtonEvent) => {
|
||||
const onPreviewClick = (ev: ButtonEvent): void => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
onViewRoomClick();
|
||||
};
|
||||
const onJoinClick = async (ev: ButtonEvent) => {
|
||||
const onJoinClick = async (ev: ButtonEvent): Promise<void> => {
|
||||
setBusy(true);
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
@ -271,7 +271,7 @@ const Tile: React.FC<ITileProps> = ({
|
|||
);
|
||||
|
||||
if (showChildren) {
|
||||
const onChildrenKeyDown = (e) => {
|
||||
const onChildrenKeyDown = (e): void => {
|
||||
const action = getKeyBindingsManager().getAccessibilityAction(e);
|
||||
switch (action) {
|
||||
case KeyBindingAction.ArrowLeft:
|
||||
|
@ -439,7 +439,7 @@ const toLocalRoom = (cli: MatrixClient, room: IHierarchyRoom): IHierarchyRoom =>
|
|||
return room;
|
||||
};
|
||||
|
||||
export const HierarchyLevel = ({
|
||||
export const HierarchyLevel: React.FC<IHierarchyLevelProps> = ({
|
||||
root,
|
||||
roomSet,
|
||||
hierarchy,
|
||||
|
@ -448,7 +448,7 @@ export const HierarchyLevel = ({
|
|||
onViewRoomClick,
|
||||
onJoinRoomClick,
|
||||
onToggleClick,
|
||||
}: IHierarchyLevelProps) => {
|
||||
}) => {
|
||||
const cli = useContext(MatrixClientContext);
|
||||
const space = cli.getRoom(root.room_id);
|
||||
const hasPermissions = space?.currentState.maySendStateEvent(EventType.SpaceChild, cli.getUserId());
|
||||
|
@ -553,7 +553,7 @@ export const useRoomHierarchy = (
|
|||
});
|
||||
|
||||
const loadMore = useCallback(
|
||||
async (pageSize?: number) => {
|
||||
async (pageSize?: number): Promise<void> => {
|
||||
if (hierarchy.loading || !hierarchy.canLoadMore || hierarchy.noSupport || error) return;
|
||||
await hierarchy.load(pageSize).catch(setError);
|
||||
setRooms(hierarchy.rooms);
|
||||
|
@ -578,8 +578,8 @@ export const useRoomHierarchy = (
|
|||
};
|
||||
};
|
||||
|
||||
const useIntersectionObserver = (callback: () => void) => {
|
||||
const handleObserver = (entries: IntersectionObserverEntry[]) => {
|
||||
const useIntersectionObserver = (callback: () => void): ((element: HTMLDivElement) => void) => {
|
||||
const handleObserver = (entries: IntersectionObserverEntry[]): void => {
|
||||
const target = entries[0];
|
||||
if (target.isIntersecting) {
|
||||
callback();
|
||||
|
@ -610,7 +610,7 @@ interface IManageButtonsProps {
|
|||
setError: Dispatch<SetStateAction<string>>;
|
||||
}
|
||||
|
||||
const ManageButtons = ({ hierarchy, selected, setSelected, setError }: IManageButtonsProps) => {
|
||||
const ManageButtons: React.FC<IManageButtonsProps> = ({ hierarchy, selected, setSelected, setError }) => {
|
||||
const cli = useContext(MatrixClientContext);
|
||||
|
||||
const [removing, setRemoving] = useState(false);
|
||||
|
@ -645,7 +645,7 @@ const ManageButtons = ({ hierarchy, selected, setSelected, setError }: IManageBu
|
|||
<>
|
||||
<Button
|
||||
{...props}
|
||||
onClick={async () => {
|
||||
onClick={async (): Promise<void> => {
|
||||
setRemoving(true);
|
||||
try {
|
||||
const userId = cli.getUserId();
|
||||
|
@ -680,7 +680,7 @@ const ManageButtons = ({ hierarchy, selected, setSelected, setError }: IManageBu
|
|||
</Button>
|
||||
<Button
|
||||
{...props}
|
||||
onClick={async () => {
|
||||
onClick={async (): Promise<void> => {
|
||||
setSaving(true);
|
||||
try {
|
||||
for (const [parentId, childId] of selectedRelations) {
|
||||
|
@ -713,7 +713,7 @@ const ManageButtons = ({ hierarchy, selected, setSelected, setError }: IManageBu
|
|||
);
|
||||
};
|
||||
|
||||
const SpaceHierarchy = ({ space, initialText = "", showRoom, additionalButtons }: IProps) => {
|
||||
const SpaceHierarchy: React.FC<IProps> = ({ space, initialText = "", showRoom, additionalButtons }) => {
|
||||
const cli = useContext(MatrixClientContext);
|
||||
const [query, setQuery] = useState(initialText);
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@ enum Phase {
|
|||
PrivateExistingRooms,
|
||||
}
|
||||
|
||||
const SpaceLandingAddButton = ({ space }) => {
|
||||
const SpaceLandingAddButton: React.FC<{ space: Room }> = ({ space }) => {
|
||||
const [menuDisplayed, handle, openMenu, closeMenu] = useContextMenu();
|
||||
const canCreateRoom = shouldShowComponent(UIComponent.CreateRooms);
|
||||
const canCreateSpace = shouldShowComponent(UIComponent.CreateSpaces);
|
||||
|
@ -128,7 +128,7 @@ const SpaceLandingAddButton = ({ space }) => {
|
|||
<IconizedContextMenuOption
|
||||
label={_t("New room")}
|
||||
iconClassName="mx_RoomList_iconNewRoom"
|
||||
onClick={async (e) => {
|
||||
onClick={async (e): Promise<void> => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
closeMenu();
|
||||
|
@ -143,7 +143,7 @@ const SpaceLandingAddButton = ({ space }) => {
|
|||
<IconizedContextMenuOption
|
||||
label={_t("New video room")}
|
||||
iconClassName="mx_RoomList_iconNewVideoRoom"
|
||||
onClick={async (e) => {
|
||||
onClick={async (e): Promise<void> => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
closeMenu();
|
||||
|
@ -210,7 +210,7 @@ const SpaceLandingAddButton = ({ space }) => {
|
|||
);
|
||||
};
|
||||
|
||||
const SpaceLanding = ({ space }: { space: Room }) => {
|
||||
const SpaceLanding: React.FC<{ space: Room }> = ({ space }) => {
|
||||
const cli = useContext(MatrixClientContext);
|
||||
const myMembership = useMyRoomMembership(space);
|
||||
const userId = cli.getUserId();
|
||||
|
@ -259,7 +259,7 @@ const SpaceLanding = ({ space }: { space: Room }) => {
|
|||
);
|
||||
}
|
||||
|
||||
const onMembersClick = () => {
|
||||
const onMembersClick = (): void => {
|
||||
RightPanelStore.instance.setCard({ phase: RightPanelPhases.SpaceMemberList });
|
||||
};
|
||||
|
||||
|
@ -297,7 +297,12 @@ const SpaceLanding = ({ space }: { space: Room }) => {
|
|||
);
|
||||
};
|
||||
|
||||
const SpaceSetupFirstRooms = ({ space, title, description, onFinished }) => {
|
||||
const SpaceSetupFirstRooms: React.FC<{
|
||||
space: Room;
|
||||
title: string;
|
||||
description: JSX.Element;
|
||||
onFinished(firstRoomId?: string): void;
|
||||
}> = ({ space, title, description, onFinished }) => {
|
||||
const [busy, setBusy] = useState(false);
|
||||
const [error, setError] = useState("");
|
||||
const numFields = 3;
|
||||
|
@ -321,7 +326,7 @@ const SpaceSetupFirstRooms = ({ space, title, description, onFinished }) => {
|
|||
);
|
||||
});
|
||||
|
||||
const onNextClick = async (ev: ButtonEvent) => {
|
||||
const onNextClick = async (ev: ButtonEvent): Promise<void> => {
|
||||
ev.preventDefault();
|
||||
if (busy) return;
|
||||
setError("");
|
||||
|
@ -354,7 +359,7 @@ const SpaceSetupFirstRooms = ({ space, title, description, onFinished }) => {
|
|||
setBusy(false);
|
||||
};
|
||||
|
||||
let onClick = (ev: ButtonEvent) => {
|
||||
let onClick = (ev: ButtonEvent): void => {
|
||||
ev.preventDefault();
|
||||
onFinished();
|
||||
};
|
||||
|
@ -389,7 +394,10 @@ const SpaceSetupFirstRooms = ({ space, title, description, onFinished }) => {
|
|||
);
|
||||
};
|
||||
|
||||
const SpaceAddExistingRooms = ({ space, onFinished }) => {
|
||||
const SpaceAddExistingRooms: React.FC<{
|
||||
space: Room;
|
||||
onFinished(): void;
|
||||
}> = ({ space, onFinished }) => {
|
||||
return (
|
||||
<div>
|
||||
<h1>{_t("What do you want to organise?")}</h1>
|
||||
|
@ -420,7 +428,12 @@ interface ISpaceSetupPublicShareProps extends Pick<IProps & IState, "justCreated
|
|||
onFinished(): void;
|
||||
}
|
||||
|
||||
const SpaceSetupPublicShare = ({ justCreatedOpts, space, onFinished, firstRoomId }: ISpaceSetupPublicShareProps) => {
|
||||
const SpaceSetupPublicShare: React.FC<ISpaceSetupPublicShareProps> = ({
|
||||
justCreatedOpts,
|
||||
space,
|
||||
onFinished,
|
||||
firstRoomId,
|
||||
}) => {
|
||||
return (
|
||||
<div className="mx_SpaceRoomView_publicShare">
|
||||
<h1>
|
||||
|
@ -443,7 +456,11 @@ const SpaceSetupPublicShare = ({ justCreatedOpts, space, onFinished, firstRoomId
|
|||
);
|
||||
};
|
||||
|
||||
const SpaceSetupPrivateScope = ({ space, justCreatedOpts, onFinished }) => {
|
||||
const SpaceSetupPrivateScope: React.FC<{
|
||||
space: Room;
|
||||
justCreatedOpts: IOpts;
|
||||
onFinished(createRooms: boolean): void;
|
||||
}> = ({ space, justCreatedOpts, onFinished }) => {
|
||||
return (
|
||||
<div className="mx_SpaceRoomView_privateScope">
|
||||
<h1>{_t("Who are you working with?")}</h1>
|
||||
|
@ -485,7 +502,10 @@ const validateEmailRules = withValidation({
|
|||
],
|
||||
});
|
||||
|
||||
const SpaceSetupPrivateInvite = ({ space, onFinished }) => {
|
||||
const SpaceSetupPrivateInvite: React.FC<{
|
||||
space: Room;
|
||||
onFinished(): void;
|
||||
}> = ({ space, onFinished }) => {
|
||||
const [busy, setBusy] = useState(false);
|
||||
const [error, setError] = useState("");
|
||||
const numFields = 3;
|
||||
|
@ -501,7 +521,7 @@ const SpaceSetupPrivateInvite = ({ space, onFinished }) => {
|
|||
label={_t("Email address")}
|
||||
placeholder={_t("Email")}
|
||||
value={emailAddresses[i]}
|
||||
onChange={(ev) => setEmailAddress(i, ev.target.value)}
|
||||
onChange={(ev: React.ChangeEvent<HTMLInputElement>) => setEmailAddress(i, ev.target.value)}
|
||||
ref={fieldRefs[i]}
|
||||
onValidate={validateEmailRules}
|
||||
autoFocus={i === 0}
|
||||
|
@ -510,7 +530,7 @@ const SpaceSetupPrivateInvite = ({ space, onFinished }) => {
|
|||
);
|
||||
});
|
||||
|
||||
const onNextClick = async (ev) => {
|
||||
const onNextClick = async (ev: ButtonEvent): Promise<void> => {
|
||||
ev.preventDefault();
|
||||
if (busy) return;
|
||||
setError("");
|
||||
|
@ -548,7 +568,7 @@ const SpaceSetupPrivateInvite = ({ space, onFinished }) => {
|
|||
setBusy(false);
|
||||
};
|
||||
|
||||
let onClick = (ev) => {
|
||||
let onClick = (ev: ButtonEvent): void => {
|
||||
ev.preventDefault();
|
||||
onFinished();
|
||||
};
|
||||
|
@ -642,29 +662,29 @@ export default class SpaceRoomView extends React.PureComponent<IProps, IState> {
|
|||
RightPanelStore.instance.on(UPDATE_EVENT, this.onRightPanelStoreUpdate);
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
public componentDidMount(): void {
|
||||
this.context.on(RoomEvent.MyMembership, this.onMyMembership);
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
public componentWillUnmount(): void {
|
||||
defaultDispatcher.unregister(this.dispatcherRef);
|
||||
RightPanelStore.instance.off(UPDATE_EVENT, this.onRightPanelStoreUpdate);
|
||||
this.context.off(RoomEvent.MyMembership, this.onMyMembership);
|
||||
}
|
||||
|
||||
private onMyMembership = (room: Room, myMembership: string) => {
|
||||
private onMyMembership = (room: Room, myMembership: string): void => {
|
||||
if (room.roomId === this.props.space.roomId) {
|
||||
this.setState({ myMembership });
|
||||
}
|
||||
};
|
||||
|
||||
private onRightPanelStoreUpdate = () => {
|
||||
private onRightPanelStoreUpdate = (): void => {
|
||||
this.setState({
|
||||
showRightPanel: RightPanelStore.instance.isOpenForRoom(this.props.space.roomId),
|
||||
});
|
||||
};
|
||||
|
||||
private onAction = (payload: ActionPayload) => {
|
||||
private onAction = (payload: ActionPayload): void => {
|
||||
if (payload.action === Action.ViewRoom && payload.room_id === this.props.space.roomId) {
|
||||
this.setState({ phase: Phase.Landing });
|
||||
return;
|
||||
|
@ -698,7 +718,7 @@ export default class SpaceRoomView extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
};
|
||||
|
||||
private goToFirstRoom = async () => {
|
||||
private goToFirstRoom = async (): Promise<void> => {
|
||||
if (this.state.firstRoomId) {
|
||||
defaultDispatcher.dispatch<ViewRoomPayload>({
|
||||
action: Action.ViewRoom,
|
||||
|
@ -711,7 +731,7 @@ export default class SpaceRoomView extends React.PureComponent<IProps, IState> {
|
|||
this.setState({ phase: Phase.Landing });
|
||||
};
|
||||
|
||||
private renderBody() {
|
||||
private renderBody(): JSX.Element {
|
||||
switch (this.state.phase) {
|
||||
case Phase.Landing:
|
||||
if (this.state.myMembership === "join") {
|
||||
|
@ -794,7 +814,7 @@ export default class SpaceRoomView extends React.PureComponent<IProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
public render() {
|
||||
public render(): JSX.Element {
|
||||
const rightPanel =
|
||||
this.state.showRightPanel && this.state.phase === Phase.Landing ? (
|
||||
<RightPanel room={this.props.space} resizeNotifier={this.props.resizeNotifier} />
|
||||
|
|
|
@ -19,7 +19,7 @@ interface Props extends DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLEleme
|
|||
children?: ReactNode;
|
||||
}
|
||||
|
||||
export default function SplashPage({ children, className, ...other }: Props) {
|
||||
export default function SplashPage({ children, className, ...other }: Props): JSX.Element {
|
||||
const classes = classNames(className, "mx_SplashPage");
|
||||
return (
|
||||
<main {...other} className={classes}>
|
||||
|
|
|
@ -86,7 +86,7 @@ export default class TabbedView extends React.Component<IProps, IState> {
|
|||
* @param {Tab} tab the tab to show
|
||||
* @private
|
||||
*/
|
||||
private setActiveTab(tab: Tab) {
|
||||
private setActiveTab(tab: Tab): void {
|
||||
// make sure this tab is still in available tabs
|
||||
if (!!this.getTabById(tab.id)) {
|
||||
if (this.props.onChange) this.props.onChange(tab.id);
|
||||
|
@ -96,7 +96,7 @@ export default class TabbedView extends React.Component<IProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
private renderTabLabel(tab: Tab) {
|
||||
private renderTabLabel(tab: Tab): JSX.Element {
|
||||
let classes = "mx_TabbedView_tabLabel ";
|
||||
|
||||
if (this.state.activeTabId === tab.id) classes += "mx_TabbedView_tabLabel_active";
|
||||
|
@ -106,7 +106,7 @@ export default class TabbedView extends React.Component<IProps, IState> {
|
|||
tabIcon = <span className={`mx_TabbedView_maskedIcon ${tab.icon}`} />;
|
||||
}
|
||||
|
||||
const onClickHandler = () => this.setActiveTab(tab);
|
||||
const onClickHandler = (): void => this.setActiveTab(tab);
|
||||
|
||||
const label = _t(tab.label);
|
||||
return (
|
||||
|
|
|
@ -61,15 +61,12 @@ type ThreadPanelHeaderOption = {
|
|||
key: ThreadFilterType;
|
||||
};
|
||||
|
||||
export const ThreadPanelHeaderFilterOptionItem = ({
|
||||
label,
|
||||
description,
|
||||
onClick,
|
||||
isSelected,
|
||||
}: ThreadPanelHeaderOption & {
|
||||
onClick: () => void;
|
||||
isSelected: boolean;
|
||||
}) => {
|
||||
export const ThreadPanelHeaderFilterOptionItem: React.FC<
|
||||
ThreadPanelHeaderOption & {
|
||||
onClick: () => void;
|
||||
isSelected: boolean;
|
||||
}
|
||||
> = ({ label, description, onClick, isSelected }) => {
|
||||
return (
|
||||
<MenuItemRadio active={isSelected} className="mx_ThreadPanel_Header_FilterOptionItem" onClick={onClick}>
|
||||
<span>{label}</span>
|
||||
|
@ -78,15 +75,11 @@ export const ThreadPanelHeaderFilterOptionItem = ({
|
|||
);
|
||||
};
|
||||
|
||||
export const ThreadPanelHeader = ({
|
||||
filterOption,
|
||||
setFilterOption,
|
||||
empty,
|
||||
}: {
|
||||
export const ThreadPanelHeader: React.FC<{
|
||||
filterOption: ThreadFilterType;
|
||||
setFilterOption: (filterOption: ThreadFilterType) => void;
|
||||
empty: boolean;
|
||||
}) => {
|
||||
}> = ({ filterOption, setFilterOption, empty }) => {
|
||||
const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu<HTMLElement>();
|
||||
const options: readonly ThreadPanelHeaderOption[] = [
|
||||
{
|
||||
|
|
|
@ -137,7 +137,7 @@ export default class ThreadView extends React.Component<IProps, IState> {
|
|||
});
|
||||
}
|
||||
|
||||
public componentDidUpdate(prevProps) {
|
||||
public componentDidUpdate(prevProps): void {
|
||||
if (prevProps.mxEvent !== this.props.mxEvent) {
|
||||
this.setupThread(this.props.mxEvent);
|
||||
}
|
||||
|
@ -192,7 +192,7 @@ export default class ThreadView extends React.Component<IProps, IState> {
|
|||
}
|
||||
};
|
||||
|
||||
private setupThread = (mxEv: MatrixEvent) => {
|
||||
private setupThread = (mxEv: MatrixEvent): void => {
|
||||
let thread = this.props.room.getThread(mxEv.getId());
|
||||
if (!thread) {
|
||||
thread = this.props.room.createThread(mxEv.getId(), mxEv, [mxEv], true);
|
||||
|
@ -200,7 +200,7 @@ export default class ThreadView extends React.Component<IProps, IState> {
|
|||
this.updateThread(thread);
|
||||
};
|
||||
|
||||
private onNewThread = (thread: Thread) => {
|
||||
private onNewThread = (thread: Thread): void => {
|
||||
if (thread.id === this.props.mxEvent.getId()) {
|
||||
this.setupThread(this.props.mxEvent);
|
||||
}
|
||||
|
@ -218,7 +218,7 @@ export default class ThreadView extends React.Component<IProps, IState> {
|
|||
});
|
||||
}
|
||||
|
||||
private updateThread = (thread?: Thread) => {
|
||||
private updateThread = (thread?: Thread): void => {
|
||||
if (this.state.thread === thread) return;
|
||||
|
||||
this.setupThreadListeners(thread, this.state.thread);
|
||||
|
@ -276,7 +276,7 @@ export default class ThreadView extends React.Component<IProps, IState> {
|
|||
this.setState({ narrow });
|
||||
};
|
||||
|
||||
private onKeyDown = (ev: KeyboardEvent) => {
|
||||
private onKeyDown = (ev: KeyboardEvent): void => {
|
||||
let handled = false;
|
||||
|
||||
const action = getKeyBindingsManager().getRoomAction(ev);
|
||||
|
@ -300,7 +300,7 @@ export default class ThreadView extends React.Component<IProps, IState> {
|
|||
}
|
||||
};
|
||||
|
||||
private onFileDrop = (dataTransfer: DataTransfer) => {
|
||||
private onFileDrop = (dataTransfer: DataTransfer): void => {
|
||||
const roomId = this.props.mxEvent.getRoomId();
|
||||
if (roomId) {
|
||||
ContentMessages.sharedInstance().sendContentListToRoom(
|
||||
|
|
|
@ -31,6 +31,7 @@ import { Thread, ThreadEvent } from "matrix-js-sdk/src/models/thread";
|
|||
import { ReceiptType } from "matrix-js-sdk/src/@types/read_receipts";
|
||||
import { MatrixError } from "matrix-js-sdk/src/http-api";
|
||||
import { ReadReceipt } from "matrix-js-sdk/src/models/read-receipt";
|
||||
import { Relations } from "matrix-js-sdk/src/models/relations";
|
||||
|
||||
import SettingsStore from "../../settings/SettingsStore";
|
||||
import { Layout } from "../../settings/enums/Layout";
|
||||
|
@ -67,7 +68,7 @@ const READ_MARKER_DEBOUNCE_MS = 100;
|
|||
// How far off-screen a decryption failure can be for it to still count as "visible"
|
||||
const VISIBLE_DECRYPTION_FAILURE_MARGIN = 100;
|
||||
|
||||
const debuglog = (...args: any[]) => {
|
||||
const debuglog = (...args: any[]): void => {
|
||||
if (SettingsStore.getValue("debug_timeline_panel")) {
|
||||
logger.log.call(console, "TimelinePanel debuglog:", ...args);
|
||||
}
|
||||
|
@ -315,7 +316,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
|||
this.props.timelineSet.room?.on(ThreadEvent.Update, this.onThreadUpdate);
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
public componentDidMount(): void {
|
||||
if (this.props.manageReadReceipts) {
|
||||
this.updateReadReceiptOnUserActivity();
|
||||
}
|
||||
|
@ -325,7 +326,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
|||
this.initTimeline(this.props);
|
||||
}
|
||||
|
||||
public componentDidUpdate(prevProps) {
|
||||
public componentDidUpdate(prevProps: Readonly<IProps>): void {
|
||||
if (prevProps.timelineSet !== this.props.timelineSet) {
|
||||
// throw new Error("changing timelineSet on a TimelinePanel is not supported");
|
||||
|
||||
|
@ -360,7 +361,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
public componentWillUnmount(): void {
|
||||
// set a boolean to say we've been unmounted, which any pending
|
||||
// promises can use to throw away their results.
|
||||
//
|
||||
|
@ -616,7 +617,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
|||
});
|
||||
};
|
||||
|
||||
private onMessageListScroll = (e) => {
|
||||
private onMessageListScroll = (e: Event): void => {
|
||||
this.props.onScroll?.(e);
|
||||
if (this.props.manageReadMarkers) {
|
||||
this.doManageReadMarkers();
|
||||
|
@ -777,7 +778,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
|||
}
|
||||
};
|
||||
|
||||
public canResetTimeline = () => this.messagePanel?.current?.isAtBottom();
|
||||
public canResetTimeline = (): boolean => this.messagePanel?.current?.isAtBottom();
|
||||
|
||||
private onRoomRedaction = (ev: MatrixEvent, room: Room): void => {
|
||||
if (this.unmounted) return;
|
||||
|
@ -1060,7 +1061,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
|||
this.state.readMarkerEventId ?? "",
|
||||
sendRRs ? lastReadEvent ?? undefined : undefined, // Public read receipt (could be null)
|
||||
lastReadEvent ?? undefined, // Private read receipt (could be null)
|
||||
).catch(async (e) => {
|
||||
).catch(async (e): Promise<void> => {
|
||||
// /read_markers API is not implemented on this HS, fallback to just RR
|
||||
if (e.errcode === "M_UNRECOGNIZED" && lastReadEvent) {
|
||||
if (
|
||||
|
@ -1070,10 +1071,11 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
|||
)
|
||||
return;
|
||||
try {
|
||||
return await cli.sendReadReceipt(
|
||||
await cli.sendReadReceipt(
|
||||
lastReadEvent,
|
||||
sendRRs ? ReceiptType.Read : ReceiptType.ReadPrivate,
|
||||
);
|
||||
return;
|
||||
} catch (error) {
|
||||
logger.error(e);
|
||||
this.lastRRSentEventId = undefined;
|
||||
|
@ -1314,7 +1316,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
|||
*
|
||||
* We pass it down to the scroll panel.
|
||||
*/
|
||||
public handleScrollKey = (ev) => {
|
||||
public handleScrollKey = (ev: React.KeyboardEvent): void => {
|
||||
if (!this.messagePanel.current) return;
|
||||
|
||||
// jump to the live timeline on ctrl-end, rather than the end of the
|
||||
|
@ -1342,7 +1344,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
|||
}
|
||||
|
||||
private scrollIntoView(eventId?: string, pixelOffset?: number, offsetBase?: number): void {
|
||||
const doScroll = () => {
|
||||
const doScroll = (): void => {
|
||||
if (!this.messagePanel.current) return;
|
||||
if (eventId) {
|
||||
debuglog(
|
||||
|
@ -1401,7 +1403,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
|||
? new TimelineWindow(cli, this.props.overlayTimelineSet, { windowLimit: this.props.timelineCap })
|
||||
: undefined;
|
||||
|
||||
const onLoaded = () => {
|
||||
const onLoaded = (): void => {
|
||||
if (this.unmounted) return;
|
||||
|
||||
// clear the timeline min-height when (re)loading the timeline
|
||||
|
@ -1441,7 +1443,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
|||
);
|
||||
};
|
||||
|
||||
const onError = (error: MatrixError) => {
|
||||
const onError = (error: MatrixError): void => {
|
||||
if (this.unmounted) return;
|
||||
|
||||
this.setState({ timelineLoading: false });
|
||||
|
@ -1504,7 +1506,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
|||
return;
|
||||
}
|
||||
|
||||
const prom = this.timelineWindow.load(eventId, INITIAL_SIZE).then(async () => {
|
||||
const prom = this.timelineWindow.load(eventId, INITIAL_SIZE).then(async (): Promise<void> => {
|
||||
if (this.overlayTimelineWindow) {
|
||||
// @TODO(kerrya) use timestampToEvent to load the overlay timeline
|
||||
// with more correct position when main TL eventId is truthy
|
||||
|
@ -1746,7 +1748,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
|||
const wrapperRect = messagePanelNode.getBoundingClientRect();
|
||||
const myUserId = MatrixClientPeg.get().credentials.userId;
|
||||
|
||||
const isNodeInView = (node: HTMLElement) => {
|
||||
const isNodeInView = (node: HTMLElement): boolean => {
|
||||
if (node) {
|
||||
const boundingRect = node.getBoundingClientRect();
|
||||
if (
|
||||
|
@ -1877,13 +1879,14 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
|||
eventId: string,
|
||||
relationType: RelationType | string,
|
||||
eventType: EventType | string,
|
||||
) => this.props.timelineSet.relations?.getChildEventsForEvent(eventId, relationType, eventType);
|
||||
): Relations | undefined =>
|
||||
this.props.timelineSet.relations?.getChildEventsForEvent(eventId, relationType, eventType);
|
||||
|
||||
private buildLegacyCallEventGroupers(events?: MatrixEvent[]): void {
|
||||
this.callEventGroupers = buildLegacyCallEventGroupers(this.callEventGroupers, events);
|
||||
}
|
||||
|
||||
public render() {
|
||||
public render(): JSX.Element {
|
||||
// just show a spinner while the timeline loads.
|
||||
//
|
||||
// put it in a div of the right class (mx_RoomView_messagePanel) so
|
||||
|
|
|
@ -39,18 +39,18 @@ export default class ToastContainer extends React.Component<{}, IState> {
|
|||
ToastStore.sharedInstance().on("update", this.onToastStoreUpdate);
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
public componentWillUnmount(): void {
|
||||
ToastStore.sharedInstance().removeListener("update", this.onToastStoreUpdate);
|
||||
}
|
||||
|
||||
private onToastStoreUpdate = () => {
|
||||
private onToastStoreUpdate = (): void => {
|
||||
this.setState({
|
||||
toasts: ToastStore.sharedInstance().getToasts(),
|
||||
countSeen: ToastStore.sharedInstance().getCountSeen(),
|
||||
});
|
||||
};
|
||||
|
||||
public render() {
|
||||
public render(): JSX.Element {
|
||||
const totalCount = this.state.toasts.length;
|
||||
const isStacked = totalCount > 1;
|
||||
let toast;
|
||||
|
|
|
@ -65,12 +65,12 @@ export default class UploadBar extends React.PureComponent<IProps, IState> {
|
|||
this.state = this.calculateState();
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
public componentDidMount(): void {
|
||||
this.dispatcherRef = dis.register(this.onAction);
|
||||
this.mounted = true;
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
public componentWillUnmount(): void {
|
||||
this.mounted = false;
|
||||
dis.unregister(this.dispatcherRef!);
|
||||
}
|
||||
|
@ -91,19 +91,19 @@ export default class UploadBar extends React.PureComponent<IProps, IState> {
|
|||
};
|
||||
}
|
||||
|
||||
private onAction = (payload: ActionPayload) => {
|
||||
private onAction = (payload: ActionPayload): void => {
|
||||
if (!this.mounted) return;
|
||||
if (isUploadPayload(payload)) {
|
||||
this.setState(this.calculateState());
|
||||
}
|
||||
};
|
||||
|
||||
private onCancelClick = (ev: ButtonEvent) => {
|
||||
private onCancelClick = (ev: ButtonEvent): void => {
|
||||
ev.preventDefault();
|
||||
ContentMessages.sharedInstance().cancelUpload(this.state.currentUpload!);
|
||||
};
|
||||
|
||||
public render() {
|
||||
public render(): JSX.Element {
|
||||
if (!this.state.currentFile) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ import defaultDispatcher from "../../dispatcher/dispatcher";
|
|||
import { ActionPayload } from "../../dispatcher/payloads";
|
||||
import { Action } from "../../dispatcher/actions";
|
||||
import { _t } from "../../languageHandler";
|
||||
import { ChevronFace, ContextMenuButton } from "./ContextMenu";
|
||||
import { ChevronFace, ContextMenuButton, MenuProps } from "./ContextMenu";
|
||||
import { UserTab } from "../views/dialogs/UserTab";
|
||||
import { OpenToTabPayload } from "../../dispatcher/payloads/OpenToTabPayload";
|
||||
import FeedbackDialog from "../views/dialogs/FeedbackDialog";
|
||||
|
@ -67,7 +67,7 @@ interface IState {
|
|||
showLiveAvatarAddon: boolean;
|
||||
}
|
||||
|
||||
const toRightOf = (rect: PartialDOMRect) => {
|
||||
const toRightOf = (rect: PartialDOMRect): MenuProps => {
|
||||
return {
|
||||
left: rect.width + rect.left + 8,
|
||||
top: rect.top,
|
||||
|
@ -75,7 +75,7 @@ const toRightOf = (rect: PartialDOMRect) => {
|
|||
};
|
||||
};
|
||||
|
||||
const below = (rect: PartialDOMRect) => {
|
||||
const below = (rect: PartialDOMRect): MenuProps => {
|
||||
return {
|
||||
left: rect.left,
|
||||
top: rect.top + rect.height,
|
||||
|
@ -118,7 +118,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
|||
});
|
||||
};
|
||||
|
||||
public componentDidMount() {
|
||||
public componentDidMount(): void {
|
||||
this.context.voiceBroadcastRecordingsStore.on(
|
||||
VoiceBroadcastRecordingsStoreEvent.CurrentChanged,
|
||||
this.onCurrentVoiceBroadcastRecordingChanged,
|
||||
|
@ -127,7 +127,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
|||
this.themeWatcherRef = SettingsStore.watchSetting("theme", null, this.onThemeChanged);
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
public componentWillUnmount(): void {
|
||||
if (this.themeWatcherRef) SettingsStore.unwatchSetting(this.themeWatcherRef);
|
||||
if (this.dndWatcherRef) SettingsStore.unwatchSetting(this.dndWatcherRef);
|
||||
if (this.dispatcherRef) defaultDispatcher.unregister(this.dispatcherRef);
|
||||
|
@ -163,26 +163,26 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
private onProfileUpdate = async () => {
|
||||
private onProfileUpdate = async (): Promise<void> => {
|
||||
// the store triggered an update, so force a layout update. We don't
|
||||
// have any state to store here for that to magically happen.
|
||||
this.forceUpdate();
|
||||
};
|
||||
|
||||
private onSelectedSpaceUpdate = async () => {
|
||||
private onSelectedSpaceUpdate = async (): Promise<void> => {
|
||||
this.setState({
|
||||
selectedSpace: SpaceStore.instance.activeSpaceRoom,
|
||||
});
|
||||
};
|
||||
|
||||
private onThemeChanged = () => {
|
||||
private onThemeChanged = (): void => {
|
||||
this.setState({
|
||||
isDarkTheme: this.isUserOnDarkTheme(),
|
||||
isHighContrast: this.isUserOnHighContrastTheme(),
|
||||
});
|
||||
};
|
||||
|
||||
private onAction = (payload: ActionPayload) => {
|
||||
private onAction = (payload: ActionPayload): void => {
|
||||
switch (payload.action) {
|
||||
case Action.ToggleUserMenu:
|
||||
if (this.state.contextMenuPosition) {
|
||||
|
@ -194,13 +194,13 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
|||
}
|
||||
};
|
||||
|
||||
private onOpenMenuClick = (ev: React.MouseEvent) => {
|
||||
private onOpenMenuClick = (ev: React.MouseEvent): void => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
this.setState({ contextMenuPosition: ev.currentTarget.getBoundingClientRect() });
|
||||
};
|
||||
|
||||
private onContextMenu = (ev: React.MouseEvent) => {
|
||||
private onContextMenu = (ev: React.MouseEvent): void => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
this.setState({
|
||||
|
@ -213,11 +213,11 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
|||
});
|
||||
};
|
||||
|
||||
private onCloseMenu = () => {
|
||||
private onCloseMenu = (): void => {
|
||||
this.setState({ contextMenuPosition: null });
|
||||
};
|
||||
|
||||
private onSwitchThemeClick = (ev: React.MouseEvent) => {
|
||||
private onSwitchThemeClick = (ev: React.MouseEvent): void => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
|
@ -236,7 +236,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
|||
SettingsStore.setValue("theme", null, SettingLevel.DEVICE, newTheme); // set at same level as Appearance tab
|
||||
};
|
||||
|
||||
private onSettingsOpen = (ev: ButtonEvent, tabId: string) => {
|
||||
private onSettingsOpen = (ev: ButtonEvent, tabId: string): void => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
|
@ -245,7 +245,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
|||
this.setState({ contextMenuPosition: null }); // also close the menu
|
||||
};
|
||||
|
||||
private onProvideFeedback = (ev: ButtonEvent) => {
|
||||
private onProvideFeedback = (ev: ButtonEvent): void => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
|
@ -253,7 +253,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
|||
this.setState({ contextMenuPosition: null }); // also close the menu
|
||||
};
|
||||
|
||||
private onSignOutClick = async (ev: ButtonEvent) => {
|
||||
private onSignOutClick = async (ev: ButtonEvent): Promise<void> => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
|
@ -268,17 +268,17 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
|||
this.setState({ contextMenuPosition: null }); // also close the menu
|
||||
};
|
||||
|
||||
private onSignInClick = () => {
|
||||
private onSignInClick = (): void => {
|
||||
defaultDispatcher.dispatch({ action: "start_login" });
|
||||
this.setState({ contextMenuPosition: null }); // also close the menu
|
||||
};
|
||||
|
||||
private onRegisterClick = () => {
|
||||
private onRegisterClick = (): void => {
|
||||
defaultDispatcher.dispatch({ action: "start_registration" });
|
||||
this.setState({ contextMenuPosition: null }); // also close the menu
|
||||
};
|
||||
|
||||
private onHomeClick = (ev: ButtonEvent) => {
|
||||
private onHomeClick = (ev: ButtonEvent): void => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
|
@ -429,7 +429,7 @@ export default class UserMenu extends React.Component<IProps, IState> {
|
|||
);
|
||||
};
|
||||
|
||||
public render() {
|
||||
public render(): JSX.Element {
|
||||
const avatarSize = 32; // should match border-radius of the avatar
|
||||
|
||||
const userId = MatrixClientPeg.get().getUserId();
|
||||
|
|
|
@ -57,7 +57,7 @@ export default class CompleteSecurity extends React.Component<IProps, IState> {
|
|||
store.stop();
|
||||
}
|
||||
|
||||
public render() {
|
||||
public render(): JSX.Element {
|
||||
const { phase, lostKeys } = this.state;
|
||||
let icon;
|
||||
let title;
|
||||
|
|
|
@ -27,7 +27,7 @@ interface IProps {
|
|||
}
|
||||
|
||||
export default class E2eSetup extends React.Component<IProps> {
|
||||
public render() {
|
||||
public render(): JSX.Element {
|
||||
return (
|
||||
<AuthPage>
|
||||
<CompleteSecurityBody>
|
||||
|
|
|
@ -110,11 +110,11 @@ export default class ForgotPassword extends React.Component<Props, State> {
|
|||
this.reset = new PasswordReset(this.props.serverConfig.hsUrl, this.props.serverConfig.isUrl);
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
public componentDidMount(): void {
|
||||
this.checkServerCapabilities(this.props.serverConfig);
|
||||
}
|
||||
|
||||
public componentDidUpdate(prevProps: Readonly<Props>) {
|
||||
public componentDidUpdate(prevProps: Readonly<Props>): void {
|
||||
if (
|
||||
prevProps.serverConfig.hsUrl !== this.props.serverConfig.hsUrl ||
|
||||
prevProps.serverConfig.isUrl !== this.props.serverConfig.isUrl
|
||||
|
@ -159,7 +159,7 @@ export default class ForgotPassword extends React.Component<Props, State> {
|
|||
});
|
||||
}
|
||||
|
||||
private async onPhaseEmailInputSubmit() {
|
||||
private async onPhaseEmailInputSubmit(): Promise<void> {
|
||||
this.phase = Phase.SendingEmail;
|
||||
|
||||
if (await this.sendVerificationMail()) {
|
||||
|
@ -213,7 +213,7 @@ export default class ForgotPassword extends React.Component<Props, State> {
|
|||
});
|
||||
}
|
||||
|
||||
private async onPhaseEmailSentSubmit() {
|
||||
private async onPhaseEmailSentSubmit(): Promise<void> {
|
||||
this.setState({
|
||||
phase: Phase.PasswordInput,
|
||||
});
|
||||
|
@ -288,7 +288,7 @@ export default class ForgotPassword extends React.Component<Props, State> {
|
|||
false,
|
||||
false,
|
||||
{
|
||||
onBeforeClose: async (reason?: string) => {
|
||||
onBeforeClose: async (reason?: string): Promise<boolean> => {
|
||||
if (reason === "backgroundClick") {
|
||||
// Modal dismissed by clicking the background.
|
||||
// Go one phase back.
|
||||
|
@ -342,7 +342,7 @@ export default class ForgotPassword extends React.Component<Props, State> {
|
|||
}
|
||||
};
|
||||
|
||||
private onInputChanged = (stateKey: string, ev: React.FormEvent<HTMLInputElement>) => {
|
||||
private onInputChanged = (stateKey: string, ev: React.FormEvent<HTMLInputElement>): void => {
|
||||
let value = ev.currentTarget.value;
|
||||
if (stateKey === "email") value = value.trim();
|
||||
this.setState({
|
||||
|
@ -460,7 +460,7 @@ export default class ForgotPassword extends React.Component<Props, State> {
|
|||
);
|
||||
}
|
||||
|
||||
public renderDone() {
|
||||
public renderDone(): JSX.Element {
|
||||
return (
|
||||
<>
|
||||
<CheckboxIcon className="mx_Icon mx_Icon_32 mx_Icon_accent" />
|
||||
|
@ -484,7 +484,7 @@ export default class ForgotPassword extends React.Component<Props, State> {
|
|||
);
|
||||
}
|
||||
|
||||
public render() {
|
||||
public render(): JSX.Element {
|
||||
let resetPasswordJsx: JSX.Element;
|
||||
|
||||
switch (this.state.phase) {
|
||||
|
|
|
@ -144,15 +144,15 @@ export default class LoginComponent extends React.PureComponent<IProps, IState>
|
|||
};
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
public componentDidMount(): void {
|
||||
this.initLoginLogic(this.props.serverConfig);
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
public componentWillUnmount(): void {
|
||||
this.unmounted = true;
|
||||
}
|
||||
|
||||
public componentDidUpdate(prevProps) {
|
||||
public componentDidUpdate(prevProps): void {
|
||||
if (
|
||||
prevProps.serverConfig.hsUrl !== this.props.serverConfig.hsUrl ||
|
||||
prevProps.serverConfig.isUrl !== this.props.serverConfig.isUrl
|
||||
|
@ -162,9 +162,9 @@ export default class LoginComponent extends React.PureComponent<IProps, IState>
|
|||
}
|
||||
}
|
||||
|
||||
public isBusy = () => this.state.busy || this.props.busy;
|
||||
public isBusy = (): boolean => this.state.busy || this.props.busy;
|
||||
|
||||
public onPasswordLogin = async (username, phoneCountry, phoneNumber, password) => {
|
||||
public onPasswordLogin = async (username, phoneCountry, phoneNumber, password): Promise<void> => {
|
||||
if (!this.state.serverIsAlive) {
|
||||
this.setState({ busy: true });
|
||||
// Do a quick liveliness check on the URLs
|
||||
|
@ -264,11 +264,11 @@ export default class LoginComponent extends React.PureComponent<IProps, IState>
|
|||
);
|
||||
};
|
||||
|
||||
public onUsernameChanged = (username) => {
|
||||
public onUsernameChanged = (username): void => {
|
||||
this.setState({ username: username });
|
||||
};
|
||||
|
||||
public onUsernameBlur = async (username) => {
|
||||
public onUsernameBlur = async (username): Promise<void> => {
|
||||
const doWellknownLookup = username[0] === "@";
|
||||
this.setState({
|
||||
username: username,
|
||||
|
@ -315,23 +315,23 @@ export default class LoginComponent extends React.PureComponent<IProps, IState>
|
|||
}
|
||||
};
|
||||
|
||||
public onPhoneCountryChanged = (phoneCountry) => {
|
||||
public onPhoneCountryChanged = (phoneCountry): void => {
|
||||
this.setState({ phoneCountry: phoneCountry });
|
||||
};
|
||||
|
||||
public onPhoneNumberChanged = (phoneNumber) => {
|
||||
public onPhoneNumberChanged = (phoneNumber): void => {
|
||||
this.setState({
|
||||
phoneNumber: phoneNumber,
|
||||
});
|
||||
};
|
||||
|
||||
public onRegisterClick = (ev) => {
|
||||
public onRegisterClick = (ev): void => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
this.props.onRegisterClick();
|
||||
};
|
||||
|
||||
public onTryRegisterClick = (ev) => {
|
||||
public onTryRegisterClick = (ev): void => {
|
||||
const hasPasswordFlow = this.state.flows?.find((flow) => flow.type === "m.login.password");
|
||||
const ssoFlow = this.state.flows?.find((flow) => flow.type === "m.login.sso" || flow.type === "m.login.cas");
|
||||
// If has no password flow but an SSO flow guess that the user wants to register with SSO.
|
||||
|
@ -352,7 +352,7 @@ export default class LoginComponent extends React.PureComponent<IProps, IState>
|
|||
}
|
||||
};
|
||||
|
||||
private async initLoginLogic({ hsUrl, isUrl }: ValidatedServerConfig) {
|
||||
private async initLoginLogic({ hsUrl, isUrl }: ValidatedServerConfig): Promise<void> {
|
||||
let isDefaultServer = false;
|
||||
if (
|
||||
this.props.serverConfig.isDefault &&
|
||||
|
@ -502,7 +502,7 @@ export default class LoginComponent extends React.PureComponent<IProps, IState>
|
|||
return errorText;
|
||||
}
|
||||
|
||||
public renderLoginComponentForFlows() {
|
||||
public renderLoginComponentForFlows(): JSX.Element {
|
||||
if (!this.state.flows) return null;
|
||||
|
||||
// this is the ideal order we want to show the flows in
|
||||
|
@ -519,7 +519,7 @@ export default class LoginComponent extends React.PureComponent<IProps, IState>
|
|||
);
|
||||
}
|
||||
|
||||
private renderPasswordStep = () => {
|
||||
private renderPasswordStep = (): JSX.Element => {
|
||||
return (
|
||||
<PasswordLogin
|
||||
onSubmit={this.onPasswordLogin}
|
||||
|
@ -539,7 +539,7 @@ export default class LoginComponent extends React.PureComponent<IProps, IState>
|
|||
);
|
||||
};
|
||||
|
||||
private renderSsoStep = (loginType) => {
|
||||
private renderSsoStep = (loginType): JSX.Element => {
|
||||
const flow = this.state.flows.find((flow) => flow.type === "m.login." + loginType) as ISSOFlow;
|
||||
|
||||
return (
|
||||
|
@ -553,7 +553,7 @@ export default class LoginComponent extends React.PureComponent<IProps, IState>
|
|||
);
|
||||
};
|
||||
|
||||
public render() {
|
||||
public render(): JSX.Element {
|
||||
const loader =
|
||||
this.isBusy() && !this.state.busyLoggingIn ? (
|
||||
<div className="mx_Login_loader">
|
||||
|
|
|
@ -14,9 +14,9 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { AuthType, createClient, IAuthData } from "matrix-js-sdk/src/matrix";
|
||||
import { AuthType, createClient, IAuthData, IInputs } from "matrix-js-sdk/src/matrix";
|
||||
import React, { Fragment, ReactNode } from "react";
|
||||
import { MatrixClient } from "matrix-js-sdk/src/client";
|
||||
import { IRequestTokenResponse, MatrixClient } from "matrix-js-sdk/src/client";
|
||||
import classNames from "classnames";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { ISSOFlow } from "matrix-js-sdk/src/@types/auth";
|
||||
|
@ -32,7 +32,7 @@ import dis from "../../../dispatcher/dispatcher";
|
|||
import SSOButtons from "../../views/elements/SSOButtons";
|
||||
import ServerPicker from "../../views/elements/ServerPicker";
|
||||
import RegistrationForm from "../../views/auth/RegistrationForm";
|
||||
import AccessibleButton from "../../views/elements/AccessibleButton";
|
||||
import AccessibleButton, { ButtonEvent } from "../../views/elements/AccessibleButton";
|
||||
import AuthBody from "../../views/auth/AuthBody";
|
||||
import AuthHeader from "../../views/auth/AuthHeader";
|
||||
import InteractiveAuth, { InteractiveAuthCallback } from "../InteractiveAuth";
|
||||
|
@ -42,7 +42,7 @@ import { AuthHeaderProvider } from "./header/AuthHeaderProvider";
|
|||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import { ValidatedServerConfig } from "../../../utils/ValidatedServerConfig";
|
||||
|
||||
const debuglog = (...args: any[]) => {
|
||||
const debuglog = (...args: any[]): void => {
|
||||
if (SettingsStore.getValue("debug_registration")) {
|
||||
logger.log.call(console, "Registration debuglog:", ...args);
|
||||
}
|
||||
|
@ -148,17 +148,17 @@ export default class Registration extends React.Component<IProps, IState> {
|
|||
});
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
public componentDidMount(): void {
|
||||
this.replaceClient(this.props.serverConfig);
|
||||
//triggers a confirmation dialog for data loss before page unloads/refreshes
|
||||
window.addEventListener("beforeunload", this.unloadCallback);
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
public componentWillUnmount(): void {
|
||||
window.removeEventListener("beforeunload", this.unloadCallback);
|
||||
}
|
||||
|
||||
private unloadCallback = (event: BeforeUnloadEvent) => {
|
||||
private unloadCallback = (event: BeforeUnloadEvent): string => {
|
||||
if (this.state.doingUIAuth) {
|
||||
event.preventDefault();
|
||||
event.returnValue = "";
|
||||
|
@ -166,7 +166,7 @@ export default class Registration extends React.Component<IProps, IState> {
|
|||
}
|
||||
};
|
||||
|
||||
public componentDidUpdate(prevProps) {
|
||||
public componentDidUpdate(prevProps): void {
|
||||
if (
|
||||
prevProps.serverConfig.hsUrl !== this.props.serverConfig.hsUrl ||
|
||||
prevProps.serverConfig.isUrl !== this.props.serverConfig.isUrl
|
||||
|
@ -175,7 +175,7 @@ export default class Registration extends React.Component<IProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
private async replaceClient(serverConfig: ValidatedServerConfig) {
|
||||
private async replaceClient(serverConfig: ValidatedServerConfig): Promise<void> {
|
||||
this.latestServerConfig = serverConfig;
|
||||
const { hsUrl, isUrl } = serverConfig;
|
||||
|
||||
|
@ -283,7 +283,12 @@ export default class Registration extends React.Component<IProps, IState> {
|
|||
});
|
||||
};
|
||||
|
||||
private requestEmailToken = (emailAddress, clientSecret, sendAttempt, sessionId) => {
|
||||
private requestEmailToken = (
|
||||
emailAddress: string,
|
||||
clientSecret: string,
|
||||
sendAttempt: number,
|
||||
sessionId: string,
|
||||
): Promise<IRequestTokenResponse> => {
|
||||
return this.state.matrixClient.requestRegisterEmailToken(
|
||||
emailAddress,
|
||||
clientSecret,
|
||||
|
@ -297,10 +302,10 @@ export default class Registration extends React.Component<IProps, IState> {
|
|||
);
|
||||
};
|
||||
|
||||
private onUIAuthFinished: InteractiveAuthCallback = async (success, response) => {
|
||||
private onUIAuthFinished: InteractiveAuthCallback = async (success, response): Promise<void> => {
|
||||
debuglog("Registration: ui authentication finished: ", { success, response });
|
||||
if (!success) {
|
||||
let errorText: ReactNode = response.message || response.toString();
|
||||
let errorText: ReactNode = (response as Error).message || (response as Error).toString();
|
||||
// can we give a better error message?
|
||||
if (response.errcode === "M_RESOURCE_LIMIT_EXCEEDED") {
|
||||
const errorTop = messageForResourceLimitError(response.data.limit_type, response.data.admin_contact, {
|
||||
|
@ -404,7 +409,7 @@ export default class Registration extends React.Component<IProps, IState> {
|
|||
this.setState(newState);
|
||||
};
|
||||
|
||||
private setupPushers() {
|
||||
private setupPushers(): Promise<void> {
|
||||
if (!this.props.brand) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
@ -433,13 +438,13 @@ export default class Registration extends React.Component<IProps, IState> {
|
|||
);
|
||||
}
|
||||
|
||||
private onLoginClick = (ev) => {
|
||||
private onLoginClick = (ev: ButtonEvent): void => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
this.props.onLoginClick();
|
||||
};
|
||||
|
||||
private onGoToFormClicked = (ev) => {
|
||||
private onGoToFormClicked = (ev: ButtonEvent): void => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
this.replaceClient(this.props.serverConfig);
|
||||
|
@ -449,7 +454,7 @@ export default class Registration extends React.Component<IProps, IState> {
|
|||
});
|
||||
};
|
||||
|
||||
private makeRegisterRequest = (auth: IAuthData | null) => {
|
||||
private makeRegisterRequest = (auth: IAuthData | null): Promise<IAuthData> => {
|
||||
const registerParams = {
|
||||
username: this.state.formVals.username,
|
||||
password: this.state.formVals.password,
|
||||
|
@ -464,7 +469,7 @@ export default class Registration extends React.Component<IProps, IState> {
|
|||
return this.state.matrixClient.registerRequest(registerParams);
|
||||
};
|
||||
|
||||
private getUIAuthInputs() {
|
||||
private getUIAuthInputs(): IInputs {
|
||||
return {
|
||||
emailAddress: this.state.formVals.email,
|
||||
phoneCountry: this.state.formVals.phoneCountry,
|
||||
|
@ -475,7 +480,7 @@ export default class Registration extends React.Component<IProps, IState> {
|
|||
// Links to the login page shown after registration is completed are routed through this
|
||||
// which checks the user hasn't already logged in somewhere else (perhaps we should do
|
||||
// this more generally?)
|
||||
private onLoginClickWithCheck = async (ev) => {
|
||||
private onLoginClickWithCheck = async (ev: ButtonEvent): Promise<boolean> => {
|
||||
ev.preventDefault();
|
||||
|
||||
const sessionLoaded = await Lifecycle.loadSession({ ignoreGuest: true });
|
||||
|
@ -487,7 +492,7 @@ export default class Registration extends React.Component<IProps, IState> {
|
|||
return sessionLoaded;
|
||||
};
|
||||
|
||||
private renderRegisterComponent() {
|
||||
private renderRegisterComponent(): JSX.Element {
|
||||
if (this.state.matrixClient && this.state.doingUIAuth) {
|
||||
return (
|
||||
<InteractiveAuth
|
||||
|
@ -565,7 +570,7 @@ export default class Registration extends React.Component<IProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
public render() {
|
||||
public render(): JSX.Element {
|
||||
let errorText;
|
||||
const err = this.state.errorText;
|
||||
if (err) {
|
||||
|
@ -627,7 +632,7 @@ export default class Registration extends React.Component<IProps, IState> {
|
|||
<p>
|
||||
<AccessibleButton
|
||||
kind="link_inline"
|
||||
onClick={async (event) => {
|
||||
onClick={async (event: ButtonEvent): Promise<void> => {
|
||||
const sessionLoaded = await this.onLoginClickWithCheck(event);
|
||||
if (sessionLoaded) {
|
||||
dis.dispatch({ action: "view_welcome_page" });
|
||||
|
@ -651,7 +656,7 @@ export default class Registration extends React.Component<IProps, IState> {
|
|||
a: (sub) => (
|
||||
<AccessibleButton
|
||||
kind="link_inline"
|
||||
onClick={async (event) => {
|
||||
onClick={async (event: ButtonEvent): Promise<void> => {
|
||||
const sessionLoaded = await this.onLoginClickWithCheck(event);
|
||||
if (sessionLoaded) {
|
||||
dis.dispatch({ action: "view_home_page" });
|
||||
|
|
|
@ -61,7 +61,7 @@ export default class SetupEncryptionBody extends React.Component<IProps, IState>
|
|||
};
|
||||
}
|
||||
|
||||
private onStoreUpdate = () => {
|
||||
private onStoreUpdate = (): void => {
|
||||
const store = SetupEncryptionStore.sharedInstance();
|
||||
if (store.phase === Phase.Finished) {
|
||||
this.props.onFinished();
|
||||
|
@ -75,18 +75,18 @@ export default class SetupEncryptionBody extends React.Component<IProps, IState>
|
|||
});
|
||||
};
|
||||
|
||||
public componentWillUnmount() {
|
||||
public componentWillUnmount(): void {
|
||||
const store = SetupEncryptionStore.sharedInstance();
|
||||
store.off("update", this.onStoreUpdate);
|
||||
store.stop();
|
||||
}
|
||||
|
||||
private onUsePassphraseClick = async () => {
|
||||
private onUsePassphraseClick = async (): Promise<void> => {
|
||||
const store = SetupEncryptionStore.sharedInstance();
|
||||
store.usePassPhrase();
|
||||
};
|
||||
|
||||
private onVerifyClick = () => {
|
||||
private onVerifyClick = (): void => {
|
||||
const cli = MatrixClientPeg.get();
|
||||
const userId = cli.getUserId();
|
||||
const requestPromise = cli.requestVerification(userId);
|
||||
|
@ -97,7 +97,7 @@ export default class SetupEncryptionBody extends React.Component<IProps, IState>
|
|||
Modal.createDialog(VerificationRequestDialog, {
|
||||
verificationRequestPromise: requestPromise,
|
||||
member: cli.getUser(userId),
|
||||
onFinished: async () => {
|
||||
onFinished: async (): Promise<void> => {
|
||||
const request = await requestPromise;
|
||||
request.cancel();
|
||||
this.props.onFinished();
|
||||
|
@ -105,43 +105,43 @@ export default class SetupEncryptionBody extends React.Component<IProps, IState>
|
|||
});
|
||||
};
|
||||
|
||||
private onSkipConfirmClick = () => {
|
||||
private onSkipConfirmClick = (): void => {
|
||||
const store = SetupEncryptionStore.sharedInstance();
|
||||
store.skipConfirm();
|
||||
};
|
||||
|
||||
private onSkipBackClick = () => {
|
||||
private onSkipBackClick = (): void => {
|
||||
const store = SetupEncryptionStore.sharedInstance();
|
||||
store.returnAfterSkip();
|
||||
};
|
||||
|
||||
private onResetClick = (ev: React.MouseEvent<HTMLButtonElement>) => {
|
||||
private onResetClick = (ev: React.MouseEvent<HTMLButtonElement>): void => {
|
||||
ev.preventDefault();
|
||||
const store = SetupEncryptionStore.sharedInstance();
|
||||
store.reset();
|
||||
};
|
||||
|
||||
private onResetConfirmClick = () => {
|
||||
private onResetConfirmClick = (): void => {
|
||||
this.props.onFinished();
|
||||
const store = SetupEncryptionStore.sharedInstance();
|
||||
store.resetConfirm();
|
||||
};
|
||||
|
||||
private onResetBackClick = () => {
|
||||
private onResetBackClick = (): void => {
|
||||
const store = SetupEncryptionStore.sharedInstance();
|
||||
store.returnAfterReset();
|
||||
};
|
||||
|
||||
private onDoneClick = () => {
|
||||
private onDoneClick = (): void => {
|
||||
const store = SetupEncryptionStore.sharedInstance();
|
||||
store.done();
|
||||
};
|
||||
|
||||
private onEncryptionPanelClose = () => {
|
||||
private onEncryptionPanelClose = (): void => {
|
||||
this.props.onFinished();
|
||||
};
|
||||
|
||||
public render() {
|
||||
public render(): JSX.Element {
|
||||
const { phase, lostKeys } = this.state;
|
||||
|
||||
if (this.state.verificationRequest) {
|
||||
|
|
|
@ -101,7 +101,7 @@ export default class SoftLogout extends React.Component<IProps, IState> {
|
|||
}
|
||||
}
|
||||
|
||||
private onClearAll = () => {
|
||||
private onClearAll = (): void => {
|
||||
Modal.createDialog(ConfirmWipeDeviceDialog, {
|
||||
onFinished: (wipeData) => {
|
||||
if (!wipeData) return;
|
||||
|
@ -112,7 +112,7 @@ export default class SoftLogout extends React.Component<IProps, IState> {
|
|||
});
|
||||
};
|
||||
|
||||
private async initLogin() {
|
||||
private async initLogin(): Promise<void> {
|
||||
const queryParams = this.props.realQueryParams;
|
||||
const hasAllParams = queryParams && queryParams["loginToken"];
|
||||
if (hasAllParams) {
|
||||
|
@ -133,15 +133,15 @@ export default class SoftLogout extends React.Component<IProps, IState> {
|
|||
this.setState({ flows, loginView: chosenView });
|
||||
}
|
||||
|
||||
private onPasswordChange = (ev) => {
|
||||
private onPasswordChange = (ev): void => {
|
||||
this.setState({ password: ev.target.value });
|
||||
};
|
||||
|
||||
private onForgotPassword = () => {
|
||||
private onForgotPassword = (): void => {
|
||||
dis.dispatch({ action: "start_password_recovery" });
|
||||
};
|
||||
|
||||
private onPasswordLogin = async (ev) => {
|
||||
private onPasswordLogin = async (ev): Promise<void> => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
|
@ -181,7 +181,7 @@ export default class SoftLogout extends React.Component<IProps, IState> {
|
|||
});
|
||||
};
|
||||
|
||||
private async trySsoLogin() {
|
||||
private async trySsoLogin(): Promise<void> {
|
||||
this.setState({ busy: true });
|
||||
|
||||
const hsUrl = localStorage.getItem(SSO_HOMESERVER_URL_KEY);
|
||||
|
@ -261,7 +261,7 @@ export default class SoftLogout extends React.Component<IProps, IState> {
|
|||
);
|
||||
}
|
||||
|
||||
private renderSignInSection() {
|
||||
private renderSignInSection(): JSX.Element {
|
||||
if (this.state.loginView === LoginView.Loading) {
|
||||
return <Spinner />;
|
||||
}
|
||||
|
@ -325,7 +325,7 @@ export default class SoftLogout extends React.Component<IProps, IState> {
|
|||
);
|
||||
}
|
||||
|
||||
public render() {
|
||||
public render(): JSX.Element {
|
||||
return (
|
||||
<AuthPage>
|
||||
<AuthHeader />
|
||||
|
|
|
@ -50,7 +50,7 @@ export const EnterEmail: React.FC<EnterEmailProps> = ({
|
|||
|
||||
const emailFieldRef = useRef<Field>(null);
|
||||
|
||||
const onSubmit = async (event: React.FormEvent) => {
|
||||
const onSubmit = async (event: React.FormEvent): Promise<void> => {
|
||||
if (await emailFieldRef.current?.validate({ allowEmpty: false })) {
|
||||
onSubmitForm(event);
|
||||
return;
|
||||
|
|
|
@ -24,7 +24,7 @@ interface Props {
|
|||
serverPicker: ReactNode;
|
||||
}
|
||||
|
||||
export function AuthHeaderDisplay({ title, icon, serverPicker, children }: PropsWithChildren<Props>) {
|
||||
export function AuthHeaderDisplay({ title, icon, serverPicker, children }: PropsWithChildren<Props>): JSX.Element {
|
||||
const context = useContext(AuthHeaderContext);
|
||||
if (!context) {
|
||||
return null;
|
||||
|
|
|
@ -25,7 +25,7 @@ interface Props {
|
|||
hideServerPicker?: boolean;
|
||||
}
|
||||
|
||||
export function AuthHeaderModifier(props: Props) {
|
||||
export function AuthHeaderModifier(props: Props): null {
|
||||
const context = useContext(AuthHeaderContext);
|
||||
const dispatch = context ? context.dispatch : null;
|
||||
useEffect(() => {
|
||||
|
|
|
@ -32,7 +32,7 @@ interface AuthHeaderAction {
|
|||
|
||||
export type AuthHeaderReducer = Reducer<ComponentProps<typeof AuthHeaderModifier>[], AuthHeaderAction>;
|
||||
|
||||
export function AuthHeaderProvider({ children }: PropsWithChildren<{}>) {
|
||||
export function AuthHeaderProvider({ children }: PropsWithChildren<{}>): JSX.Element {
|
||||
const [state, dispatch] = useReducer<AuthHeaderReducer>(
|
||||
(state: ComponentProps<typeof AuthHeaderModifier>[], action: AuthHeaderAction) => {
|
||||
switch (action.type) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue