Perform dead code analysis with Knip (#2575)
* Install Knip * Clarify an import that was confusing Knip * Fix issues detected by Knip Including cleaning up some unused code and dependencies, using a React hook that we unintentionally stopped using, and also adding some previously undeclared dependencies. * Run dead code analysis in lint script and CI --------- Co-authored-by: Timo <toger5@hotmail.de>
This commit is contained in:
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
Copyright 2023 New Vector Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { FC, ReactNode } from "react";
|
||||
|
||||
import styles from "./Banner.module.css";
|
||||
|
||||
interface Props {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
export const Banner: FC<Props> = ({ children }) => {
|
||||
return <div className={styles.banner}>{children}</div>;
|
||||
};
|
||||
@@ -40,10 +40,7 @@ import { Caption } from "../typography/Typography";
|
||||
import { Form } from "../form/Form";
|
||||
import { AnalyticsNotice } from "../analytics/AnalyticsNotice";
|
||||
import { E2eeType } from "../e2ee/e2eeType";
|
||||
import {
|
||||
useSetting,
|
||||
optInAnalytics as optInAnalyticsSetting,
|
||||
} from "../settings/settings";
|
||||
import { useOptInAnalytics } from "../settings/settings";
|
||||
|
||||
interface Props {
|
||||
client: MatrixClient;
|
||||
@@ -52,7 +49,7 @@ interface Props {
|
||||
export const RegisteredView: FC<Props> = ({ client }) => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<Error>();
|
||||
const [optInAnalytics] = useSetting(optInAnalyticsSetting);
|
||||
const [optInAnalytics] = useOptInAnalytics();
|
||||
const history = useHistory();
|
||||
const { t } = useTranslation();
|
||||
const [joinExistingCallModalOpen, setJoinExistingCallModalOpen] =
|
||||
|
||||
@@ -43,16 +43,13 @@ import { generateRandomName } from "../auth/generateRandomName";
|
||||
import { AnalyticsNotice } from "../analytics/AnalyticsNotice";
|
||||
import { Config } from "../config/Config";
|
||||
import { E2eeType } from "../e2ee/e2eeType";
|
||||
import {
|
||||
useSetting,
|
||||
optInAnalytics as optInAnalyticsSetting,
|
||||
} from "../settings/settings";
|
||||
import { useOptInAnalytics } from "../settings/settings";
|
||||
|
||||
export const UnauthenticatedView: FC = () => {
|
||||
const { setClient } = useClient();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<Error>();
|
||||
const [optInAnalytics] = useSetting(optInAnalyticsSetting);
|
||||
const [optInAnalytics] = useOptInAnalytics();
|
||||
const { recaptchaKey, register } = useInteractiveRegistration();
|
||||
const { execute, reset, recaptchaId } = useRecaptcha(recaptchaKey);
|
||||
|
||||
|
||||
@@ -35,10 +35,7 @@ import { LobbyView } from "./LobbyView";
|
||||
import { E2eeType } from "../e2ee/e2eeType";
|
||||
import { useProfile } from "../profile/useProfile";
|
||||
import { useMuteStates } from "./MuteStates";
|
||||
import {
|
||||
useSetting,
|
||||
optInAnalytics as optInAnalyticsSetting,
|
||||
} from "../settings/settings";
|
||||
import { useOptInAnalytics } from "../settings/settings";
|
||||
|
||||
export const RoomPage: FC = () => {
|
||||
const {
|
||||
@@ -83,7 +80,7 @@ export const RoomPage: FC = () => {
|
||||
registerPasswordlessUser,
|
||||
]);
|
||||
|
||||
const [optInAnalytics, setOptInAnalytics] = useSetting(optInAnalyticsSetting);
|
||||
const [optInAnalytics, setOptInAnalytics] = useOptInAnalytics();
|
||||
useEffect(() => {
|
||||
// During the beta, opt into analytics by default
|
||||
if (optInAnalytics === null && setOptInAnalytics) setOptInAnalytics(true);
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
Copyright 2022 New Vector Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { useEffect } from "react";
|
||||
|
||||
import { platform } from "../Platform";
|
||||
|
||||
export function usePageUnload(callback: () => void): void {
|
||||
useEffect(() => {
|
||||
let pageVisibilityTimeout: ReturnType<typeof setTimeout>;
|
||||
|
||||
function onBeforeUnload(event: PageTransitionEvent): void {
|
||||
if (event.type === "visibilitychange") {
|
||||
if (document.visibilityState === "visible") {
|
||||
clearTimeout(pageVisibilityTimeout);
|
||||
} else {
|
||||
// Wait 5 seconds before closing the page to avoid accidentally leaving
|
||||
// TODO: Make this configurable?
|
||||
pageVisibilityTimeout = setTimeout(() => {
|
||||
callback();
|
||||
}, 5000);
|
||||
}
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
// iOS doesn't fire beforeunload event, so leave the call when you hide the page.
|
||||
if (platform === "ios") {
|
||||
window.addEventListener("pagehide", onBeforeUnload);
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
document.addEventListener("visibilitychange", onBeforeUnload);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
window.addEventListener("beforeunload", onBeforeUnload);
|
||||
|
||||
return (): void => {
|
||||
window.removeEventListener("pagehide", onBeforeUnload);
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
document.removeEventListener("visibilitychange", onBeforeUnload);
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
window.removeEventListener("beforeunload", onBeforeUnload);
|
||||
clearTimeout(pageVisibilityTimeout);
|
||||
};
|
||||
}, [callback]);
|
||||
}
|
||||
@@ -42,9 +42,9 @@ import {
|
||||
import { widget } from "../widget";
|
||||
import {
|
||||
useSetting,
|
||||
optInAnalytics as optInAnalyticsSetting,
|
||||
developerSettingsTab as developerSettingsTabSetting,
|
||||
duplicateTiles as duplicateTilesSetting,
|
||||
useOptInAnalytics,
|
||||
} from "./settings";
|
||||
import { isFirefox } from "../Platform";
|
||||
|
||||
@@ -77,7 +77,7 @@ export const SettingsModal: FC<Props> = ({
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [optInAnalytics, setOptInAnalytics] = useSetting(optInAnalyticsSetting);
|
||||
const [optInAnalytics, setOptInAnalytics] = useOptInAnalytics();
|
||||
const [developerSettingsTab, setDeveloperSettingsTab] = useSetting(
|
||||
developerSettingsTabSetting,
|
||||
);
|
||||
|
||||
@@ -15,7 +15,6 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
import { useEffect } from "react";
|
||||
import EventEmitter, { EventMap } from "typed-emitter";
|
||||
|
||||
import type {
|
||||
Listener,
|
||||
@@ -60,20 +59,3 @@ export function useTypedEventEmitter<
|
||||
};
|
||||
}, [emitter, eventType, listener]);
|
||||
}
|
||||
|
||||
// Shortcut for registering a listener on an eventemitter3 EventEmitter (ie. what the LiveKit SDK uses)
|
||||
export function useEventEmitterThree<
|
||||
EventType extends keyof T,
|
||||
T extends EventMap,
|
||||
>(
|
||||
emitter: EventEmitter<T>,
|
||||
eventType: EventType,
|
||||
listener: T[EventType],
|
||||
): void {
|
||||
useEffect(() => {
|
||||
emitter.on(eventType, listener);
|
||||
return (): void => {
|
||||
emitter.off(eventType, listener);
|
||||
};
|
||||
}, [emitter, eventType, listener]);
|
||||
}
|
||||
|
||||
@@ -50,9 +50,6 @@ export const useLocalStorage = (
|
||||
];
|
||||
};
|
||||
|
||||
export const getLocalStorageItem = (key: string): LocalStorageItem =>
|
||||
localStorage.getItem(key);
|
||||
|
||||
export const setLocalStorageItem = (key: string, value: string): void => {
|
||||
localStorage.setItem(key, value);
|
||||
localStorageBus.emit(key, value);
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
Copyright 2023 New Vector Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { useRef } from "react";
|
||||
|
||||
/**
|
||||
* React hook that returns the value given on the previous render.
|
||||
*/
|
||||
export function usePrevious<T>(value: T): T | undefined {
|
||||
const ref = useRef<T>();
|
||||
const previous = ref.current;
|
||||
ref.current = value;
|
||||
return previous;
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
Copyright 2023 New Vector Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Gets the index of the last element in the array to satsify the given
|
||||
* predicate.
|
||||
*/
|
||||
// TODO: remove this once TypeScript recognizes the existence of
|
||||
// Array.prototype.findLastIndex
|
||||
export function findLastIndex<T>(
|
||||
array: T[],
|
||||
predicate: (item: T, index: number) => boolean,
|
||||
): number | null {
|
||||
for (let i = array.length - 1; i >= 0; i--) {
|
||||
if (predicate(array[i], i)) return i;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the number of elements in an array that satsify the given predicate.
|
||||
*/
|
||||
export const count = <T>(
|
||||
array: T[],
|
||||
predicate: (item: T, index: number) => boolean,
|
||||
): number =>
|
||||
array.reduce(
|
||||
(acc, item, index) => (predicate(item, index) ? acc + 1 : acc),
|
||||
0,
|
||||
);
|
||||
@@ -246,38 +246,6 @@ export function sanitiseRoomNameInput(input: string): string {
|
||||
return input;
|
||||
}
|
||||
|
||||
/**
|
||||
* XXX: What is this trying to do? It looks like it's getting the localpart from
|
||||
* a room alias, but why is it splitting on hyphens and then putting spaces in??
|
||||
* @param roomId
|
||||
* @returns
|
||||
*/
|
||||
export function roomNameFromRoomId(roomId: string): string {
|
||||
return roomId
|
||||
.match(/([^:]+):.*$/)![1]
|
||||
.substring(1)
|
||||
.split("-")
|
||||
.map((part) =>
|
||||
part.length > 0 ? part.charAt(0).toUpperCase() + part.slice(1) : part,
|
||||
)
|
||||
.join(" ")
|
||||
.toLowerCase();
|
||||
}
|
||||
|
||||
export function isLocalRoomId(roomId: string, client: MatrixClient): boolean {
|
||||
if (!roomId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const parts = roomId.match(/[^:]+:(.*)$/)!;
|
||||
|
||||
if (parts.length < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return parts[1] === client.getDomain();
|
||||
}
|
||||
|
||||
interface CreateRoomResult {
|
||||
roomId: string;
|
||||
alias?: string;
|
||||
|
||||
@@ -31,21 +31,6 @@ export enum ElementWidgetActions {
|
||||
HangupCall = "im.vector.hangup",
|
||||
TileLayout = "io.element.tile_layout",
|
||||
SpotlightLayout = "io.element.spotlight_layout",
|
||||
|
||||
// Element Call -> host requesting to start a screenshare
|
||||
// (ie. expects a ScreenshareStart once the user has picked a source)
|
||||
// Element Call -> host requesting to start a screenshare
|
||||
// (ie. expects a ScreenshareStart once the user has picked a source)
|
||||
// replies with { pending } where pending is true if the host has asked
|
||||
// the user to choose a window and false if not (ie. if the host isn't
|
||||
// running within Electron)
|
||||
ScreenshareRequest = "io.element.screenshare_request",
|
||||
// host -> Element Call telling EC to start screen sharing with
|
||||
// the given source
|
||||
ScreenshareStart = "io.element.screenshare_start",
|
||||
// host -> Element Call telling EC to stop screen sharing, or that
|
||||
// the user cancelled when selecting a source after a ScreenshareRequest
|
||||
ScreenshareStop = "io.element.screenshare_stop",
|
||||
// This can be sent as from or to widget
|
||||
// fromWidget: updates the client about the current device mute state
|
||||
// toWidget: the client requests a specific device mute configuration
|
||||
@@ -68,10 +53,6 @@ export interface JoinCallData {
|
||||
videoInput: string | null;
|
||||
}
|
||||
|
||||
export interface ScreenshareStartData {
|
||||
desktopCapturerSourceId: string;
|
||||
}
|
||||
|
||||
export interface WidgetHelpers {
|
||||
api: WidgetApi;
|
||||
lazyActions: LazyEventEmitter;
|
||||
@@ -101,8 +82,6 @@ export const widget = ((): WidgetHelpers | null => {
|
||||
ElementWidgetActions.HangupCall,
|
||||
ElementWidgetActions.TileLayout,
|
||||
ElementWidgetActions.SpotlightLayout,
|
||||
ElementWidgetActions.ScreenshareStart,
|
||||
ElementWidgetActions.ScreenshareStop,
|
||||
ElementWidgetActions.DeviceMute,
|
||||
].forEach((action) => {
|
||||
api.on(`action:${action}`, (ev: CustomEvent<IWidgetApiRequest>) => {
|
||||
|
||||
Reference in New Issue
Block a user