Conform more of the codebase to strict typescript (#10841)

This commit is contained in:
Michael Telatynski 2023-05-25 09:39:23 +01:00 committed by GitHub
parent af78a5a2f5
commit 277a3c0146
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 89 additions and 60 deletions

View file

@ -64,7 +64,11 @@ export default class IdentityAuthClient {
private writeToken(): void { private writeToken(): void {
if (this.tempClient) return; // temporary client: ignore if (this.tempClient) return; // temporary client: ignore
if (this.accessToken) {
window.localStorage.setItem("mx_is_access_token", this.accessToken); window.localStorage.setItem("mx_is_access_token", this.accessToken);
} else {
window.localStorage.removeItem("mx_is_access_token");
}
} }
private readToken(): string | null { private readToken(): string | null {

View file

@ -44,26 +44,37 @@ import TimelineCard from "../views/right_panel/TimelineCard";
import { UPDATE_EVENT } from "../../stores/AsyncStore"; import { UPDATE_EVENT } from "../../stores/AsyncStore";
import { IRightPanelCard, IRightPanelCardState } from "../../stores/right-panel/RightPanelStoreIPanelState"; import { IRightPanelCard, IRightPanelCardState } from "../../stores/right-panel/RightPanelStoreIPanelState";
import { Action } from "../../dispatcher/actions"; import { Action } from "../../dispatcher/actions";
import { XOR } from "../../@types/common";
interface IProps { interface BaseProps {
room?: Room; // if showing panels for a given room, this is set
overwriteCard?: IRightPanelCard; // used to display a custom card and ignoring the RightPanelStore (used for UserView) overwriteCard?: IRightPanelCard; // used to display a custom card and ignoring the RightPanelStore (used for UserView)
resizeNotifier: ResizeNotifier; resizeNotifier: ResizeNotifier;
permalinkCreator?: RoomPermalinkCreator;
e2eStatus?: E2EStatus; e2eStatus?: E2EStatus;
} }
interface RoomlessProps extends BaseProps {
room?: undefined;
permalinkCreator?: undefined;
}
interface RoomProps extends BaseProps {
room: Room;
permalinkCreator: RoomPermalinkCreator;
}
type Props = XOR<RoomlessProps, RoomProps>;
interface IState { interface IState {
phase?: RightPanelPhases; phase?: RightPanelPhases;
searchQuery: string; searchQuery: string;
cardState?: IRightPanelCardState; cardState?: IRightPanelCardState;
} }
export default class RightPanel extends React.Component<IProps, IState> { export default class RightPanel extends React.Component<Props, IState> {
public static contextType = MatrixClientContext; public static contextType = MatrixClientContext;
public context!: React.ContextType<typeof MatrixClientContext>; public context!: React.ContextType<typeof MatrixClientContext>;
public constructor(props: IProps, context: React.ContextType<typeof MatrixClientContext>) { public constructor(props: Props, context: React.ContextType<typeof MatrixClientContext>) {
super(props, context); super(props, context);
this.state = { this.state = {
@ -89,7 +100,7 @@ export default class RightPanel extends React.Component<IProps, IState> {
RightPanelStore.instance.off(UPDATE_EVENT, this.onRightPanelStoreUpdate); RightPanelStore.instance.off(UPDATE_EVENT, this.onRightPanelStoreUpdate);
} }
public static getDerivedStateFromProps(props: IProps): Partial<IState> { public static getDerivedStateFromProps(props: Props): Partial<IState> {
let currentCard: IRightPanelCard | undefined; let currentCard: IRightPanelCard | undefined;
if (props.room) { if (props.room) {
currentCard = RightPanelStore.instance.currentCardForRoom(props.room.roomId); currentCard = RightPanelStore.instance.currentCardForRoom(props.room.roomId);
@ -169,32 +180,36 @@ export default class RightPanel extends React.Component<IProps, IState> {
} }
break; break;
case RightPanelPhases.SpaceMemberList: case RightPanelPhases.SpaceMemberList:
if (!!cardState?.spaceId || !!roomId) {
card = ( card = (
<MemberList <MemberList
roomId={cardState?.spaceId ?? roomId} roomId={cardState?.spaceId ?? roomId!}
key={cardState?.spaceId ?? roomId} key={cardState?.spaceId ?? roomId!}
onClose={this.onClose} onClose={this.onClose}
searchQuery={this.state.searchQuery} searchQuery={this.state.searchQuery}
onSearchQueryChanged={this.onSearchQueryChanged} onSearchQueryChanged={this.onSearchQueryChanged}
/> />
); );
}
break; break;
case RightPanelPhases.RoomMemberInfo: case RightPanelPhases.RoomMemberInfo:
case RightPanelPhases.SpaceMemberInfo: case RightPanelPhases.SpaceMemberInfo:
case RightPanelPhases.EncryptionPanel: { case RightPanelPhases.EncryptionPanel: {
const roomMember = cardState?.member instanceof RoomMember ? cardState.member : undefined; if (!!cardState?.member) {
const roomMember = cardState.member instanceof RoomMember ? cardState.member : undefined;
card = ( card = (
<UserInfo <UserInfo
user={cardState?.member} user={cardState.member}
room={this.context.getRoom(roomMember?.roomId) ?? this.props.room} room={this.context.getRoom(roomMember?.roomId) ?? this.props.room}
key={roomId ?? cardState?.member?.userId} key={roomId ?? cardState.member.userId}
onClose={this.onClose} onClose={this.onClose}
phase={phase} phase={phase}
verificationRequest={cardState?.verificationRequest} verificationRequest={cardState.verificationRequest}
verificationRequestPromise={cardState?.verificationRequestPromise} verificationRequestPromise={cardState.verificationRequestPromise}
/> />
); );
}
break; break;
} }
case RightPanelPhases.Room3pidMemberInfo: case RightPanelPhases.Room3pidMemberInfo:
@ -261,10 +276,10 @@ export default class RightPanel extends React.Component<IProps, IState> {
break; break;
case RightPanelPhases.ThreadPanel: case RightPanelPhases.ThreadPanel:
if (!!roomId) { if (!!this.props.room) {
card = ( card = (
<ThreadPanel <ThreadPanel
roomId={roomId} roomId={this.props.room.roomId}
resizeNotifier={this.props.resizeNotifier} resizeNotifier={this.props.resizeNotifier}
onClose={this.onClose} onClose={this.onClose}
permalinkCreator={this.props.permalinkCreator} permalinkCreator={this.props.permalinkCreator}

View file

@ -1488,6 +1488,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
// rate limited because a power level change will emit an event for every member in the room. // rate limited because a power level change will emit an event for every member in the room.
private updateRoomMembers = throttle( private updateRoomMembers = throttle(
() => { () => {
if (!this.state.room) return;
this.updateDMState(); this.updateDMState();
this.updateE2EStatus(this.state.room); this.updateE2EStatus(this.state.room);
}, },

View file

@ -740,7 +740,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
if (!this.messagePanel.current?.getScrollState()) return; 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 // 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 // events off the other end of the timeline. But we need to note
// that we can now paginate. // that we can now paginate.
@ -981,7 +981,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
{ leading: true, trailing: true }, { leading: true, trailing: true },
); );
private readMarkerTimeout(readMarkerPosition: number): number { private readMarkerTimeout(readMarkerPosition: number | null): number {
return readMarkerPosition === 0 return readMarkerPosition === 0
? this.context?.readMarkerInViewThresholdMs ?? this.state.readMarkerInViewThresholdMs ? this.context?.readMarkerInViewThresholdMs ?? this.state.readMarkerInViewThresholdMs
: this.context?.readMarkerOutOfViewThresholdMs ?? this.state.readMarkerOutOfViewThresholdMs; : this.context?.readMarkerOutOfViewThresholdMs ?? this.state.readMarkerOutOfViewThresholdMs;

View file

@ -51,6 +51,8 @@ export default class VerificationRequestDialog extends React.Component<IProps, I
const member = this.props.member || (otherUserId ? MatrixClientPeg.get().getUser(otherUserId) : null); const member = this.props.member || (otherUserId ? MatrixClientPeg.get().getUser(otherUserId) : null);
const title = request?.isSelfVerification ? _t("Verify other device") : _t("Verification Request"); const title = request?.isSelfVerification ? _t("Verify other device") : _t("Verification Request");
if (!member) return null;
return ( return (
<BaseDialog <BaseDialog
className="mx_InfoDialog" className="mx_InfoDialog"

View file

@ -152,13 +152,10 @@ class EditMessageComposer extends React.Component<IEditMessageComposerProps, ISt
} }
private getRoom(): Room { private getRoom(): Room {
const roomId = this.props.editState.getEvent().getRoomId(); if (!this.context.room) {
const room = this.props.mxClient.getRoom(roomId); throw new Error(`Cannot render without room`);
// Something is very wrong if we encounter this
if (!room) {
throw new Error(`Cannot find room for event ${roomId}`);
} }
return room; return this.context.room;
} }
private onKeyDown = (event: KeyboardEvent): void => { private onKeyDown = (event: KeyboardEvent): void => {

View file

@ -126,19 +126,23 @@ export default class NotificationBadge extends React.PureComponent<XOR<IProps, I
tooltip = <Tooltip className="mx_NotificationBadge_tooltip" label={label} />; tooltip = <Tooltip className="mx_NotificationBadge_tooltip" label={label} />;
} }
const commonProps: React.ComponentProps<typeof StatelessNotificationBadge> = {
label,
symbol: notification.symbol,
count: notification.count,
color: notification.color,
onMouseOver: this.onMouseOver,
onMouseLeave: this.onMouseLeave,
};
if (onClick) {
return ( return (
<StatelessNotificationBadge <StatelessNotificationBadge {...commonProps} onClick={onClick} tabIndex={tabIndex}>
label={label}
symbol={notification.symbol}
count={notification.count}
color={notification.color}
onClick={onClick}
onMouseOver={this.onMouseOver}
onMouseLeave={this.onMouseLeave}
tabIndex={tabIndex}
>
{tooltip} {tooltip}
</StatelessNotificationBadge> </StatelessNotificationBadge>
); );
} }
return <StatelessNotificationBadge {...commonProps}>{tooltip}</StatelessNotificationBadge>;
}
} }

View file

@ -74,7 +74,7 @@ const KeyboardUserSettingsTab: React.FC = () => {
return ( return (
<SettingsTab> <SettingsTab>
<SettingsSection heading={_t("Keyboard")}> <SettingsSection heading={_t("Keyboard")}>
{visibleCategories.map(([categoryName, category]: [CategoryName, ICategory]) => { {visibleCategories.map(([categoryName, category]) => {
return ( return (
<KeyboardShortcutSection key={categoryName} categoryName={categoryName} category={category} /> <KeyboardShortcutSection key={categoryName} categoryName={categoryName} category={category} />
); );

View file

@ -146,7 +146,7 @@ export class CallStore extends AsyncStoreWithClient<{}> {
this.calls.set(room.roomId, call); this.calls.set(room.roomId, call);
this.callListeners.set( this.callListeners.set(
call, call,
new Map<CallEvent, (...args: unknown[]) => unknown>([ new Map<CallEvent, (...args: any[]) => unknown>([
[CallEvent.ConnectionState, onConnectionState], [CallEvent.ConnectionState, onConnectionState],
[CallEvent.Destroy, onDestroy], [CallEvent.Destroy, onDestroy],
]), ]),

View file

@ -42,10 +42,14 @@ export class RoomScrollStateStore {
return this.scrollStateMap.get(roomId); return this.scrollStateMap.get(roomId);
} }
public setScrollState(roomId: string, scrollState: ScrollState): void { public setScrollState(roomId: string, scrollState: ScrollState | null): void {
if (scrollState === null) {
this.scrollStateMap.delete(roomId);
} else {
this.scrollStateMap.set(roomId, scrollState); this.scrollStateMap.set(roomId, scrollState);
} }
} }
}
if (window.mxRoomScrollStateStore === undefined) { if (window.mxRoomScrollStateStore === undefined) {
window.mxRoomScrollStateStore = new RoomScrollStateStore(); window.mxRoomScrollStateStore = new RoomScrollStateStore();

View file

@ -75,10 +75,10 @@ export function formatCryptoKey(key: string): string {
* *
* @return {number} * @return {number}
*/ */
export function hashCode(str: string): number { export function hashCode(str?: string): number {
let hash = 0; let hash = 0;
let chr: number; let chr: number;
if (str.length === 0) { if (!str?.length) {
return hash; return hash;
} }
for (let i = 0; i < str.length; i++) { for (let i = 0; i < str.length; i++) {
@ -89,7 +89,7 @@ export function hashCode(str: string): number {
return Math.abs(hash); return Math.abs(hash);
} }
export function getUserNameColorClass(userId: string): string { export function getUserNameColorClass(userId?: string): string {
const colorNumber = (hashCode(userId) % 8) + 1; const colorNumber = (hashCode(userId) % 8) + 1;
return `mx_Username_color${colorNumber}`; return `mx_Username_color${colorNumber}`;
} }

View file

@ -151,7 +151,9 @@ describe("<EditMessageComposer/>", () => {
it("should throw when room for message is not found", () => { it("should throw when room for message is not found", () => {
mockClient.getRoom.mockReturnValue(null); mockClient.getRoom.mockReturnValue(null);
const editState = new EditorStateTransfer(editedEvent); 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", () => { describe("createEditContent", () => {