Enable oxlint restriction ruleset (#34307)

* Remove stale max-len disablements

* Remove stale camelCase & naming-convention disablements

* Remove stale ban-ts-comment disablements

* Remove stale no-var disablements

* Remove stale no-empty-property disablements

* Remove stale react rule disablements

* Remove stale no-constant-condition disablements

* Remove stale no-unused-vars disablements

* Remove stale disablements for disabled rules

* fixup camelcase

* Remove dead code

* Tidy code

* Tweak oxlint config

* Use oxlint to apply jsx/tsx extension consistently

* Fix import

* Fix imports

* Rename affected snapshots

* Update more imports

* Enable restriction ruleset

* Make code comply with new rules

* Make code comply with react/button-has-type

* Make code comply with typescript/non-nullable-type-assertion-style

* Comply with node/no-process-env

* Comply with unicorn/prefer-node-protocol

* Comply with unicorn/import-style

* Comply with unicorn/no-process-exit

* Comply with no-proto

* Comply with node/handle-callback-err

* Comply with import/no-commonjs

* Comply with node/no-path-concat

* Comply with unicorn/no-length-as-slice-end

* Comply with unicorn/no-document-cookie

* Comply with unicorn/prefer-module

* Comply with typescript/prefer-literal-enum-member

* Comply with jsx-a11y/anchor-ambiguous-text

* Tweak oxlint config

* Fix resolves

* Iterate

* Iterate

* Iterate

* Iterate

* Iterate

* Iterate

* Iterate
This commit is contained in:
Michael Telatynski
2026-08-04 09:15:07 +00:00
committed by GitHub
parent c091ebec6e
commit 4aa1a3549e
167 changed files with 526 additions and 346 deletions
+1 -1
View File
@@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
// @vitest-environment happy-dom
import { EventEmitter } from "events";
import { EventEmitter } from "node:events";
import { vi, describe, it, expect, beforeEach, afterEach } from "vitest";
import type { MatrixClient } from "matrix-js-sdk/src/matrix";
+1
View File
@@ -7,6 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
// oxlint-disable-next-line no-restricted-imports
import EventEmitter from "events";
import { logger } from "matrix-js-sdk/src/logger";
+1
View File
@@ -56,6 +56,7 @@ export async function startAnyRegistrationFlow(
modal.close();
dis.dispatch({ action: "start_registration", screenAfterLogin: options.screen_after });
}}
type="button"
>
{_t("auth|register_action")}
</button>,
+1 -1
View File
@@ -827,7 +827,7 @@ async function readEvents(
const effectiveStateKey = stateKey === true ? undefined : stateKey;
let events: MatrixEvent[] = [];
events = events.concat(room.currentState.getStateEvents(eventType, effectiveStateKey as string) || []);
events = events.concat(room.currentState.getStateEvents(eventType, effectiveStateKey!) || []);
events = events.slice(0, effectiveLimit);
sendResponse(event, {
+1 -1
View File
@@ -12,7 +12,7 @@ import { vi, describe, it, expect, beforeEach } from "vitest";
import { type SlidingSync, SlidingSyncEvent, SlidingSyncState } from "matrix-js-sdk/src/sliding-sync";
import { ClientEvent, type MatrixClient, MatrixEvent, Room } from "matrix-js-sdk/src/matrix";
import fetchMock from "@fetch-mock/vitest";
import EventEmitter from "events";
import EventEmitter from "node:events";
import { waitFor } from "test-utils-rtl";
import { mkStubRoom, stubClient } from "test-utils";
+3 -1
View File
@@ -101,7 +101,9 @@ export default class UserActivity {
// as we fork the promise here,
// avoid unhandled rejection warnings
})
.catch((err) => {});
.catch(() => {
// Do nothing
});
}
}
@@ -211,7 +211,7 @@ export default class ExportE2eKeysDialog extends React.Component<IProps, IState>
value={_t("action|export")}
disabled={disableForm}
/>
<button onClick={this.onCancelClick} disabled={disableForm}>
<button onClick={this.onCancelClick} disabled={disableForm} type="button">
{_t("action|cancel")}
</button>
</div>
@@ -180,7 +180,7 @@ export default class ImportE2eKeysDialog extends React.Component<IProps, IState>
value={_t("action|import")}
disabled={!this.state.enableSubmit || disableForm}
/>
<button onClick={this.onCancelClick} disabled={disableForm}>
<button onClick={this.onCancelClick} disabled={disableForm} type="button">
{_t("action|cancel")}
</button>
</div>
+1
View File
@@ -6,6 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
// oxlint-disable-next-line no-restricted-imports
import EventEmitter from "events";
import { SimpleObservable } from "matrix-widget-api";
import { logger } from "matrix-js-sdk/src/logger";
+1
View File
@@ -9,6 +9,7 @@ Please see LICENSE files in the repository root for full details.
import Recorder from "opus-recorder/dist/recorder.min.js";
import encoderPath from "opus-recorder/dist/encoderWorker.min.js";
import { SimpleObservable } from "matrix-widget-api";
// oxlint-disable-next-line no-restricted-imports
import EventEmitter from "events";
import { logger } from "matrix-js-sdk/src/logger";
import { clamp } from "@element-hq/web-shared-components";
@@ -8,6 +8,7 @@ Please see LICENSE files in the repository root for full details.
import { EventType, type MatrixEvent } from "matrix-js-sdk/src/matrix";
import { CallEvent, CallState, CallType, type MatrixCall } from "matrix-js-sdk/src/webrtc/call";
// oxlint-disable-next-line no-restricted-imports
import { EventEmitter } from "events";
import { LegacyCallHandlerEvent } from "../../LegacyCallHandler";
+14 -16
View File
@@ -712,19 +712,19 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
// Add watchers for each of the settings we just looked up
this.settingWatchers = this.settingWatchers.concat([
SettingsStore.watchSetting("showReadReceipts", roomId, (...[, , , value]) =>
this.setState({ showReadReceipts: value as boolean }),
this.setState({ showReadReceipts: value! }),
),
SettingsStore.watchSetting("showRedactions", roomId, (...[, , , value]) =>
this.setState({ showRedactions: value as boolean }),
this.setState({ showRedactions: value! }),
),
SettingsStore.watchSetting("showJoinLeaves", roomId, (...[, , , value]) =>
this.setState({ showJoinLeaves: value as boolean }),
this.setState({ showJoinLeaves: value! }),
),
SettingsStore.watchSetting("showAvatarChanges", roomId, (...[, , , value]) =>
this.setState({ showAvatarChanges: value as boolean }),
this.setState({ showAvatarChanges: value! }),
),
SettingsStore.watchSetting("showDisplaynameChanges", roomId, (...[, , , value]) =>
this.setState({ showDisplaynameChanges: value as boolean }),
this.setState({ showDisplaynameChanges: value! }),
),
]);
@@ -985,34 +985,32 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
this.context.resizeNotifier.on("isResizing", this.onIsResizing);
this.settingWatchers = [
SettingsStore.watchSetting("layout", null, (...[, , , value]) =>
this.setState({ layout: value as Layout }),
),
SettingsStore.watchSetting("layout", null, (...[, , , value]) => this.setState({ layout: value! })),
SettingsStore.watchSetting("lowBandwidth", null, (...[, , , value]) =>
this.setState({ lowBandwidth: value as boolean }),
this.setState({ lowBandwidth: value! }),
),
SettingsStore.watchSetting("alwaysShowTimestamps", null, (...[, , , value]) =>
this.setState({ alwaysShowTimestamps: value as boolean }),
this.setState({ alwaysShowTimestamps: value! }),
),
SettingsStore.watchSetting("showTwelveHourTimestamps", null, (...[, , , value]) =>
this.setState({ showTwelveHourTimestamps: value as boolean }),
this.setState({ showTwelveHourTimestamps: value! }),
),
SettingsStore.watchSetting(TimezoneHandler.USER_TIMEZONE_KEY, null, (...[, , , value]) =>
this.setState({ userTimezone: value as string }),
this.setState({ userTimezone: value! }),
),
SettingsStore.watchSetting("readMarkerInViewThresholdMs", null, (...[, , , value]) =>
this.setState({ readMarkerInViewThresholdMs: value as number }),
this.setState({ readMarkerInViewThresholdMs: value! }),
),
SettingsStore.watchSetting("readMarkerOutOfViewThresholdMs", null, (...[, , , value]) =>
this.setState({ readMarkerOutOfViewThresholdMs: value as number }),
this.setState({ readMarkerOutOfViewThresholdMs: value! }),
),
SettingsStore.watchSetting("showHiddenEventsInTimeline", null, (...[, , , value]) =>
this.setState({ showHiddenEvents: value as boolean }),
this.setState({ showHiddenEvents: value! }),
),
SettingsStore.watchSetting("urlPreviewsEnabled", null, this.onUrlPreviewsEnabledChange),
SettingsStore.watchSetting("urlPreviewsEnabled_e2ee", null, this.onUrlPreviewsEnabledChange),
SettingsStore.watchSetting("feature_dynamic_room_predecessors", null, (...[, , , value]) =>
this.setState({ msc3946ProcessDynamicPredecessor: value as boolean }),
this.setState({ msc3946ProcessDynamicPredecessor: value! }),
),
];
@@ -158,7 +158,7 @@ export default class ScrollPanel extends React.Component<IProps> {
return Promise.resolve(false);
},
onUnfillRequest: function (backwards: boolean, scrollToken: string) {},
onScroll: function () {},
onScroll: function (): void {},
};
private readonly pendingFillRequests: Record<"b" | "f", boolean | null> = {
@@ -102,8 +102,6 @@ function TabLabel<T extends string>({ tab, isActive, showToolip, onClick }: ITab
const label = _t(tab.label);
return (
// The RovingAccessibleComponent correctly sets the tabIndex based on roving context
// oxlint-disable-next-line jsx-a11y/interactive-supports-focus
<RovingAccessibleButton
className={classes}
onClick={onClick}
@@ -106,7 +106,7 @@ export default class ThreadView extends React.Component<IProps, IState> {
this.setupThreadListeners(this.state.thread);
this.layoutWatcherRef = SettingsStore.watchSetting("layout", null, (...[, , , value]) =>
this.setState({ layout: value as Layout }),
this.setState({ layout: value! }),
);
if (this.state.thread) {
@@ -172,7 +172,9 @@ export default class ViewSource extends React.Component<IProps, IState> {
{isEditing ? this.editSourceContent() : this.viewSourceContent()}
{!isEditing && canEdit && (
<div className="mx_Dialog_buttons">
<button onClick={() => this.onEdit()}>{_t("action|edit")}</button>
<button onClick={() => this.onEdit()} type="button">
{_t("action|edit")}
</button>
</div>
)}
</BaseDialog>
@@ -10,7 +10,7 @@ Please see LICENSE files in the repository root for full details.
import { vi, describe, it, expect, beforeEach, afterEach } from "vitest";
import React from "react";
import { act, render, screen } from "test-utils-rtl";
import EventEmitter from "events";
import EventEmitter from "node:events";
import { stubClient } from "test-utils";
import CompleteSecurity from "./CompleteSecurity";
@@ -11,7 +11,7 @@ Please see LICENSE files in the repository root for full details.
import { vi, describe, it, expect, beforeEach } from "vitest";
import { act, render, type RenderResult } from "test-utils-rtl";
import React, { type ComponentProps } from "react";
import EventEmitter from "events";
import EventEmitter from "node:events";
import { CryptoEvent } from "matrix-js-sdk/src/crypto-api";
import { sleep } from "matrix-js-sdk/src/utils";
@@ -64,10 +64,10 @@ export default class PasswordLogin extends React.PureComponent<IProps, IState> {
private [LoginField.Password]: Field | null = null;
public static defaultProps = {
onUsernameChanged: function () {},
onUsernameBlur: function () {},
onPhoneCountryChanged: function () {},
onPhoneNumberChanged: function () {},
onUsernameChanged: function (): void {},
onUsernameBlur: function (): void {},
onPhoneCountryChanged: function (): void {},
onPhoneNumberChanged: function (): void {},
loginIncorrect: false,
disableSubmit: false,
};
@@ -77,11 +77,13 @@ export default function AskInviteAnywayDialog({
</div>
<div className="mx_Dialog_buttons">
<button onClick={onGiveUpClicked}>{_t("action|close")}</button>
<button onClick={onInviteNeverWarnClicked}>
<button onClick={onGiveUpClicked} type="button">
{_t("action|close")}
</button>
<button onClick={onInviteNeverWarnClicked} type="button">
{inviteNeverWarnLabel ?? _t("invite|unable_find_profiles_invite_never_warn_label_default")}
</button>
<button onClick={onInviteClicked} autoFocus={true}>
<button onClick={onInviteClicked} autoFocus={true} type="button">
{inviteLabel ?? _t("invite|unable_find_profiles_invite_label_default")}
</button>
</div>
@@ -97,7 +97,7 @@ const DevtoolsDialog: React.FC<IProps> = ({ roomId, threadRootId, onFinished })
setTool([label, tool]);
};
return (
<button className="mx_DevTools_button" key={label} onClick={onClick}>
<button className="mx_DevTools_button" key={label} onClick={onClick} type="button">
{_t(label)}
</button>
);
@@ -74,7 +74,12 @@ export default class ErrorDialog extends React.Component<IProps, IState> {
{this.props.description || _t("error|dialog_description_default")}
</div>
<div className="mx_Dialog_buttons">
<button className="mx_Dialog_primary" onClick={this.onClick} autoFocus={this.props.focus}>
<button
className="mx_Dialog_primary"
onClick={this.onClick}
autoFocus={this.props.focus}
type="button"
>
{this.props.button || _t("action|ok")}
</button>
</div>
@@ -50,7 +50,7 @@ export default class SessionRestoreErrorDialog extends React.Component<IProps> {
const brand = SdkConfig.get().brand;
const clearStorageButton = (
<button onClick={this.onClearStorageClick} className="danger">
<button onClick={this.onClearStorageClick} className="danger" type="button">
{_t("error|session_restore|clear_storage_button")}
</button>
);
@@ -104,7 +104,11 @@ export default class UploadConfirmDialog extends React.Component<IProps, IState>
let uploadAllButton: JSX.Element | undefined;
if (this.props.currentIndex + 1 < this.props.totalFiles) {
uploadAllButton = <button onClick={this.onUploadAllClick}>{_t("upload_file|upload_all_button")}</button>;
uploadAllButton = (
<button onClick={this.onUploadAllClick} type="button">
{_t("upload_file|upload_all_button")}
</button>
);
}
return (
@@ -78,7 +78,7 @@ const BaseAccountDataExplorer: React.FC<IProps> = ({ events, Editor, actionLabel
};
return (
<button className="mx_DevTools_button" key={eventType} onClick={onClick}>
<button className="mx_DevTools_button" key={eventType} onClick={onClick} type="button">
{eventType}
</button>
);
@@ -61,7 +61,11 @@ const BaseTool: React.FC<XOR<IMinProps, IProps>> = ({
});
};
actionButton = <button onClick={onActionClick}>{_t(actionLabel)}</button>;
actionButton = (
<button onClick={onActionClick} type="button">
{_t(actionLabel)}
</button>
);
}
return (
@@ -69,7 +73,9 @@ const BaseTool: React.FC<XOR<IMinProps, IProps>> = ({
<div className={classNames("mx_DevTools_content", className)}>{children}</div>
<div className="mx_Dialog_buttons">
{extraButton}
<button onClick={onBackClick}>{_t("action|back")}</button>
<button onClick={onBackClick} type="button">
{_t("action|back")}
</button>
{actionButton}
</div>
</>
@@ -50,7 +50,7 @@ const FilteredList: React.FC<IProps> = ({ children, query, onChange }) => {
};
return (
<button className="mx_DevTools_button" onClick={showMore}>
<button className="mx_DevTools_button" onClick={showMore} type="button">
{_t("common|and_n_others", { count: overflowCount })}
</button>
);
@@ -100,6 +100,7 @@ const StateEventButton: React.FC<StateEventButtonProps> = ({ label, onClick }) =
mx_DevTools_RoomStateExplorer_button_emptyString: !trimmed,
})}
onClick={onClick}
type="button"
>
{content}
</button>
@@ -148,7 +149,11 @@ const RoomStateExplorerEventType: React.FC<IEventTypeProps> = ({ eventType, onBa
const onHistoryClick = (): void => {
setHistory(true);
};
const extraButton = <button onClick={onHistoryClick}>{_t("devtools|see_history")}</button>;
const extraButton = (
<button onClick={onHistoryClick} type="button">
{_t("devtools|see_history")}
</button>
);
return <EventViewer mxEvent={event} onBack={_onBack} Editor={StateEventEditor} extraButton={extraButton} />;
}
@@ -56,7 +56,11 @@ export const StickyStateExplorer: React.FC<IDevtoolsProps> = ({ onBack, setTool
<Alert
type="critical"
title={_t("common|error")}
actions={<button onClick={onBack}>{_t("action|back")}</button>}
actions={
<button onClick={onBack} type="button">
{_t("action|back")}
</button>
}
>
{_t("devtools|sticky_events_not_supported")}
</Alert>
@@ -107,7 +111,12 @@ export const StickyStateExplorer: React.FC<IDevtoolsProps> = ({ onBack, setTool
<BaseTool onBack={onBack} actionLabel={_td("devtools|send_custom_sticky_event")} onAction={onAction}>
<p>
{uniqueEventTypes.map((eventType) => (
<button key={eventType} className="mx_DevTools_button" onClick={() => setEventType(eventType)}>
<button
key={eventType}
className="mx_DevTools_button"
onClick={() => setEventType(eventType)}
type="button"
>
{eventType.length > 0 ? eventType : _t("devtools|empty_string")}
</button>
))}
@@ -88,7 +88,7 @@ interface UserButtonProps {
*/
const UserButton: React.FC<UserButtonProps> = ({ member, onClick }) => {
return (
<button className="mx_DevTools_button" onClick={onClick}>
<button className="mx_DevTools_button" onClick={onClick} type="button">
{member.userId}
</button>
);
@@ -273,7 +273,7 @@ const DeviceButton: React.FC<DeviceButtonProps> = ({ crypto, device, onClick })
null,
);
return (
<button className="mx_DevTools_button" onClick={onClick}>
<button className="mx_DevTools_button" onClick={onClick} type="button">
{verificationIcon}
{device.deviceId}
</button>
@@ -53,7 +53,12 @@ const WidgetExplorer: React.FC<IDevtoolsProps> = ({ onBack }) => {
<BaseTool onBack={onBack}>
<FilteredList query={query} onChange={setQuery}>
{widgets.map((w) => (
<button className="mx_DevTools_button" key={w.url + w.eventId} onClick={() => setWidget(w)}>
<button
className="mx_DevTools_button"
key={w.url + w.eventId}
onClick={() => setWidget(w)}
type="button"
>
{w.url}
</button>
))}
@@ -538,7 +538,7 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", initialFilter = n
});
// we intentionally ignore changes to the rovingContext for the purpose of this hook
// we only want to reset the focus whenever the results or filters change
// eslint-disable-next-line
// oxlint-disable-next-line react-hooks/exhaustive-deps
}, [results, filter]);
const viewRoom = (
@@ -238,9 +238,7 @@ export default class Dropdown extends React.Component<DropdownProps, IState> {
highlightedOption: nextKey,
});
(
this.dropdownRootElement?.querySelector(`#${this.props.id}__${nextKey}`) as HTMLLIElement
)?.focus();
this.dropdownRootElement?.querySelector<HTMLLIElement>(`#${this.props.id}__${nextKey}`)?.focus();
} else {
this.setState({ expanded: true });
}
@@ -251,9 +249,7 @@ export default class Dropdown extends React.Component<DropdownProps, IState> {
this.setState({
highlightedOption: prevKey,
});
(
this.dropdownRootElement?.querySelector(`#${this.props.id}__${prevKey}`) as HTMLLIElement
)?.focus();
this.dropdownRootElement?.querySelector<HTMLLIElement>(`#${this.props.id}__${prevKey}`)?.focus();
} else {
this.setState({ expanded: true });
}
@@ -319,7 +315,7 @@ export default class Dropdown extends React.Component<DropdownProps, IState> {
<MenuOption
id={`${this.props.id}__${child.key}`}
key={child.key}
dropdownKey={child.key as string}
dropdownKey={child.key!}
highlighted={highlighted}
onMouseEnter={this.setHighlightedOption}
onClick={this.onMenuOptionClick}
@@ -42,6 +42,7 @@ export default class Spoiler extends React.Component<IProps, IState> {
<button
className={"mx_EventTile_spoiler" + (this.state.visible ? " visible" : "")}
onClick={this.toggleVisible}
type="button"
>
{reason}
&nbsp;
@@ -100,6 +100,7 @@ class Header extends React.PureComponent<IProps> {
tabIndex={category.firstVisible ? 0 : -1} // roving
aria-selected={category.visible}
aria-controls={`mx_EmojiPicker_category_${category.id}`}
type="button"
>
{category.emoji}
</button>
@@ -55,6 +55,7 @@ class Search extends React.PureComponent<IProps> {
onClick={() => this.props.onChange("")}
className="mx_EmojiPicker_search_clear"
title={_t("emoji_picker|cancel_search_label")}
type="button"
>
<CloseIcon />
</button>
@@ -296,7 +296,7 @@ const MESSAGE_BODY_TYPES = new Map<string, MBodyComponent>([
// Render a body using the picked factory.
// Falls back to the provided factory when msgtype has no specific handler.
export function renderMBody(props: IBodyProps, fallbackFactory?: MBodyComponent): JSX.Element | null {
const BodyType = MESSAGE_BODY_TYPES.get(props.mxEvent.getContent().msgtype as string) ?? fallbackFactory;
const BodyType = MESSAGE_BODY_TYPES.get(props.mxEvent.getContent().msgtype!) ?? fallbackFactory;
if (!BodyType) {
return null;
}
@@ -92,10 +92,10 @@ export default class TimelineCard extends React.Component<IProps, IState> {
this.context.roomViewStore.addListener(UPDATE_EVENT, this.onRoomViewStoreUpdate);
this.dispatcherRef = dis.register(this.onAction);
this.readReceiptsSettingWatcher = SettingsStore.watchSetting("showReadReceipts", null, (...[, , , value]) =>
this.setState({ showReadReceipts: value as boolean }),
this.setState({ showReadReceipts: value! }),
);
this.layoutWatcherRef = SettingsStore.watchSetting("layout", null, (...[, , , value]) =>
this.setState({ layout: value as Layout }),
this.setState({ layout: value! }),
);
}
@@ -195,7 +195,7 @@ const UserInfo: React.FC<IProps> = ({ user, room, onClose, phase = RightPanelPha
let content: JSX.Element | undefined;
switch (phase) {
case RightPanelPhases.MemberInfo:
content = <UserInfoBasicView room={room as Room} member={member} />;
content = <UserInfoBasicView room={room!} member={member} />;
break;
case RightPanelPhases.EncryptionPanel:
classes.push("mx_UserInfo_smallAvatar");
@@ -485,6 +485,7 @@ export default function RoomHeader({
: () => sdkContext.rightPanelStore.showOrHidePhase(RightPanelPhases.RoomSummary)
}
className="mx_RoomHeader_infoWrapper"
type="button"
>
<Box flex="1" className="mx_RoomHeader_info">
<Text
@@ -23,6 +23,7 @@ exports[`RoomHeader > dm > does not show the face pile for DMs 1`] = `
aria-label="Room info"
class="mx_RoomHeader_infoWrapper"
tabindex="0"
type="button"
>
<div
class="mx_RoomHeader_info _box-flex_1odfs_9"
@@ -232,7 +232,7 @@ export default class Notifications extends React.PureComponent<EmptyObject, ISta
public componentDidMount(): void {
this.settingWatchers = [
SettingsStore.watchSetting("deviceNotificationsEnabled", null, (...[, , , , value]) => {
this.setState({ deviceNotificationsEnabled: value as boolean });
this.setState({ deviceNotificationsEnabled: value! });
}),
];
@@ -78,7 +78,7 @@ export default class VoiceUserSettingsTab extends React.Component<EmptyObject, I
this.legacyCallsEnabledWatcherRef = SettingsStore.watchSetting(
"enableLegacyCallsVoip",
null,
(...[, , , , value]) => this.setState({ enableLegacyCallsVoip: value as boolean }),
(...[, , , , value]) => this.setState({ enableLegacyCallsVoip: value! }),
);
const canSeeDeviceLabels = await MediaDeviceHandler.hasAnyLabeledDevices();
@@ -501,38 +501,20 @@ export default class LegacyCallView extends React.Component<IProps, IState> {
// We've already checked that we have feeds so we cast away the optional when passing the feed
return (
<div className="mx_LegacyCallView_content" onMouseMove={this.onMouseMove}>
<VideoFeed
feed={primaryFeed as CallFeed}
call={call}
pipMode={pipMode}
onResize={onResize}
primary={true}
/>
<VideoFeed feed={primaryFeed!} call={call} pipMode={pipMode} onResize={onResize} primary={true} />
</div>
);
} else if (secondaryFeed) {
return (
<div className="mx_LegacyCallView_content" onMouseMove={this.onMouseMove}>
<VideoFeed
feed={primaryFeed as CallFeed}
call={call}
pipMode={pipMode}
onResize={onResize}
primary={true}
/>
<VideoFeed feed={primaryFeed!} call={call} pipMode={pipMode} onResize={onResize} primary={true} />
{secondaryFeedElement}
</div>
);
} else {
return (
<div className="mx_LegacyCallView_content" onMouseMove={this.onMouseMove}>
<VideoFeed
feed={primaryFeed as CallFeed}
call={call}
pipMode={pipMode}
onResize={onResize}
primary={true}
/>
<VideoFeed feed={primaryFeed!} call={call} pipMode={pipMode} onResize={onResize} primary={true} />
{sidebarShown && (
<LegacyCallViewSidebar feeds={sidebarFeeds} call={call} pipMode={Boolean(pipMode)} />
)}
+1
View File
@@ -9,6 +9,7 @@ Please see LICENSE files in the repository root for full details.
import { useRef, useEffect, useState, useCallback, type DependencyList } from "react";
import { type ListenerMap, type TypedEventEmitter } from "matrix-js-sdk/src/matrix";
// oxlint-disable-next-line no-restricted-imports
import type { EventEmitter } from "events";
type Handler = (...args: any[]) => void;
+1
View File
@@ -42,6 +42,7 @@ export async function setLanguage(...preferredLangs: string[]): Promise<void> {
await SettingsStore.setValue("language", null, SettingLevel.DEVICE, chosenLanguage);
// Adds a lot of noise to test runs, so disable logging there.
// oxlint-disable-next-line node/no-process-env
if (process.env.NODE_ENV !== "test") {
logger.log("set language to " + chosenLanguage);
}
+1
View File
@@ -6,6 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
// oxlint-disable-next-line no-restricted-imports
import { EventEmitter } from "events";
import {
RoomMember,
+1
View File
@@ -26,6 +26,7 @@ import {
MatrixRTCSessionManagerEvents,
} from "matrix-js-sdk/src/matrixrtc";
// oxlint-disable-next-line no-restricted-imports
import type EventEmitter from "events";
import type { IApp } from "../stores/WidgetStore";
import SettingsStore from "../settings/SettingsStore";
+1
View File
@@ -201,6 +201,7 @@ export async function initSentry(sentryConfig: IConfigOptions["sentry"]): Promis
Sentry.init({
dsn: sentryConfig.dsn,
// oxlint-disable-next-line node/no-process-env
release: process.env.VERSION,
environment: sentryConfig.environment,
defaultIntegrations: false,
+1
View File
@@ -5,6 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
// oxlint-disable-next-line no-restricted-imports
import EventEmitter from "events";
import { type MatrixEvent, RoomStateEvent, type RoomState } from "matrix-js-sdk/src/matrix";
+1
View File
@@ -6,6 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
// oxlint-disable-next-line no-restricted-imports
import { EventEmitter } from "events";
import AwaitLock from "await-lock";
@@ -5,6 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
// oxlint-disable-next-line no-restricted-imports
import EventEmitter from "events";
import { type MatrixClient } from "matrix-js-sdk/src/matrix";
import { logger } from "matrix-js-sdk/src/logger";
@@ -9,7 +9,7 @@
import { describe, it, expect, vi } from "vitest";
import { type EventTimeline, EventType, RoomEvent } from "matrix-js-sdk/src/matrix";
import { EventEmitter } from "stream";
import { EventEmitter } from "node:events";
import { mkEvent, mkRoom, mkRoomMember, stubClient } from "../../test/test-utils";
import { CallStoreEvent, type CallStore } from "./CallStore";
@@ -6,6 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
// oxlint-disable-next-line no-restricted-imports
import EventEmitter from "events";
import { type ComponentClass } from "../@types/common";
@@ -7,6 +7,7 @@
*/
import { type MatrixClient, SyncState } from "matrix-js-sdk/src/matrix";
// oxlint-disable-next-line no-restricted-imports
import { EventEmitter } from "events";
import { MatrixClientPeg } from "../MatrixClientPeg";
+1
View File
@@ -15,6 +15,7 @@ import { KnownMembership } from "matrix-js-sdk/src/types";
import { logger } from "matrix-js-sdk/src/logger";
import { type ViewRoom as ViewRoomEvent } from "@matrix-org/analytics-events/types/typescript/ViewRoom";
import { type JoinedRoom as JoinedRoomEvent } from "@matrix-org/analytics-events/types/typescript/JoinedRoom";
// oxlint-disable-next-line no-restricted-imports
import EventEmitter from "events";
import {
RoomViewLifecycle,
@@ -6,6 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
// oxlint-disable-next-line no-restricted-imports
import EventEmitter from "events";
import {
type KeyBackupInfo,
@@ -6,6 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
// oxlint-disable-next-line no-restricted-imports
import EventEmitter from "events";
import { base32 } from "rfc4648";
import { type RoomType } from "matrix-js-sdk/src/matrix";
+1
View File
@@ -6,6 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
// oxlint-disable-next-line no-restricted-imports
import EventEmitter from "events";
import { logger } from "matrix-js-sdk/src/logger";
import { type JSX } from "react";
+1
View File
@@ -6,6 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
// oxlint-disable-next-line no-restricted-imports
import EventEmitter from "events";
export enum UI_EVENTS {
+1
View File
@@ -6,6 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
// oxlint-disable-next-line no-restricted-imports
import EventEmitter from "events";
import { type IWidget } from "matrix-widget-api";
import { type MatrixEvent } from "matrix-js-sdk/src/matrix";
@@ -7,6 +7,7 @@ Please see LICENSE files in the repository root for full details.
*/
import { type MatrixClient } from "matrix-js-sdk/src/matrix";
// oxlint-disable-next-line no-restricted-imports
import { EventEmitter } from "events";
import { type EchoContext } from "./EchoContext";
@@ -9,7 +9,7 @@ Please see LICENSE files in the repository root for full details.
// @vitest-environment happy-dom
import { vi, describe, it, expect, beforeAll, beforeEach, afterEach } from "vitest";
import { type EventEmitter } from "events";
import { type EventEmitter } from "node:events";
import {
EventType,
RoomMember,
+2 -1
View File
@@ -9,10 +9,11 @@ Please see LICENSE files in the repository root for full details.
import { describe, it, expect } from "vitest";
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { blobIsAnimated, mayBeAnimated } from "./Image";
const imagesDir = path.resolve(__dirname, "../../test/unit-tests/images");
const imagesDir = fileURLToPath(import.meta.resolve("../../test/unit-tests/images"));
describe("Image", () => {
describe("mayBeAnimated", () => {
+1
View File
@@ -15,6 +15,7 @@ Please see LICENSE files in the repository root for full details.
* @event module:utils~ResizeNotifier#"middlePanelResizedNoisy"
*/
// oxlint-disable-next-line no-restricted-imports
import { EventEmitter } from "events";
import { throttle } from "lodash";
+15 -16
View File
@@ -212,17 +212,6 @@ export class UrlPreviewFetcher {
* Convert an MSC4095 URL preview bundle item to a UrlPreview
*/
public previewFromBundle(single: UnstableBundledUrlPreviewSingle): UrlPreview {
// missing fields from the bundle because backend does provide it:
// - siteName (can be computed)
// - favicon
// - media is a video or audio?
// TODO in next PR: URL previews in encrypted chat?
const hasImage =
typeof single["og:image"] === "string" &&
typeof single["og:image:type"] === "string" &&
typeof single["og:image:width"] === "number" &&
typeof single["og:image:height"] === "number";
const preview: UrlPreview = {
link: single.matched_url,
title: single["og:title"] ?? single.matched_url,
@@ -232,7 +221,17 @@ export class UrlPreviewFetcher {
ogUrl: single["og:url"],
};
if (hasImage) {
// missing fields from the bundle because backend does provide it:
// - siteName (can be computed)
// - favicon
// - media is a video or audio?
// TODO in next PR: URL previews in encrypted chat?
if (
typeof single["og:image"] === "string" &&
typeof single["og:image:type"] === "string" &&
typeof single["og:image:width"] === "number" &&
typeof single["og:image:height"] === "number"
) {
const media = mediaFromMxc(single["og:image"], this.client);
const thumb = media.getThumbnailOfSourceHttp(PREVIEW_WIDTH_PX, PREVIEW_HEIGHT_PX, "scale");
@@ -245,10 +244,10 @@ export class UrlPreviewFetcher {
preview.image = {
imageThumb: thumb,
imageFull: media.srcHttp,
imageType: single["og:image:type"] as string,
mxcImageFull: single["og:image"] as string,
width: single["og:image:width"] as number,
height: single["og:image:height"] as number,
imageType: single["og:image:type"],
mxcImageFull: single["og:image"],
width: single["og:image:width"],
height: single["og:image:height"],
playable: false, // TODO: do we know?
};
}
+1 -1
View File
@@ -135,7 +135,7 @@ export function arrayTrimFill<T>(a: T[], len: number, seed: T[]): T[] {
* @returns A copy of the array.
*/
export function arrayFastClone<T>(a: T[]): T[] {
return a.slice(0, a.length);
return a.slice(0);
}
/**
+1 -1
View File
@@ -63,7 +63,7 @@ export async function createThumbnail(
let context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D;
try {
canvas = new window.OffscreenCanvas(targetWidth, targetHeight);
context = canvas.getContext("2d") as OffscreenCanvasRenderingContext2D;
context = canvas.getContext("2d")!;
} catch {
// Fallback support for other browsers (Safari and Firefox for now)
canvas = document.createElement("canvas");
@@ -10,7 +10,7 @@ Please see LICENSE files in the repository root for full details.
import { vi, describe, it, expect, afterAll, beforeEach } from "vitest";
import { getMockClientWithEventEmitter } from "test-utils/client";
import { type EventEmitter } from "events";
import { type EventEmitter } from "node:events";
import { Room, RoomMember, EventType, MatrixEvent } from "matrix-js-sdk/src/matrix";
import { KnownMembership } from "matrix-js-sdk/src/types";
+1
View File
@@ -36,6 +36,7 @@ import { ModuleNotificationDecoration } from "../modules/components/ModuleNotifi
import Login from "../Login.ts";
import { startOAuthLogin } from "../utils/oauth/authorize.ts";
// oxlint-disable-next-line node/no-process-env
logger.log(`Application is running in ${process.env.NODE_ENV} mode`);
window.matrixLogger = logger;
+2 -2
View File
@@ -22,10 +22,10 @@ import "../../res/css/_index.pcss";
// Require common CSS here; this will make webpack process it into bundle.css.
// Our own CSS (which is themed) is imported via separate webpack entry points
// in webpack.config.js
// eslint-disable-next-line @typescript-eslint/no-require-imports
// eslint-disable-next-line @typescript-eslint/no-require-imports,import/no-commonjs,unicorn/prefer-module
require("katex/dist/katex.css");
// eslint-disable-next-line @typescript-eslint/no-require-imports
// eslint-disable-next-line @typescript-eslint/no-require-imports,import/no-commonjs,unicorn/prefer-module
require("./localstorage-fix");
// Patch a fake window.TouchEvent for re-resizable's unguarded `instanceof TouchEvent`.
@@ -59,7 +59,7 @@ export const mobileApps: Record<MobileAppVariant, MobileAppMetadata> = {
};
export function updateMobilePage(metadata: MobileAppMetadata, deepLinkUrl: string, server: string | undefined): void {
const appleMeta = document.querySelector('meta[name="apple-itunes-app"]') as Element;
const appleMeta = document.querySelector('meta[name="apple-itunes-app"]')!;
appleMeta.setAttribute("content", `app-id=${metadata.appleAppId}`);
if (server) {
@@ -136,6 +136,7 @@ describe("WebPlatform", () => {
});
describe("app version", () => {
// oxlint-disable-next-line node/no-process-env
const envVersion = process.env.VERSION;
const prodVersion = "1.10.13";
@@ -35,6 +35,7 @@ function getNormalizedAppVersion(version: string): string {
}
export default class WebPlatform extends BasePlatform {
// oxlint-disable-next-line node/no-process-env
private static readonly VERSION = process.env.VERSION!; // baked in by Webpack
private readonly registerServiceWorkerPromise: Promise<void>;
+1 -1
View File
@@ -48,7 +48,7 @@ describe("mxSendRageshake", () => {
});
it.each(["", " ", undefined, null])("Does not send a rageshake if text is '%s'", async (text) => {
await window.mxSendRageshake(text as string);
await window.mxSendRageshake(text!);
expect(fetchMock).not.toHaveFetched();
});
@@ -122,7 +122,7 @@ export class ImageBodyViewModel
this.state = initialState;
const imageSizeWatcherRef = SettingsStore.watchSetting("Images.size", null, (_s, _r, _l, _nvl, value) => {
this.setImageSize(value as ImageSize);
this.setImageSize(value!);
});
this.disposables.track(() => SettingsStore.unwatchSetting(imageSizeWatcherRef));
}
@@ -109,7 +109,7 @@ export class VideoBodyViewModel
this.state = initialState;
const imageSizeWatcherRef = SettingsStore.watchSetting("Images.size", null, (_s, _r, _l, _nvl, value) => {
this.setImageSize(value as ImageSize);
this.setImageSize(value!);
});
this.disposables.track(() => SettingsStore.unwatchSetting(imageSizeWatcherRef));
}
@@ -5,7 +5,7 @@
* Please see LICENSE files in the repository root for full details.
*/
import { EventEmitter } from "events";
import { EventEmitter } from "node:events";
import { type RoomMember, type MatrixEvent, EventType } from "matrix-js-sdk/src/matrix";
import { mkEvent, mkRoomMember } from "../../../../../../test/test-utils";
@@ -7,7 +7,7 @@
// @vitest-environment happy-dom
import EventEmitter from "events";
import EventEmitter from "node:events";
import { type CallStore, CallStoreEvent } from "../../../../stores/CallStore";
import { CollapseOnCallResizeBehaviour } from "./CollapseOnCallResizeBehaviour";