Conform more of the codebase to strictNullChecks
(#10602)
* Conform more of the codebase to `strictNullChecks` * Conform more of the codebase to `strictNullChecks` * Fix types
This commit is contained in:
parent
93858813a3
commit
daad630827
26 changed files with 79 additions and 49 deletions
|
@ -39,7 +39,7 @@ export interface ICompletion {
|
||||||
type?: "at-room" | "command" | "community" | "room" | "user";
|
type?: "at-room" | "command" | "community" | "room" | "user";
|
||||||
completion: string;
|
completion: string;
|
||||||
completionId?: string;
|
completionId?: string;
|
||||||
component?: ReactElement;
|
component: ReactElement;
|
||||||
range: ISelectionRange;
|
range: ISelectionRange;
|
||||||
command?: string;
|
command?: string;
|
||||||
suffix?: string;
|
suffix?: string;
|
||||||
|
|
|
@ -231,7 +231,7 @@ class LoggedInView extends React.Component<IProps, IState> {
|
||||||
};
|
};
|
||||||
|
|
||||||
private createResizer(): Resizer {
|
private createResizer(): Resizer {
|
||||||
let panelSize: number;
|
let panelSize: number | null;
|
||||||
let panelCollapsed: boolean;
|
let panelCollapsed: boolean;
|
||||||
const collapseConfig: ICollapseConfig = {
|
const collapseConfig: ICollapseConfig = {
|
||||||
// TODO decrease this once Spaces launches as it'll no longer need to include the 56px Community Panel
|
// TODO decrease this once Spaces launches as it'll no longer need to include the 56px Community Panel
|
||||||
|
|
|
@ -110,6 +110,7 @@ export default class RoomAvatar extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
private onRoomAvatarClick = (): void => {
|
private onRoomAvatarClick = (): void => {
|
||||||
const avatarUrl = Avatar.avatarUrlForRoom(this.props.room ?? null, undefined, undefined, undefined);
|
const avatarUrl = Avatar.avatarUrlForRoom(this.props.room ?? null, undefined, undefined, undefined);
|
||||||
|
if (!avatarUrl) return;
|
||||||
const params = {
|
const params = {
|
||||||
src: avatarUrl,
|
src: avatarUrl,
|
||||||
name: this.props.room?.name,
|
name: this.props.room?.name,
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { RefObject, useRef, useState } from "react";
|
import React, { useRef, useState } from "react";
|
||||||
import { Room } from "matrix-js-sdk/src/models/room";
|
import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
import { JoinRule } from "matrix-js-sdk/src/@types/partials";
|
import { JoinRule } from "matrix-js-sdk/src/@types/partials";
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
@ -41,9 +41,9 @@ const CreateSubspaceDialog: React.FC<IProps> = ({ space, onAddExistingSpaceClick
|
||||||
|
|
||||||
const [busy, setBusy] = useState<boolean>(false);
|
const [busy, setBusy] = useState<boolean>(false);
|
||||||
const [name, setName] = useState("");
|
const [name, setName] = useState("");
|
||||||
const spaceNameField = useRef() as RefObject<Field>;
|
const spaceNameField = useRef<Field>(null);
|
||||||
const [alias, setAlias] = useState("");
|
const [alias, setAlias] = useState("");
|
||||||
const spaceAliasField = useRef() as RefObject<RoomAliasField>;
|
const spaceAliasField = useRef<RoomAliasField>(null);
|
||||||
const [avatar, setAvatar] = useState<File | undefined>();
|
const [avatar, setAvatar] = useState<File | undefined>();
|
||||||
const [topic, setTopic] = useState<string>("");
|
const [topic, setTopic] = useState<string>("");
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useRef, useState, Dispatch, SetStateAction, RefObject } from "react";
|
import React, { useRef, useState, Dispatch, SetStateAction } from "react";
|
||||||
import { Room } from "matrix-js-sdk/src/matrix";
|
import { Room } from "matrix-js-sdk/src/matrix";
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
|
||||||
|
@ -104,8 +104,8 @@ const ExportDialog: React.FC<IProps> = ({ room, onFinished }) => {
|
||||||
} = useExportFormState();
|
} = useExportFormState();
|
||||||
|
|
||||||
const [isExporting, setExporting] = useState(false);
|
const [isExporting, setExporting] = useState(false);
|
||||||
const sizeLimitRef = useRef() as RefObject<Field>;
|
const sizeLimitRef = useRef<Field>(null);
|
||||||
const messageCountRef = useRef() as RefObject<Field>;
|
const messageCountRef = useRef<Field>(null);
|
||||||
const [exportProgressText, setExportProgressText] = useState(_t("Processing…"));
|
const [exportProgressText, setExportProgressText] = useState(_t("Processing…"));
|
||||||
const [displayCancel, setCancelWarning] = useState(false);
|
const [displayCancel, setCancelWarning] = useState(false);
|
||||||
const [exportCancelled, setExportCancelled] = useState(false);
|
const [exportCancelled, setExportCancelled] = useState(false);
|
||||||
|
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { RefObject, SyntheticEvent, useRef, useState } from "react";
|
import { SyntheticEvent, useRef, useState } from "react";
|
||||||
|
|
||||||
import { _t, _td } from "../../../languageHandler";
|
import { _t, _td } from "../../../languageHandler";
|
||||||
import Field from "../elements/Field";
|
import Field from "../elements/Field";
|
||||||
|
@ -30,7 +30,7 @@ interface IProps {
|
||||||
|
|
||||||
const RegistrationEmailPromptDialog: React.FC<IProps> = ({ onFinished }) => {
|
const RegistrationEmailPromptDialog: React.FC<IProps> = ({ onFinished }) => {
|
||||||
const [email, setEmail] = useState("");
|
const [email, setEmail] = useState("");
|
||||||
const fieldRef = useRef() as RefObject<Field>;
|
const fieldRef = useRef<Field>(null);
|
||||||
|
|
||||||
const onSubmit = async (e: SyntheticEvent): Promise<void> => {
|
const onSubmit = async (e: SyntheticEvent): Promise<void> => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
|
@ -255,7 +255,7 @@ export default class ReportEventDialog extends React.Component<IProps, IState> {
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// Report to homeserver admin through the dedicated Matrix API.
|
// Report to homeserver admin through the dedicated Matrix API.
|
||||||
await client.reportEvent(ev.getRoomId(), ev.getId(), -100, this.state.reason.trim());
|
await client.reportEvent(ev.getRoomId()!, ev.getId()!, -100, this.state.reason.trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the user should also be ignored, do that
|
// if the user should also be ignored, do that
|
||||||
|
@ -340,7 +340,7 @@ export default class ReportEventDialog extends React.Component<IProps, IState> {
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case NonStandardValue.Admin:
|
case NonStandardValue.Admin:
|
||||||
if (client.isRoomEncrypted(this.props.mxEvent.getRoomId())) {
|
if (client.isRoomEncrypted(this.props.mxEvent.getRoomId()!)) {
|
||||||
subtitle = _t(
|
subtitle = _t(
|
||||||
"This room is dedicated to illegal or toxic content " +
|
"This room is dedicated to illegal or toxic content " +
|
||||||
"or the moderators fail to moderate illegal or toxic content.\n" +
|
"or the moderators fail to moderate illegal or toxic content.\n" +
|
||||||
|
|
|
@ -288,8 +288,8 @@ interface IDirectoryOpts {
|
||||||
}
|
}
|
||||||
|
|
||||||
const SpotlightDialog: React.FC<IProps> = ({ initialText = "", initialFilter = null, onFinished }) => {
|
const SpotlightDialog: React.FC<IProps> = ({ initialText = "", initialFilter = null, onFinished }) => {
|
||||||
const inputRef = useRef() as RefObject<HTMLInputElement>;
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
const scrollContainerRef = useRef() as RefObject<HTMLDivElement>;
|
const scrollContainerRef = useRef<HTMLDivElement>(null);
|
||||||
const cli = MatrixClientPeg.get();
|
const cli = MatrixClientPeg.get();
|
||||||
const rovingContext = useContext(RovingTabIndexContext);
|
const rovingContext = useContext(RovingTabIndexContext);
|
||||||
const [query, _setQuery] = useState(initialText);
|
const [query, _setQuery] = useState(initialText);
|
||||||
|
|
|
@ -16,7 +16,7 @@ limitations under the License.
|
||||||
|
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { EventType } from "matrix-js-sdk/src/@types/event";
|
import { EventType } from "matrix-js-sdk/src/@types/event";
|
||||||
import React, { useContext, useRef, useState, MouseEvent, ReactNode, RefObject } from "react";
|
import React, { useContext, useRef, useState, MouseEvent, ReactNode } from "react";
|
||||||
|
|
||||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||||
import RoomContext from "../../../contexts/RoomContext";
|
import RoomContext from "../../../contexts/RoomContext";
|
||||||
|
@ -59,7 +59,7 @@ const MiniAvatarUploader: React.FC<IProps> = ({
|
||||||
setShow(false);
|
setShow(false);
|
||||||
}, 13000); // hide after being shown for 10 seconds
|
}, 13000); // hide after being shown for 10 seconds
|
||||||
|
|
||||||
const uploadRef = useRef() as RefObject<HTMLInputElement>;
|
const uploadRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
const label = hasAvatar || busy ? hasAvatarLabel : noAvatarLabel;
|
const label = hasAvatar || busy ? hasAvatarLabel : noAvatarLabel;
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { RefObject, useCallback, useContext, useRef } from "react";
|
import React, { useCallback, useContext, useRef } from "react";
|
||||||
import { Room } from "matrix-js-sdk/src/models/room";
|
import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { EventType } from "matrix-js-sdk/src/@types/event";
|
import { EventType } from "matrix-js-sdk/src/@types/event";
|
||||||
|
@ -38,7 +38,7 @@ interface IProps extends React.HTMLProps<HTMLDivElement> {
|
||||||
|
|
||||||
export default function RoomTopic({ room, ...props }: IProps): JSX.Element {
|
export default function RoomTopic({ room, ...props }: IProps): JSX.Element {
|
||||||
const client = useContext(MatrixClientContext);
|
const client = useContext(MatrixClientContext);
|
||||||
const ref = useRef() as RefObject<HTMLDivElement>;
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
const topic = useTopic(room);
|
const topic = useTopic(room);
|
||||||
const body = topicToHtml(topic?.text, topic?.html, ref);
|
const body = topicToHtml(topic?.text, topic?.html, ref);
|
||||||
|
|
|
@ -1504,9 +1504,10 @@ export const UserInfoHeader: React.FC<{
|
||||||
const avatarUrl = (member as RoomMember).getMxcAvatarUrl
|
const avatarUrl = (member as RoomMember).getMxcAvatarUrl
|
||||||
? (member as RoomMember).getMxcAvatarUrl()
|
? (member as RoomMember).getMxcAvatarUrl()
|
||||||
: (member as User).avatarUrl;
|
: (member as User).avatarUrl;
|
||||||
if (!avatarUrl) return;
|
|
||||||
|
|
||||||
const httpUrl = mediaFromMxc(avatarUrl).srcHttp;
|
const httpUrl = mediaFromMxc(avatarUrl).srcHttp;
|
||||||
|
if (!httpUrl) return;
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
src: httpUrl,
|
src: httpUrl,
|
||||||
name: (member as RoomMember).name || (member as User).displayName,
|
name: (member as RoomMember).name || (member as User).displayName,
|
||||||
|
|
|
@ -100,14 +100,14 @@ export default class AuxPanel extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
if (this.props.room && SettingsStore.getValue("feature_state_counters")) {
|
if (this.props.room && SettingsStore.getValue("feature_state_counters")) {
|
||||||
const stateEvs = this.props.room.currentState.getStateEvents("re.jki.counter");
|
const stateEvs = this.props.room.currentState.getStateEvents("re.jki.counter");
|
||||||
stateEvs.sort((a, b) => lexicographicCompare(a.getStateKey(), b.getStateKey()));
|
stateEvs.sort((a, b) => lexicographicCompare(a.getStateKey()!, b.getStateKey()!));
|
||||||
|
|
||||||
for (const ev of stateEvs) {
|
for (const ev of stateEvs) {
|
||||||
const title = ev.getContent().title;
|
const title = ev.getContent().title;
|
||||||
const value = ev.getContent().value;
|
const value = ev.getContent().value;
|
||||||
const link = ev.getContent().link;
|
const link = ev.getContent().link;
|
||||||
const severity = ev.getContent().severity || "normal";
|
const severity = ev.getContent().severity || "normal";
|
||||||
const stateKey = ev.getStateKey();
|
const stateKey = ev.getStateKey()!;
|
||||||
|
|
||||||
// We want a non-empty title but can accept falsy values (e.g.
|
// We want a non-empty title but can accept falsy values (e.g.
|
||||||
// zero)
|
// zero)
|
||||||
|
|
|
@ -765,7 +765,7 @@ export default class BasicMessageEditor extends React.Component<IProps, IState>
|
||||||
|
|
||||||
public render(): React.ReactNode {
|
public render(): React.ReactNode {
|
||||||
let autoComplete: JSX.Element | undefined;
|
let autoComplete: JSX.Element | undefined;
|
||||||
if (this.state.autoComplete) {
|
if (this.state.autoComplete && this.state.query) {
|
||||||
const query = this.state.query;
|
const query = this.state.query;
|
||||||
const queryLen = query.length;
|
const queryLen = query.length;
|
||||||
autoComplete = (
|
autoComplete = (
|
||||||
|
@ -800,8 +800,8 @@ export default class BasicMessageEditor extends React.Component<IProps, IState>
|
||||||
const { completionIndex } = this.state;
|
const { completionIndex } = this.state;
|
||||||
const hasAutocomplete = Boolean(this.state.autoComplete);
|
const hasAutocomplete = Boolean(this.state.autoComplete);
|
||||||
let activeDescendant: string | undefined;
|
let activeDescendant: string | undefined;
|
||||||
if (hasAutocomplete && completionIndex >= 0) {
|
if (hasAutocomplete && completionIndex! >= 0) {
|
||||||
activeDescendant = generateCompletionDomId(completionIndex);
|
activeDescendant = generateCompletionDomId(completionIndex!);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -229,11 +229,11 @@ class EditMessageComposer extends React.Component<IEditMessageComposerProps, ISt
|
||||||
}
|
}
|
||||||
|
|
||||||
private get editorRoomKey(): string {
|
private get editorRoomKey(): string {
|
||||||
return editorRoomKey(this.props.editState.getEvent().getRoomId(), this.context.timelineRenderingType);
|
return editorRoomKey(this.props.editState.getEvent().getRoomId()!, this.context.timelineRenderingType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private get editorStateKey(): string {
|
private get editorStateKey(): string {
|
||||||
return editorStateKey(this.props.editState.getEvent().getId());
|
return editorStateKey(this.props.editState.getEvent().getId()!);
|
||||||
}
|
}
|
||||||
|
|
||||||
private get events(): MatrixEvent[] {
|
private get events(): MatrixEvent[] {
|
||||||
|
@ -275,7 +275,7 @@ class EditMessageComposer extends React.Component<IEditMessageComposerProps, ISt
|
||||||
private saveStoredEditorState = (): void => {
|
private saveStoredEditorState = (): void => {
|
||||||
const item = SendHistoryManager.createItem(this.model);
|
const item = SendHistoryManager.createItem(this.model);
|
||||||
this.clearPreviousEdit();
|
this.clearPreviousEdit();
|
||||||
localStorage.setItem(this.editorRoomKey, this.props.editState.getEvent().getId());
|
localStorage.setItem(this.editorRoomKey, this.props.editState.getEvent().getId()!);
|
||||||
localStorage.setItem(this.editorStateKey, JSON.stringify(item));
|
localStorage.setItem(this.editorStateKey, JSON.stringify(item));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -329,7 +329,7 @@ class EditMessageComposer extends React.Component<IEditMessageComposerProps, ISt
|
||||||
|
|
||||||
// If content is modified then send an updated event into the room
|
// If content is modified then send an updated event into the room
|
||||||
if (this.isContentModified(newContent)) {
|
if (this.isContentModified(newContent)) {
|
||||||
const roomId = editedEvent.getRoomId();
|
const roomId = editedEvent.getRoomId()!;
|
||||||
if (!containsEmote(this.model) && isSlashCommand(this.model)) {
|
if (!containsEmote(this.model) && isSlashCommand(this.model)) {
|
||||||
const [cmd, args, commandText] = getSlashCommand(this.model);
|
const [cmd, args, commandText] = getSlashCommand(this.model);
|
||||||
if (cmd) {
|
if (cmd) {
|
||||||
|
|
|
@ -43,11 +43,13 @@ export default class LinkPreviewWidget extends React.Component<IProps> {
|
||||||
if (ev.button != 0 || ev.metaKey) return;
|
if (ev.button != 0 || ev.metaKey) return;
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
|
||||||
let src = p["og:image"];
|
let src: string | null | undefined = p["og:image"];
|
||||||
if (src?.startsWith("mxc://")) {
|
if (src?.startsWith("mxc://")) {
|
||||||
src = mediaFromMxc(src).srcHttp;
|
src = mediaFromMxc(src).srcHttp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!src) return;
|
||||||
|
|
||||||
const params: Omit<ComponentProps<typeof ImageView>, "onFinished"> = {
|
const params: Omit<ComponentProps<typeof ImageView>, "onFinished"> = {
|
||||||
src: src,
|
src: src,
|
||||||
width: p["og:image:width"],
|
width: p["og:image:width"],
|
||||||
|
|
|
@ -17,7 +17,7 @@ limitations under the License.
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { IEventRelation } from "matrix-js-sdk/src/models/event";
|
import { IEventRelation } from "matrix-js-sdk/src/models/event";
|
||||||
import { M_POLL_START } from "matrix-js-sdk/src/@types/polls";
|
import { M_POLL_START } from "matrix-js-sdk/src/@types/polls";
|
||||||
import React, { createContext, MouseEventHandler, ReactElement, ReactNode, RefObject, useContext, useRef } from "react";
|
import React, { createContext, MouseEventHandler, ReactElement, ReactNode, useContext, useRef } from "react";
|
||||||
import { Room } from "matrix-js-sdk/src/models/room";
|
import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
import { MatrixClient } from "matrix-js-sdk/src/client";
|
import { MatrixClient } from "matrix-js-sdk/src/client";
|
||||||
import { THREAD_RELATION_TYPE } from "matrix-js-sdk/src/models/thread";
|
import { THREAD_RELATION_TYPE } from "matrix-js-sdk/src/models/thread";
|
||||||
|
@ -180,7 +180,7 @@ interface IUploadButtonProps {
|
||||||
const UploadButtonContextProvider: React.FC<IUploadButtonProps> = ({ roomId, relation, children }) => {
|
const UploadButtonContextProvider: React.FC<IUploadButtonProps> = ({ roomId, relation, children }) => {
|
||||||
const cli = useContext(MatrixClientContext);
|
const cli = useContext(MatrixClientContext);
|
||||||
const roomContext = useContext(RoomContext);
|
const roomContext = useContext(RoomContext);
|
||||||
const uploadInput = useRef() as RefObject<HTMLInputElement>;
|
const uploadInput = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
const onUploadClick = (): void => {
|
const onUploadClick = (): void => {
|
||||||
if (cli?.isGuest()) {
|
if (cli?.isGuest()) {
|
||||||
|
|
|
@ -293,7 +293,7 @@ interface ISectionHeaderProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
function SectionHeader({ className, children }: PropsWithChildren<ISectionHeaderProps>): JSX.Element {
|
function SectionHeader({ className, children }: PropsWithChildren<ISectionHeaderProps>): JSX.Element {
|
||||||
const ref = useRef<HTMLHeadingElement>();
|
const ref = useRef<HTMLHeadingElement>(null);
|
||||||
const [onFocus] = useRovingTabIndex(ref);
|
const [onFocus] = useRovingTabIndex(ref);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -124,7 +124,7 @@ export default class ReadReceiptMarker extends React.PureComponent<IProps, IStat
|
||||||
private buildReadReceiptInfo(target: IReadReceiptInfo = {}): IReadReceiptInfo {
|
private buildReadReceiptInfo(target: IReadReceiptInfo = {}): IReadReceiptInfo {
|
||||||
const element = this.avatar.current;
|
const element = this.avatar.current;
|
||||||
// this is the mx_ReadReceiptsGroup_container
|
// this is the mx_ReadReceiptsGroup_container
|
||||||
const horizontalContainer = element.offsetParent;
|
const horizontalContainer = element?.offsetParent;
|
||||||
if (!horizontalContainer || !(horizontalContainer instanceof HTMLElement)) {
|
if (!horizontalContainer || !(horizontalContainer instanceof HTMLElement)) {
|
||||||
// this seems to happen sometimes for reasons I don't understand
|
// this seems to happen sometimes for reasons I don't understand
|
||||||
// the docs for `offsetParent` say it may be null if `display` is
|
// the docs for `offsetParent` say it may be null if `display` is
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { RefObject, useRef } from "react";
|
import React, { useRef } from "react";
|
||||||
|
|
||||||
import { BreadcrumbsStore } from "../../../stores/BreadcrumbsStore";
|
import { BreadcrumbsStore } from "../../../stores/BreadcrumbsStore";
|
||||||
import { UPDATE_EVENT } from "../../../stores/AsyncStore";
|
import { UPDATE_EVENT } from "../../../stores/AsyncStore";
|
||||||
|
@ -30,7 +30,7 @@ import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
|
||||||
import RoomAvatar from "../avatars/RoomAvatar";
|
import RoomAvatar from "../avatars/RoomAvatar";
|
||||||
|
|
||||||
const RecentlyViewedButton: React.FC = () => {
|
const RecentlyViewedButton: React.FC = () => {
|
||||||
const tooltipRef = useRef() as RefObject<InteractiveTooltip>;
|
const tooltipRef = useRef<InteractiveTooltip>(null);
|
||||||
const crumbs = useEventEmitterState(BreadcrumbsStore.instance, UPDATE_EVENT, () => BreadcrumbsStore.instance.rooms);
|
const crumbs = useEventEmitterState(BreadcrumbsStore.instance, UPDATE_EVENT, () => BreadcrumbsStore.instance.rooms);
|
||||||
|
|
||||||
const content = (
|
const content = (
|
||||||
|
|
|
@ -134,7 +134,7 @@ export default class ReplyTile extends React.PureComponent<IProps> {
|
||||||
|
|
||||||
let permalink = "#";
|
let permalink = "#";
|
||||||
if (this.props.permalinkCreator) {
|
if (this.props.permalinkCreator) {
|
||||||
permalink = this.props.permalinkCreator.forEvent(mxEvent.getId());
|
permalink = this.props.permalinkCreator.forEvent(mxEvent.getId()!);
|
||||||
}
|
}
|
||||||
|
|
||||||
let sender;
|
let sender;
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { ChangeEvent, RefObject, useRef, useState } from "react";
|
import React, { ChangeEvent, useRef, useState } from "react";
|
||||||
|
|
||||||
import { _t } from "../../../languageHandler";
|
import { _t } from "../../../languageHandler";
|
||||||
import AccessibleButton from "../elements/AccessibleButton";
|
import AccessibleButton from "../elements/AccessibleButton";
|
||||||
|
@ -38,7 +38,7 @@ export const SpaceAvatar: React.FC<Pick<IProps, "avatarUrl" | "avatarDisabled" |
|
||||||
avatarDisabled = false,
|
avatarDisabled = false,
|
||||||
setAvatar,
|
setAvatar,
|
||||||
}) => {
|
}) => {
|
||||||
const avatarUploadRef = useRef() as RefObject<HTMLInputElement>;
|
const avatarUploadRef = useRef<HTMLInputElement>(null);
|
||||||
const [avatar, setAvatarDataUrl] = useState(avatarUrl); // avatar data url cache
|
const [avatar, setAvatarDataUrl] = useState(avatarUrl); // avatar data url cache
|
||||||
|
|
||||||
let avatarSection;
|
let avatarSection;
|
||||||
|
|
|
@ -77,7 +77,7 @@ export class Media {
|
||||||
*/
|
*/
|
||||||
public get srcHttp(): string | null {
|
public get srcHttp(): string | null {
|
||||||
// eslint-disable-next-line no-restricted-properties
|
// eslint-disable-next-line no-restricted-properties
|
||||||
return this.client.mxcUrlToHttp(this.srcMxc);
|
return this.client.mxcUrlToHttp(this.srcMxc) || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -44,7 +44,7 @@ export default class Resizer<C extends IConfig = IConfig> {
|
||||||
// TODO move vertical/horizontal to config option/container class
|
// TODO move vertical/horizontal to config option/container class
|
||||||
// as it doesn't make sense to mix them within one container/Resizer
|
// as it doesn't make sense to mix them within one container/Resizer
|
||||||
public constructor(
|
public constructor(
|
||||||
public container: HTMLElement,
|
public container: HTMLElement | null,
|
||||||
private readonly distributorCtor: {
|
private readonly distributorCtor: {
|
||||||
new (item: ResizeItem): FixedDistributor<C, any>;
|
new (item: ResizeItem): FixedDistributor<C, any>;
|
||||||
createItem(
|
createItem(
|
||||||
|
@ -53,7 +53,7 @@ export default class Resizer<C extends IConfig = IConfig> {
|
||||||
sizer: Sizer,
|
sizer: Sizer,
|
||||||
container?: HTMLElement,
|
container?: HTMLElement,
|
||||||
): ResizeItem;
|
): ResizeItem;
|
||||||
createSizer(containerElement: HTMLElement, vertical: boolean, reverse: boolean): Sizer;
|
createSizer(containerElement: HTMLElement | null, vertical: boolean, reverse: boolean): Sizer;
|
||||||
},
|
},
|
||||||
public readonly config?: C,
|
public readonly config?: C,
|
||||||
) {
|
) {
|
||||||
|
@ -71,13 +71,13 @@ export default class Resizer<C extends IConfig = IConfig> {
|
||||||
|
|
||||||
public attach(): void {
|
public attach(): void {
|
||||||
const attachment = this?.config?.handler?.parentElement ?? this.container;
|
const attachment = this?.config?.handler?.parentElement ?? this.container;
|
||||||
attachment.addEventListener("mousedown", this.onMouseDown, false);
|
attachment?.addEventListener("mousedown", this.onMouseDown, false);
|
||||||
window.addEventListener("resize", this.onResize);
|
window.addEventListener("resize", this.onResize);
|
||||||
}
|
}
|
||||||
|
|
||||||
public detach(): void {
|
public detach(): void {
|
||||||
const attachment = this?.config?.handler?.parentElement ?? this.container;
|
const attachment = this?.config?.handler?.parentElement ?? this.container;
|
||||||
attachment.removeEventListener("mousedown", this.onMouseDown, false);
|
attachment?.removeEventListener("mousedown", this.onMouseDown, false);
|
||||||
window.removeEventListener("resize", this.onResize);
|
window.removeEventListener("resize", this.onResize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,7 +194,7 @@ export default class Resizer<C extends IConfig = IConfig> {
|
||||||
const Distributor = this.distributorCtor;
|
const Distributor = this.distributorCtor;
|
||||||
const useItemContainer = this.config?.handler ? this.container : undefined;
|
const useItemContainer = this.config?.handler ? this.container : undefined;
|
||||||
const sizer = Distributor.createSizer(this.container, vertical, reverse);
|
const sizer = Distributor.createSizer(this.container, vertical, reverse);
|
||||||
const item = Distributor.createItem(resizeHandle, this, sizer, useItemContainer);
|
const item = Distributor.createItem(resizeHandle, this, sizer, useItemContainer ?? undefined);
|
||||||
const distributor = new Distributor(item);
|
const distributor = new Distributor(item);
|
||||||
return { sizer, distributor };
|
return { sizer, distributor };
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,20 @@ import { AutocompleteInput } from "../../../src/components/structures/Autocomple
|
||||||
|
|
||||||
describe("AutocompleteInput", () => {
|
describe("AutocompleteInput", () => {
|
||||||
const mockCompletion: ICompletion[] = [
|
const mockCompletion: ICompletion[] = [
|
||||||
{ type: "user", completion: "user_1", completionId: "@user_1:host.local", range: { start: 1, end: 1 } },
|
{
|
||||||
{ type: "user", completion: "user_2", completionId: "@user_2:host.local", range: { start: 1, end: 1 } },
|
type: "user",
|
||||||
|
completion: "user_1",
|
||||||
|
completionId: "@user_1:host.local",
|
||||||
|
range: { start: 1, end: 1 },
|
||||||
|
component: <div />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "user",
|
||||||
|
completion: "user_2",
|
||||||
|
completionId: "@user_2:host.local",
|
||||||
|
range: { start: 1, end: 1 },
|
||||||
|
component: <div />,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const constructMockProvider = (data: ICompletion[]) =>
|
const constructMockProvider = (data: ICompletion[]) =>
|
||||||
|
|
|
@ -15,6 +15,7 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { mocked } from "jest-mock";
|
import { mocked } from "jest-mock";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
import { ICompletion } from "../../../../../../src/autocomplete/Autocompleter";
|
import { ICompletion } from "../../../../../../src/autocomplete/Autocompleter";
|
||||||
import {
|
import {
|
||||||
|
@ -34,6 +35,7 @@ const createMockCompletion = (props: Partial<ICompletion>): ICompletion => {
|
||||||
return {
|
return {
|
||||||
completion: "mock",
|
completion: "mock",
|
||||||
range: { beginning: true, start: 0, end: 0 },
|
range: { beginning: true, start: 0, end: 0 },
|
||||||
|
component: React.createElement("div"),
|
||||||
...props,
|
...props,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -32,9 +32,21 @@ import { ICompletion } from "../../../../src/autocomplete/Autocompleter";
|
||||||
jest.mock("../../../../src/autocomplete/UserProvider");
|
jest.mock("../../../../src/autocomplete/UserProvider");
|
||||||
|
|
||||||
const completions: ICompletion[] = [
|
const completions: ICompletion[] = [
|
||||||
{ type: "user", completion: "user_1", completionId: "@user_1:host.local", range: { start: 1, end: 1 } },
|
{
|
||||||
{ type: "user", completion: "user_2", completionId: "@user_2:host.local", range: { start: 1, end: 1 } },
|
component: <div />,
|
||||||
{ type: "user", completion: "user_without_completion_id", range: { start: 1, end: 1 } },
|
type: "user",
|
||||||
|
completion: "user_1",
|
||||||
|
completionId: "@user_1:host.local",
|
||||||
|
range: { start: 1, end: 1 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: <div />,
|
||||||
|
type: "user",
|
||||||
|
completion: "user_2",
|
||||||
|
completionId: "@user_2:host.local",
|
||||||
|
range: { start: 1, end: 1 },
|
||||||
|
},
|
||||||
|
{ component: <div />, type: "user", completion: "user_without_completion_id", range: { start: 1, end: 1 } },
|
||||||
];
|
];
|
||||||
|
|
||||||
describe("<AddPrivilegedUsers />", () => {
|
describe("<AddPrivilegedUsers />", () => {
|
||||||
|
|
Loading…
Reference in a new issue