From 277a3c01464f0fb14843daae33f84dda0144b1e2 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 25 May 2023 09:39:23 +0100 Subject: [PATCH] Conform more of the codebase to strict typescript (#10841) --- src/IdentityAuthClient.tsx | 6 +- src/components/structures/RightPanel.tsx | 73 +++++++++++-------- src/components/structures/RoomView.tsx | 1 + src/components/structures/TimelinePanel.tsx | 4 +- .../dialogs/VerificationRequestDialog.tsx | 2 + .../views/rooms/EditMessageComposer.tsx | 9 +-- .../views/rooms/NotificationBadge.tsx | 32 ++++---- .../tabs/user/KeyboardUserSettingsTab.tsx | 2 +- src/stores/CallStore.ts | 2 +- src/stores/RoomScrollStateStore.ts | 8 +- src/utils/FormattingUtils.ts | 6 +- .../views/rooms/EditMessageComposer-test.tsx | 4 +- 12 files changed, 89 insertions(+), 60 deletions(-) diff --git a/src/IdentityAuthClient.tsx b/src/IdentityAuthClient.tsx index cb38679ee89..05a61eab058 100644 --- a/src/IdentityAuthClient.tsx +++ b/src/IdentityAuthClient.tsx @@ -64,7 +64,11 @@ export default class IdentityAuthClient { private writeToken(): void { if (this.tempClient) return; // temporary client: ignore - window.localStorage.setItem("mx_is_access_token", this.accessToken); + if (this.accessToken) { + window.localStorage.setItem("mx_is_access_token", this.accessToken); + } else { + window.localStorage.removeItem("mx_is_access_token"); + } } private readToken(): string | null { diff --git a/src/components/structures/RightPanel.tsx b/src/components/structures/RightPanel.tsx index b918c2c0c66..23bf75a33d8 100644 --- a/src/components/structures/RightPanel.tsx +++ b/src/components/structures/RightPanel.tsx @@ -44,26 +44,37 @@ import TimelineCard from "../views/right_panel/TimelineCard"; import { UPDATE_EVENT } from "../../stores/AsyncStore"; import { IRightPanelCard, IRightPanelCardState } from "../../stores/right-panel/RightPanelStoreIPanelState"; import { Action } from "../../dispatcher/actions"; +import { XOR } from "../../@types/common"; -interface IProps { - room?: Room; // if showing panels for a given room, this is set +interface BaseProps { overwriteCard?: IRightPanelCard; // used to display a custom card and ignoring the RightPanelStore (used for UserView) resizeNotifier: ResizeNotifier; - permalinkCreator?: RoomPermalinkCreator; e2eStatus?: E2EStatus; } +interface RoomlessProps extends BaseProps { + room?: undefined; + permalinkCreator?: undefined; +} + +interface RoomProps extends BaseProps { + room: Room; + permalinkCreator: RoomPermalinkCreator; +} + +type Props = XOR; + interface IState { phase?: RightPanelPhases; searchQuery: string; cardState?: IRightPanelCardState; } -export default class RightPanel extends React.Component { +export default class RightPanel extends React.Component { public static contextType = MatrixClientContext; public context!: React.ContextType; - public constructor(props: IProps, context: React.ContextType) { + public constructor(props: Props, context: React.ContextType) { super(props, context); this.state = { @@ -89,7 +100,7 @@ export default class RightPanel extends React.Component { RightPanelStore.instance.off(UPDATE_EVENT, this.onRightPanelStoreUpdate); } - public static getDerivedStateFromProps(props: IProps): Partial { + public static getDerivedStateFromProps(props: Props): Partial { let currentCard: IRightPanelCard | undefined; if (props.room) { currentCard = RightPanelStore.instance.currentCardForRoom(props.room.roomId); @@ -169,32 +180,36 @@ export default class RightPanel extends React.Component { } break; case RightPanelPhases.SpaceMemberList: - card = ( - - ); + if (!!cardState?.spaceId || !!roomId) { + card = ( + + ); + } break; case RightPanelPhases.RoomMemberInfo: case RightPanelPhases.SpaceMemberInfo: case RightPanelPhases.EncryptionPanel: { - const roomMember = cardState?.member instanceof RoomMember ? cardState.member : undefined; - card = ( - - ); + if (!!cardState?.member) { + const roomMember = cardState.member instanceof RoomMember ? cardState.member : undefined; + card = ( + + ); + } break; } case RightPanelPhases.Room3pidMemberInfo: @@ -261,10 +276,10 @@ export default class RightPanel extends React.Component { break; case RightPanelPhases.ThreadPanel: - if (!!roomId) { + if (!!this.props.room) { card = ( { // rate limited because a power level change will emit an event for every member in the room. private updateRoomMembers = throttle( () => { + if (!this.state.room) return; this.updateDMState(); this.updateE2EStatus(this.state.room); }, diff --git a/src/components/structures/TimelinePanel.tsx b/src/components/structures/TimelinePanel.tsx index b00b6ed132a..5b5e0365efc 100644 --- a/src/components/structures/TimelinePanel.tsx +++ b/src/components/structures/TimelinePanel.tsx @@ -740,7 +740,7 @@ class TimelinePanel extends React.Component { if (!this.messagePanel.current?.getScrollState()) return; - if (!this.messagePanel.current.getScrollState().stuckAtBottom) { + if (!this.messagePanel.current.getScrollState()?.stuckAtBottom) { // we won't load this event now, because we don't want to push any // events off the other end of the timeline. But we need to note // that we can now paginate. @@ -981,7 +981,7 @@ class TimelinePanel extends React.Component { { leading: true, trailing: true }, ); - private readMarkerTimeout(readMarkerPosition: number): number { + private readMarkerTimeout(readMarkerPosition: number | null): number { return readMarkerPosition === 0 ? this.context?.readMarkerInViewThresholdMs ?? this.state.readMarkerInViewThresholdMs : this.context?.readMarkerOutOfViewThresholdMs ?? this.state.readMarkerOutOfViewThresholdMs; diff --git a/src/components/views/dialogs/VerificationRequestDialog.tsx b/src/components/views/dialogs/VerificationRequestDialog.tsx index 53ac14f6c08..540cb3190eb 100644 --- a/src/components/views/dialogs/VerificationRequestDialog.tsx +++ b/src/components/views/dialogs/VerificationRequestDialog.tsx @@ -51,6 +51,8 @@ export default class VerificationRequestDialog extends React.Component { diff --git a/src/components/views/rooms/NotificationBadge.tsx b/src/components/views/rooms/NotificationBadge.tsx index a9b08ebd7a0..c6fe4e2ba17 100644 --- a/src/components/views/rooms/NotificationBadge.tsx +++ b/src/components/views/rooms/NotificationBadge.tsx @@ -126,19 +126,23 @@ export default class NotificationBadge extends React.PureComponent; } - return ( - - {tooltip} - - ); + const commonProps: React.ComponentProps = { + label, + symbol: notification.symbol, + count: notification.count, + color: notification.color, + onMouseOver: this.onMouseOver, + onMouseLeave: this.onMouseLeave, + }; + + if (onClick) { + return ( + + {tooltip} + + ); + } + + return {tooltip}; } } diff --git a/src/components/views/settings/tabs/user/KeyboardUserSettingsTab.tsx b/src/components/views/settings/tabs/user/KeyboardUserSettingsTab.tsx index f64c1ce87b5..49b598d2379 100644 --- a/src/components/views/settings/tabs/user/KeyboardUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/KeyboardUserSettingsTab.tsx @@ -74,7 +74,7 @@ const KeyboardUserSettingsTab: React.FC = () => { return ( - {visibleCategories.map(([categoryName, category]: [CategoryName, ICategory]) => { + {visibleCategories.map(([categoryName, category]) => { return ( ); diff --git a/src/stores/CallStore.ts b/src/stores/CallStore.ts index 68bc2fe94df..a24a11e5698 100644 --- a/src/stores/CallStore.ts +++ b/src/stores/CallStore.ts @@ -146,7 +146,7 @@ export class CallStore extends AsyncStoreWithClient<{}> { this.calls.set(room.roomId, call); this.callListeners.set( call, - new Map unknown>([ + new Map unknown>([ [CallEvent.ConnectionState, onConnectionState], [CallEvent.Destroy, onDestroy], ]), diff --git a/src/stores/RoomScrollStateStore.ts b/src/stores/RoomScrollStateStore.ts index 4354bfb9c78..b394ed1b519 100644 --- a/src/stores/RoomScrollStateStore.ts +++ b/src/stores/RoomScrollStateStore.ts @@ -42,8 +42,12 @@ export class RoomScrollStateStore { return this.scrollStateMap.get(roomId); } - public setScrollState(roomId: string, scrollState: ScrollState): void { - this.scrollStateMap.set(roomId, scrollState); + public setScrollState(roomId: string, scrollState: ScrollState | null): void { + if (scrollState === null) { + this.scrollStateMap.delete(roomId); + } else { + this.scrollStateMap.set(roomId, scrollState); + } } } diff --git a/src/utils/FormattingUtils.ts b/src/utils/FormattingUtils.ts index 4e9686f9977..83447aa745d 100644 --- a/src/utils/FormattingUtils.ts +++ b/src/utils/FormattingUtils.ts @@ -75,10 +75,10 @@ export function formatCryptoKey(key: string): string { * * @return {number} */ -export function hashCode(str: string): number { +export function hashCode(str?: string): number { let hash = 0; let chr: number; - if (str.length === 0) { + if (!str?.length) { return hash; } for (let i = 0; i < str.length; i++) { @@ -89,7 +89,7 @@ export function hashCode(str: string): number { return Math.abs(hash); } -export function getUserNameColorClass(userId: string): string { +export function getUserNameColorClass(userId?: string): string { const colorNumber = (hashCode(userId) % 8) + 1; return `mx_Username_color${colorNumber}`; } diff --git a/test/components/views/rooms/EditMessageComposer-test.tsx b/test/components/views/rooms/EditMessageComposer-test.tsx index da96e31b012..64425d8f914 100644 --- a/test/components/views/rooms/EditMessageComposer-test.tsx +++ b/test/components/views/rooms/EditMessageComposer-test.tsx @@ -151,7 +151,9 @@ describe("", () => { it("should throw when room for message is not found", () => { mockClient.getRoom.mockReturnValue(null); const editState = new EditorStateTransfer(editedEvent); - expect(() => getComponent(editState)).toThrow("Cannot find room for event !abc:test"); + expect(() => getComponent(editState, { ...defaultRoomContext, room: undefined })).toThrow( + "Cannot render without room", + ); }); describe("createEditContent", () => {