Format code

This commit is contained in:
Robin
2023-10-11 10:42:04 -04:00
parent b28e465122
commit 614bc82402
112 changed files with 628 additions and 602 deletions

View File

@@ -14,7 +14,7 @@ module.exports = {
Array.isArray(item) &&
item.length > 0 &&
item[0].name === "vite-plugin-mdx"
)
),
);
config.plugins.push(svgrPlugin());
config.resolve = config.resolve || {};

View File

@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />

View File

@@ -58,7 +58,7 @@ export const Avatar: FC<Props> = ({
Object.values(Size).includes(size as Size)
? sizes.get(size as Size)
: (size as number),
[size]
[size],
);
const resolvedSrc = useMemo(() => {

View File

@@ -190,7 +190,7 @@ export const ClientProvider: FC<Props> = ({ children }) => {
user: session.user_id,
password: session.tempPassword,
},
password
password,
);
saveSession({ ...session, passwordlessUser: false });
@@ -200,7 +200,7 @@ export const ClientProvider: FC<Props> = ({ children }) => {
passwordlessUser: false,
});
},
[initClientState?.client]
[initClientState?.client],
);
const setClient = useCallback(
@@ -222,7 +222,7 @@ export const ClientProvider: FC<Props> = ({ children }) => {
setInitClientState(null);
}
},
[initClientState?.client]
[initClientState?.client],
);
const logout = useCallback(async () => {
@@ -250,7 +250,7 @@ export const ClientProvider: FC<Props> = ({ children }) => {
}, []);
const [alreadyOpenedErr, setAlreadyOpenedErr] = useState<Error | undefined>(
undefined
undefined,
);
useEventTarget(
loadChannel,
@@ -258,9 +258,9 @@ export const ClientProvider: FC<Props> = ({ children }) => {
useCallback(() => {
initClientState?.client.stopClient();
setAlreadyOpenedErr(
translatedError("This application has been opened in another tab.", t)
translatedError("This application has been opened in another tab.", t),
);
}, [initClientState?.client, setAlreadyOpenedErr, t])
}, [initClientState?.client, setAlreadyOpenedErr, t]),
);
const [isDisconnected, setIsDisconnected] = useState(false);
@@ -301,7 +301,7 @@ export const ClientProvider: FC<Props> = ({ children }) => {
(state: SyncState, _old: SyncState | null, data?: ISyncStateData) => {
setIsDisconnected(clientIsDisconnected(state, data));
},
[]
[],
);
useEffect(() => {
@@ -387,7 +387,7 @@ async function loadClient(): Promise<InitResult | null> {
logger.warn(
"The previous session was lost, and we couldn't log it out, " +
err +
"either"
"either",
);
}
}
@@ -423,6 +423,6 @@ const loadSession = (): Session | undefined => {
const clientIsDisconnected = (
syncState: SyncState,
syncData?: ISyncStateData
syncData?: ISyncStateData,
): boolean =>
syncState === "ERROR" && syncData?.error?.name === "ConnectionError";

View File

@@ -48,5 +48,5 @@ export const Glass = forwardRef<HTMLDivElement, Props>(
>
{Children.only(children)}
</div>
)
),
);

View File

@@ -58,7 +58,7 @@ export const LeftNav: FC<LeftNavProps> = ({
styles.nav,
styles.leftNav,
{ [styles.hideMobile]: hideMobile },
className
className,
)}
{...rest}
>
@@ -85,7 +85,7 @@ export const RightNav: FC<RightNavProps> = ({
styles.nav,
styles.rightNav,
{ [styles.hideMobile]: hideMobile },
className
className,
)}
{...rest}
>

View File

@@ -63,7 +63,7 @@ export class LazyEventEmitter extends EventEmitter {
public addListener(
type: string | symbol,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
listener: (...args: any[]) => void
listener: (...args: any[]) => void,
): this {
return this.on(type, listener);
}

View File

@@ -77,7 +77,7 @@ function Option<T>({ item, state, className }: OptionProps<T>): ReactNode {
const { optionProps, isSelected, isFocused, isDisabled } = useOption(
{ key: item.key },
state,
ref
ref,
);
// Hack: remove the onPointerUp event handler and re-wire it to
@@ -97,7 +97,7 @@ function Option<T>({ item, state, className }: OptionProps<T>): ReactNode {
// @ts-ignore
origPointerUp(e as unknown as PointerEvent<HTMLElement>);
},
[origPointerUp]
[origPointerUp],
);
return (

View File

@@ -82,7 +82,7 @@ function MenuItem<T>({
onClose,
},
state,
ref
ref,
);
const [isFocused, setFocused] = useState(false);

View File

@@ -75,7 +75,7 @@ export const Modal: FC<Props> = ({
(open: boolean) => {
if (!open) onDismiss?.();
},
[onDismiss]
[onDismiss],
);
if (touchscreen) {
@@ -92,7 +92,7 @@ export const Modal: FC<Props> = ({
className,
overlayStyles.overlay,
styles.modal,
styles.drawer
styles.drawer,
)}
{...rest}
>
@@ -124,7 +124,7 @@ export const Modal: FC<Props> = ({
overlayStyles.overlay,
overlayStyles.animate,
styles.modal,
styles.dialog
styles.dialog,
)}
>
<div className={styles.content}>

View File

@@ -70,7 +70,7 @@ export const Toast: FC<Props> = ({
(open: boolean) => {
if (!open) onDismiss();
},
[onDismiss]
[onDismiss],
);
useEffect(() => {
@@ -91,7 +91,7 @@ export const Toast: FC<Props> = ({
className={classNames(
overlayStyles.overlay,
overlayStyles.animate,
styles.toast
styles.toast,
)}
>
<DialogTitle asChild>

View File

@@ -43,7 +43,7 @@ interface TooltipProps {
const Tooltip = forwardRef<HTMLDivElement, TooltipProps>(
(
{ state, className, children, ...rest }: TooltipProps,
ref: ForwardedRef<HTMLDivElement>
ref: ForwardedRef<HTMLDivElement>,
) => {
const { tooltipProps } = useTooltip(rest, state);
@@ -56,7 +56,7 @@ const Tooltip = forwardRef<HTMLDivElement, TooltipProps>(
{children}
</div>
);
}
},
);
interface TooltipTriggerProps {
@@ -69,7 +69,7 @@ interface TooltipTriggerProps {
export const TooltipTrigger = forwardRef<HTMLElement, TooltipTriggerProps>(
(
{ children, placement, tooltip, ...rest }: TooltipTriggerProps,
ref: ForwardedRef<HTMLElement>
ref: ForwardedRef<HTMLElement>,
) => {
const tooltipTriggerProps = { delay: 250, ...rest };
const tooltipState = useTooltipTriggerState(tooltipTriggerProps);
@@ -78,7 +78,7 @@ export const TooltipTrigger = forwardRef<HTMLElement, TooltipTriggerProps>(
const { triggerProps, tooltipProps } = useTooltipTrigger(
tooltipTriggerProps,
tooltipState,
triggerRef
triggerRef,
);
const { overlayProps } = useOverlayPosition({
@@ -94,7 +94,7 @@ export const TooltipTrigger = forwardRef<HTMLElement, TooltipTriggerProps>(
<children.type
{...mergeProps<typeof children.props | typeof rest>(
children.props,
rest
rest,
)}
/>
{tooltipState.isOpen && (
@@ -110,5 +110,5 @@ export const TooltipTrigger = forwardRef<HTMLElement, TooltipTriggerProps>(
)}
</FocusableProvider>
);
}
},
);

View File

@@ -39,5 +39,5 @@ class TranslatedErrorImpl extends TranslatedError {}
// function instead
export const translatedError = (
messageKey: string,
t: typeof i18n.t
t: typeof i18n.t,
): TranslatedError => new TranslatedErrorImpl(messageKey, t);

View File

@@ -119,17 +119,17 @@ interface UrlParams {
// file.
export function editFragmentQuery(
hash: string,
edit: (params: URLSearchParams) => URLSearchParams
edit: (params: URLSearchParams) => URLSearchParams,
): string {
const fragmentQueryStart = hash.indexOf("?");
const fragmentParams = edit(
new URLSearchParams(
fragmentQueryStart === -1 ? "" : hash.substring(fragmentQueryStart)
)
fragmentQueryStart === -1 ? "" : hash.substring(fragmentQueryStart),
),
);
return `${hash.substring(
0,
fragmentQueryStart
fragmentQueryStart,
)}?${fragmentParams.toString()}`;
}
@@ -142,7 +142,7 @@ class ParamParser {
const fragmentQueryStart = hash.indexOf("?");
this.fragmentParams = new URLSearchParams(
fragmentQueryStart === -1 ? "" : hash.substring(fragmentQueryStart)
fragmentQueryStart === -1 ? "" : hash.substring(fragmentQueryStart),
);
}
@@ -174,7 +174,7 @@ class ParamParser {
*/
export const getUrlParams = (
search = window.location.search,
hash = window.location.hash
hash = window.location.hash,
): UrlParams => {
const parser = new ParamParser(search, hash);
@@ -221,7 +221,7 @@ export const useUrlParams = (): UrlParams => {
export function getRoomIdentifierFromUrl(
pathname: string,
search: string,
hash: string
hash: string,
): RoomIdentifier {
let roomAlias: string | null = null;
pathname = pathname.substring(1); // Strip the "/"
@@ -281,6 +281,6 @@ export const useRoomIdentifier = (): RoomIdentifier => {
const { pathname, search, hash } = useLocation();
return useMemo(
() => getRoomIdentifierFromUrl(pathname, search, hash),
[pathname, search, hash]
[pathname, search, hash],
);
};

View File

@@ -34,7 +34,7 @@ export const UserMenuContainer: FC<Props> = ({ preventNavigation = false }) => {
const [settingsModalOpen, setSettingsModalOpen] = useState(false);
const onDismissSettingsModal = useCallback(
() => setSettingsModalOpen(false),
[setSettingsModalOpen]
[setSettingsModalOpen],
);
const [defaultSettingsTab, setDefaultSettingsTab] = useState<string>();
@@ -58,7 +58,7 @@ export const UserMenuContainer: FC<Props> = ({ preventNavigation = false }) => {
break;
}
},
[history, location, logout, setSettingsModalOpen]
[history, location, logout, setSettingsModalOpen],
);
const userName = client?.getUserIdLocalpart() ?? "";

View File

@@ -146,7 +146,7 @@ export class PosthogAnalytics {
this.enabled = true;
} else {
logger.info(
"Posthog is not enabled because there is no api key or no host given in the config"
"Posthog is not enabled because there is no api key or no host given in the config",
);
this.enabled = false;
}
@@ -157,7 +157,7 @@ export class PosthogAnalytics {
private sanitizeProperties = (
properties: Properties,
_eventName: string
_eventName: string,
): Properties => {
// Callback from posthog to sanitize properties before sending them to the server.
// Here we sanitize posthog's built in properties which leak PII e.g. url reporting.
@@ -201,7 +201,7 @@ export class PosthogAnalytics {
private capture(
eventName: string,
properties: Properties,
options?: CaptureOptions
options?: CaptureOptions,
): void {
if (!this.enabled) {
return;
@@ -237,7 +237,7 @@ export class PosthogAnalytics {
}
private async identifyUser(
analyticsIdGenerator: () => string
analyticsIdGenerator: () => string,
): Promise<void> {
if (this.anonymity == Anonymity.Pseudonymous && this.enabled) {
// Check the user's account_data for an analytics ID to use. Storing the ID in account_data allows
@@ -260,14 +260,14 @@ export class PosthogAnalytics {
// The above could fail due to network requests, but not essential to starting the application,
// so swallow it.
logger.log(
"Unable to identify user for tracking" + (e as Error)?.toString()
"Unable to identify user for tracking" + (e as Error)?.toString(),
);
}
if (analyticsID) {
this.posthog.identify(analyticsID);
} else {
logger.info(
"No analyticsID is availble. Should not try to setup posthog"
"No analyticsID is availble. Should not try to setup posthog",
);
}
}
@@ -280,7 +280,7 @@ export class PosthogAnalytics {
accountAnalyticsId = getUrlParams().analyticsID;
} else {
const accountData = await client.getAccountDataFromServer(
PosthogAnalytics.ANALYTICS_EVENT_TYPE
PosthogAnalytics.ANALYTICS_EVENT_TYPE,
);
accountAnalyticsId = accountData?.id;
}
@@ -294,13 +294,13 @@ export class PosthogAnalytics {
}
private async hashedEcAnalyticsId(
accountAnalyticsId: string
accountAnalyticsId: string,
): Promise<string> {
const client: MatrixClient = window.matrixclient;
const posthogIdMaterial = "ec" + accountAnalyticsId + client.getUserId();
const bufferForPosthogId = await crypto.subtle.digest(
"sha-256",
Buffer.from(posthogIdMaterial, "utf-8")
Buffer.from(posthogIdMaterial, "utf-8"),
);
const view = new Int32Array(bufferForPosthogId);
return Array.from(view)
@@ -314,11 +314,11 @@ export class PosthogAnalytics {
// the analytics ID only needs to be set in the standalone version.
const accountData = await client.getAccountDataFromServer(
PosthogAnalytics.ANALYTICS_EVENT_TYPE
PosthogAnalytics.ANALYTICS_EVENT_TYPE,
);
await client.setAccountData(
PosthogAnalytics.ANALYTICS_EVENT_TYPE,
Object.assign({ id: analyticsID }, accountData)
Object.assign({ id: analyticsID }, accountData),
);
}
}
@@ -360,7 +360,7 @@ export class PosthogAnalytics {
}
private async updateAnonymityAndIdentifyUser(
pseudonymousOptIn: boolean
pseudonymousOptIn: boolean,
): Promise<void> {
// Update this.anonymity based on the user's analytics opt-in settings
const anonymity = pseudonymousOptIn
@@ -376,11 +376,11 @@ export class PosthogAnalytics {
this.setRegistrationType(
window.matrixclient.isGuest() || window.passwordlessUser
? RegistrationType.Guest
: RegistrationType.Registered
: RegistrationType.Registered,
);
// store the promise to await posthog-tracking-events until the identification is done.
this.identificationPromise = this.identifyUser(
PosthogAnalytics.getRandomAnalyticsId
PosthogAnalytics.getRandomAnalyticsId,
);
await this.identificationPromise;
if (this.userRegisteredInThisSession()) {
@@ -395,7 +395,7 @@ export class PosthogAnalytics {
public async trackEvent<E extends IPosthogEvent>(
{ eventName, ...properties }: E,
options?: CaptureOptions
options?: CaptureOptions,
): Promise<void> {
if (this.identificationPromise) {
// only make calls to posthog after the identificaion is done

View File

@@ -43,14 +43,14 @@ export class CallEndedTracker {
public cacheParticipantCountChanged(count: number): void {
this.cache.maxParticipantsCount = Math.max(
count,
this.cache.maxParticipantsCount
this.cache.maxParticipantsCount,
);
}
public track(
callId: string,
callParticipantsNow: number,
sendInstantly: boolean
sendInstantly: boolean,
): void {
PosthogAnalytics.instance.trackEvent<CallEnded>(
{
@@ -60,7 +60,7 @@ export class CallEndedTracker {
callParticipantsOnLeave: callParticipantsNow,
callDuration: (Date.now() - this.cache.startTime.getTime()) / 1000,
},
{ send_instantly: sendInstantly }
{ send_instantly: sendInstantly },
);
}
}

View File

@@ -148,7 +148,7 @@ export class PosthogSpanProcessor implements SpanProcessor {
ratioPeerConnectionToDevices: ratioPeerConnectionToDevices,
},
// Send instantly because the window might be closing
{ send_instantly: true }
{ send_instantly: true },
);
}
}

View File

@@ -23,7 +23,7 @@ import {
} from "@opentelemetry/sdk-trace-base";
const dumpAttributes = (
attr: Attributes
attr: Attributes,
): {
key: string;
type:

View File

@@ -22,7 +22,7 @@ limitations under the License.
// Array.prototype.findLastIndex
export function findLastIndex<T>(
array: T[],
predicate: (item: T, index: number) => boolean
predicate: (item: T, index: number) => boolean,
): number | null {
for (let i = array.length - 1; i >= 0; i--) {
if (predicate(array[i], i)) return i;
@@ -36,9 +36,9 @@ export function findLastIndex<T>(
*/
export const count = <T>(
array: T[],
predicate: (item: T, index: number) => boolean
predicate: (item: T, index: number) => boolean,
): number =>
array.reduce(
(acc, item, index) => (predicate(item, index) ? acc + 1 : acc),
0
0,
);

View File

@@ -80,7 +80,7 @@ export const LoginPage: FC = () => {
setLoading(false);
});
},
[login, location, history, homeserver, setClient]
[login, location, history, homeserver, setClient],
);
return (

View File

@@ -78,7 +78,7 @@ export const RegisterPage: FC = () => {
password,
userName,
recaptchaResponse,
passwordlessUser
passwordlessUser,
);
if (client && client?.groupCallEventHandler && passwordlessUser) {
@@ -135,7 +135,7 @@ export const RegisterPage: FC = () => {
execute,
client,
setClient,
]
],
);
useEffect(() => {

View File

@@ -24,13 +24,13 @@ import { Session } from "../ClientContext";
export function useInteractiveLogin(): (
homeserver: string,
username: string,
password: string
password: string,
) => Promise<[MatrixClient, Session]> {
return useCallback<
(
homeserver: string,
username: string,
password: string
password: string,
) => Promise<[MatrixClient, Session]>
>(async (homeserver: string, username: string, password: string) => {
const authClient = createClient({ baseUrl: homeserver });
@@ -70,7 +70,7 @@ export function useInteractiveLogin(): (
userId: user_id,
deviceId: device_id,
},
false
false,
);
/* eslint-enable camelcase */
return [client, session];

View File

@@ -30,14 +30,14 @@ export const useInteractiveRegistration = (): {
password: string,
displayName: string,
recaptchaResponse: string,
passwordlessUser: boolean
passwordlessUser: boolean,
) => Promise<[MatrixClient, Session]>;
} => {
const [privacyPolicyUrl, setPrivacyPolicyUrl] = useState<string | undefined>(
undefined
undefined,
);
const [recaptchaKey, setRecaptchaKey] = useState<string | undefined>(
undefined
undefined,
);
const authClient = useRef<MatrixClient>();
@@ -50,7 +50,7 @@ export const useInteractiveRegistration = (): {
useEffect(() => {
authClient.current!.registerRequest({}).catch((error) => {
setPrivacyPolicyUrl(
error.data?.params["m.login.terms"]?.policies?.privacy_policy?.en?.url
error.data?.params["m.login.terms"]?.policies?.privacy_policy?.en?.url,
);
setRecaptchaKey(error.data?.params["m.login.recaptcha"]?.public_key);
});
@@ -62,7 +62,7 @@ export const useInteractiveRegistration = (): {
password: string,
displayName: string,
recaptchaResponse: string,
passwordlessUser: boolean
passwordlessUser: boolean,
): Promise<[MatrixClient, Session]> => {
const interactiveAuth = new InteractiveAuth({
matrixClient: authClient.current!,
@@ -106,7 +106,7 @@ export const useInteractiveRegistration = (): {
userId: user_id,
deviceId: device_id,
},
false
false,
);
await client.setDisplayName(displayName);
@@ -129,7 +129,7 @@ export const useInteractiveRegistration = (): {
return [client, session];
},
[]
[],
);
return { privacyPolicyUrl, recaptchaKey, register };

View File

@@ -108,7 +108,7 @@ export function useRecaptcha(sitekey?: string): {
window.grecaptcha.execute();
const iframe = document.querySelector<HTMLIFrameElement>(
'iframe[src*="recaptcha/api2/bframe"]'
'iframe[src*="recaptcha/api2/bframe"]',
);
if (iframe?.parentNode?.parentNode) {

View File

@@ -48,7 +48,7 @@ export function useRegisterPasswordlessUser(): UseRegisterPasswordlessUserType {
randomString(16),
displayName,
recaptchaResponse,
true
true,
);
setClient({ client, session });
} catch (e) {
@@ -56,7 +56,7 @@ export function useRegisterPasswordlessUser(): UseRegisterPasswordlessUserType {
throw e;
}
},
[execute, reset, register, setClient]
[execute, reset, register, setClient],
);
return { privacyPolicyUrl, registerPasswordlessUser, recaptchaId };

View File

@@ -146,7 +146,9 @@ limitations under the License.
.copyButton {
width: 100%;
height: 40px;
transition: border-color 250ms, background-color 250ms;
transition:
border-color 250ms,
background-color 250ms;
}
.copyButton span {

View File

@@ -94,12 +94,12 @@ export const Button = forwardRef<HTMLButtonElement, Props>(
onPressStart,
...rest
},
ref
ref,
) => {
const buttonRef = useObjectRef<HTMLButtonElement>(ref);
const { buttonProps } = useButton(
{ onPress, onPressStart, ...rest },
buttonRef
buttonRef,
);
// TODO: react-aria's useButton hook prevents form submission via keyboard
@@ -121,7 +121,7 @@ export const Button = forwardRef<HTMLButtonElement, Props>(
{
[styles.on]: on,
[styles.off]: off,
}
},
)}
{...mergeProps(rest, filteredButtonProps)}
ref={buttonRef}
@@ -132,7 +132,7 @@ export const Button = forwardRef<HTMLButtonElement, Props>(
</>
</button>
);
}
},
);
export const MicButton: FC<{

View File

@@ -47,7 +47,7 @@ export const LinkButton: FC<Props> = ({
className={classNames(
variantToClassName[variant || "secondary"],
size ? sizeToClassName[size] : [],
className
className,
)}
to={to}
{...rest}

View File

@@ -57,7 +57,7 @@ export class Config {
}
async function downloadConfig(
configJsonFilename: string
configJsonFilename: string,
): Promise<ConfigOptions> {
const url = new URL(configJsonFilename, window.location.href);
url.searchParams.set("cachebuster", Date.now().toString());

View File

@@ -26,7 +26,7 @@ export const getRoomSharedKeyLocalStorageKey = (roomId: string): string =>
`room-shared-key-${roomId}`;
const useInternalRoomSharedKey = (
roomId: string
roomId: string,
): [string | null, (value: string) => void] => {
const key = useMemo(() => getRoomSharedKeyLocalStorageKey(roomId), [roomId]);
const [e2eeEnabled] = useEnableE2EE();
@@ -68,6 +68,6 @@ export const useIsRoomE2EE = (roomId: string): boolean | null => {
// should inspect the e2eEnabled URL parameter here?
return useMemo(
() => widget === null && (room === null || !room.getCanonicalAlias()),
[room]
[room],
);
};

View File

@@ -36,5 +36,5 @@ export const Form = forwardRef<HTMLFormElement, FormProps>(
{children}
</form>
);
}
},
);

View File

@@ -74,7 +74,7 @@ const CallTile: FC<CallTileProps> = ({ name, avatarUrl, room }) => {
to={getRelativeRoomUrl(
room.roomId,
room.name,
roomSharedKey ?? undefined
roomSharedKey ?? undefined,
)}
className={styles.callTileLink}
>
@@ -92,7 +92,7 @@ const CallTile: FC<CallTileProps> = ({ name, avatarUrl, room }) => {
value={getAbsoluteRoomUrl(
room.roomId,
room.name,
roomSharedKey ?? undefined
roomSharedKey ?? undefined,
)}
/>
</div>

View File

@@ -56,7 +56,7 @@ export const RegisteredView: FC<Props> = ({ client }) => {
useState(false);
const onDismissJoinExistingCallModal = useCallback(
() => setJoinExistingCallModalOpen(false),
[setJoinExistingCallModalOpen]
[setJoinExistingCallModalOpen],
);
const [e2eeEnabled] = useEnableE2EE();
@@ -77,15 +77,15 @@ export const RegisteredView: FC<Props> = ({ client }) => {
const createRoomResult = await createRoom(
client,
roomName,
e2eeEnabled ?? false
e2eeEnabled ?? false,
);
history.push(
getRelativeRoomUrl(
createRoomResult.roomId,
roomName,
createRoomResult.password
)
createRoomResult.password,
),
);
}
@@ -102,7 +102,7 @@ export const RegisteredView: FC<Props> = ({ client }) => {
}
});
},
[client, history, setJoinExistingCallModalOpen, e2eeEnabled]
[client, history, setJoinExistingCallModalOpen, e2eeEnabled],
);
const recentRooms = useGroupCallRooms(client);

View File

@@ -57,7 +57,7 @@ export const UnauthenticatedView: FC = () => {
useState(false);
const onDismissJoinExistingCallModal = useCallback(
() => setJoinExistingCallModalOpen(false),
[setJoinExistingCallModalOpen]
[setJoinExistingCallModalOpen],
);
const [onFinished, setOnFinished] = useState<() => void>();
const history = useHistory();
@@ -82,7 +82,7 @@ export const UnauthenticatedView: FC = () => {
randomString(16),
displayName,
recaptchaResponse,
true
true,
);
let createRoomResult;
@@ -90,7 +90,7 @@ export const UnauthenticatedView: FC = () => {
createRoomResult = await createRoom(
client,
roomName,
e2eeEnabled ?? false
e2eeEnabled ?? false,
);
} catch (error) {
if (!setClient) {
@@ -124,8 +124,8 @@ export const UnauthenticatedView: FC = () => {
getRelativeRoomUrl(
createRoomResult.roomId,
roomName,
createRoomResult.password
)
createRoomResult.password,
),
);
}
@@ -144,7 +144,7 @@ export const UnauthenticatedView: FC = () => {
setJoinExistingCallModalOpen,
setClient,
e2eeEnabled,
]
],
);
return (

View File

@@ -47,7 +47,7 @@ function getLastTs(client: MatrixClient, r: Room): number {
if (r.getMyMembership() !== "join") {
const membershipEvent = r.currentState.getStateEvents(
"m.room.member",
myUserId
myUserId,
);
if (membershipEvent && !Array.isArray(membershipEvent)) {
@@ -115,7 +115,7 @@ export function useGroupCallRooms(client: MatrixClient): GroupCallRoom[] {
client.removeListener(GroupCallEventHandlerEvent.Incoming, updateRooms);
client.removeListener(
GroupCallEventHandlerEvent.Participants,
updateRooms
updateRooms,
);
};
}, [client]);

View File

@@ -68,7 +68,8 @@ limitations under the License.
font-weight: 400;
font-display: swap;
unicode-range: var(--inter-unicode-range);
src: url("/fonts/Inter/Inter-Regular.woff2") format("woff2"),
src:
url("/fonts/Inter/Inter-Regular.woff2") format("woff2"),
url("/fonts/Inter/Inter-Regular.woff") format("woff");
}
@@ -78,7 +79,8 @@ limitations under the License.
font-weight: 400;
font-display: swap;
unicode-range: var(--inter-unicode-range);
src: url("/fonts/Inter/Inter-Italic.woff2") format("woff2"),
src:
url("/fonts/Inter/Inter-Italic.woff2") format("woff2"),
url("/fonts/Inter/Inter-Italic.woff") format("woff");
}
@@ -88,7 +90,8 @@ limitations under the License.
font-weight: 500;
font-display: swap;
unicode-range: var(--inter-unicode-range);
src: url("/fonts/Inter/Inter-Medium.woff2") format("woff2"),
src:
url("/fonts/Inter/Inter-Medium.woff2") format("woff2"),
url("/fonts/Inter/Inter-Medium.woff") format("woff");
}
@@ -98,7 +101,8 @@ limitations under the License.
font-weight: 500;
font-display: swap;
unicode-range: var(--inter-unicode-range);
src: url("/fonts/Inter/Inter-MediumItalic.woff2") format("woff2"),
src:
url("/fonts/Inter/Inter-MediumItalic.woff2") format("woff2"),
url("/fonts/Inter/Inter-MediumItalic.woff") format("woff");
}
@@ -108,7 +112,8 @@ limitations under the License.
font-weight: 600;
font-display: swap;
unicode-range: var(--inter-unicode-range);
src: url("/fonts/Inter/Inter-SemiBold.woff2") format("woff2"),
src:
url("/fonts/Inter/Inter-SemiBold.woff2") format("woff2"),
url("/fonts/Inter/Inter-SemiBold.woff") format("woff");
}
@@ -118,7 +123,8 @@ limitations under the License.
font-weight: 600;
font-display: swap;
unicode-range: var(--inter-unicode-range);
src: url("/fonts/Inter/Inter-SemiBoldItalic.woff2") format("woff2"),
src:
url("/fonts/Inter/Inter-SemiBoldItalic.woff2") format("woff2"),
url("/fonts/Inter/Inter-SemiBoldItalic.woff") format("woff");
}
@@ -128,7 +134,8 @@ limitations under the License.
font-weight: 700;
font-display: swap;
unicode-range: var(--inter-unicode-range);
src: url("/fonts/Inter/Inter-Bold.woff2") format("woff2"),
src:
url("/fonts/Inter/Inter-Bold.woff2") format("woff2"),
url("/fonts/Inter/Inter-Bold.woff") format("woff");
}
@@ -138,7 +145,8 @@ limitations under the License.
font-weight: 700;
font-display: swap;
unicode-range: var(--inter-unicode-range);
src: url("/fonts/Inter/Inter-BoldItalic.woff2") format("woff2"),
src:
url("/fonts/Inter/Inter-BoldItalic.woff2") format("woff2"),
url("/fonts/Inter/Inter-BoldItalic.woff") format("woff");
}

View File

@@ -99,13 +99,13 @@ export class Initializer {
if (fontScale !== null) {
document.documentElement.style.setProperty(
"--font-scale",
fontScale.toString()
fontScale.toString(),
);
}
if (fonts.length > 0) {
document.documentElement.style.setProperty(
"--font-family",
fonts.map((f) => `"${f}"`).join(", ")
fonts.map((f) => `"${f}"`).join(", "),
);
}

View File

@@ -52,7 +52,7 @@ export const AvatarInputField = forwardRef<HTMLInputElement, Props>(
onRemoveAvatar,
...rest
},
ref
ref,
) => {
const { t } = useTranslation();
@@ -120,5 +120,5 @@ export const AvatarInputField = forwardRef<HTMLInputElement, Props>(
)}
</div>
);
}
},
);

View File

@@ -85,8 +85,11 @@ limitations under the License.
}
.inputField label {
transition: font-size 0.25s ease-out 0.1s, color 0.25s ease-out 0.1s,
top 0.25s ease-out 0.1s, background-color 0.25s ease-out 0.1s;
transition:
font-size 0.25s ease-out 0.1s,
color 0.25s ease-out 0.1s,
top 0.25s ease-out 0.1s,
background-color 0.25s ease-out 0.1s;
color: var(--cpd-color-text-secondary);
background-color: transparent;
font-size: var(--font-size-body);
@@ -118,8 +121,11 @@ limitations under the License.
.inputField textarea:not(:placeholder-shown) + label,
.inputField.prefix textarea + label {
background-color: var(--cpd-color-bg-canvas-default);
transition: font-size 0.25s ease-out 0s, color 0.25s ease-out 0s,
top 0.25s ease-out 0s, background-color 0.25s ease-out 0s;
transition:
font-size 0.25s ease-out 0s,
color 0.25s ease-out 0s,
top 0.25s ease-out 0s,
background-color 0.25s ease-out 0s;
font-size: var(--font-size-micro);
top: -13px;
padding: 0 2px;

View File

@@ -44,7 +44,7 @@ export function FieldRow({
className={classNames(
styles.fieldRow,
{ [styles.rightAlign]: rightAlign },
className
className,
)}
>
{children}
@@ -102,7 +102,7 @@ export const InputField = forwardRef<
disabled,
...rest
},
ref
ref,
) => {
const descriptionId = useId();
@@ -114,7 +114,7 @@ export const InputField = forwardRef<
[styles.prefix]: !!prefix,
[styles.disabled]: disabled,
},
className
className,
)}
>
{prefix && <span>{prefix}</span>}
@@ -163,7 +163,7 @@ export const InputField = forwardRef<
)}
</Field>
);
}
},
);
interface ErrorMessageProps {

View File

@@ -38,7 +38,7 @@ export function SelectInput(props: Props): JSX.Element {
const { labelProps, triggerProps, valueProps, menuProps } = useSelect(
props,
state,
ref
ref,
);
const { buttonProps } = useButton(triggerProps, ref);

View File

@@ -51,7 +51,7 @@ export interface MediaDevices {
// Cargo-culted from @livekit/components-react
function useObservableState<T>(
observable: Observable<T> | undefined,
startWith: T
startWith: T,
): T {
const [state, setState] = useState<T>(startWith);
useEffect(() => {
@@ -67,7 +67,7 @@ function useMediaDevice(
kind: MediaDeviceKind,
fallbackDevice: string | undefined,
usingNames: boolean,
alwaysDefault: boolean = false
alwaysDefault: boolean = false,
): MediaDevice {
// Make sure we don't needlessly reset to a device observer without names,
// once permissions are already given
@@ -83,7 +83,7 @@ function useMediaDevice(
// kind, which then results in multiple permissions requests.
const deviceObserver = useMemo(
() => createMediaDeviceObserver(kind, requestPermissions),
[kind, requestPermissions]
[kind, requestPermissions],
);
const available = useObservableState(deviceObserver, []);
const [selectedId, select] = useState(fallbackDevice);
@@ -143,18 +143,18 @@ export const MediaDevicesProvider: FC<Props> = ({ children }) => {
const audioInput = useMediaDevice(
"audioinput",
audioInputSetting,
usingNames
usingNames,
);
const audioOutput = useMediaDevice(
"audiooutput",
audioOutputSetting,
useOutputNames,
alwaysUseDefaultAudio
alwaysUseDefaultAudio,
);
const videoInput = useMediaDevice(
"videoinput",
videoInputSetting,
usingNames
usingNames,
);
useEffect(() => {
@@ -176,11 +176,11 @@ export const MediaDevicesProvider: FC<Props> = ({ children }) => {
const startUsingDeviceNames = useCallback(
() => setNumCallersUsingNames((n) => n + 1),
[setNumCallersUsingNames]
[setNumCallersUsingNames],
);
const stopUsingDeviceNames = useCallback(
() => setNumCallersUsingNames((n) => n - 1),
[setNumCallersUsingNames]
[setNumCallersUsingNames],
);
const context: MediaDevices = useMemo(
@@ -197,7 +197,7 @@ export const MediaDevicesProvider: FC<Props> = ({ children }) => {
videoInput,
startUsingDeviceNames,
stopUsingDeviceNames,
]
],
);
return (
@@ -218,7 +218,7 @@ export const useMediaDevices = (): MediaDevices =>
*/
export const useMediaDeviceNames = (
context: MediaDevices,
enabled = true
enabled = true,
): void =>
useEffect(() => {
if (enabled) {

View File

@@ -42,7 +42,7 @@ export type OpenIDClientParts = Pick<
export function useOpenIDSFU(
client: OpenIDClientParts,
rtcSession: MatrixRTCSession
rtcSession: MatrixRTCSession,
): SFUConfig | undefined {
const [sfuConfig, setSFUConfig] = useState<SFUConfig | undefined>(undefined);
@@ -62,20 +62,20 @@ export function useOpenIDSFU(
export async function getSFUConfigWithOpenID(
client: OpenIDClientParts,
activeFocus: LivekitFocus
activeFocus: LivekitFocus,
): Promise<SFUConfig | undefined> {
const openIdToken = await client.getOpenIdToken();
logger.debug("Got openID token", openIdToken);
try {
logger.info(
`Trying to get JWT from call's active focus URL of ${activeFocus.livekit_service_url}...`
`Trying to get JWT from call's active focus URL of ${activeFocus.livekit_service_url}...`,
);
const sfuConfig = await getLiveKitJWT(
client,
activeFocus.livekit_service_url,
activeFocus.livekit_alias,
openIdToken
openIdToken,
);
logger.info(`Got JWT from call's active focus URL.`);
@@ -83,7 +83,7 @@ export async function getSFUConfigWithOpenID(
} catch (e) {
logger.warn(
`Failed to get JWT from RTC session's active focus URL of ${activeFocus.livekit_service_url}.`,
e
e,
);
return undefined;
}
@@ -93,7 +93,7 @@ async function getLiveKitJWT(
client: OpenIDClientParts,
livekitServiceURL: string,
roomName: string,
openIDToken: IOpenIDToken
openIDToken: IOpenIDToken,
): Promise<SFUConfig> {
try {
const res = await fetch(livekitServiceURL + "/sfu/get", {

View File

@@ -51,7 +51,7 @@ async function doConnect(
livekitRoom: Room,
sfuConfig: SFUConfig,
audioEnabled: boolean,
audioOptions: AudioCaptureOptions
audioOptions: AudioCaptureOptions,
): Promise<void> {
await livekitRoom!.connect(sfuConfig!.url, sfuConfig!.jwt);
@@ -76,12 +76,12 @@ export function useECConnectionState(
initialAudioOptions: AudioCaptureOptions,
initialAudioEnabled: boolean,
livekitRoom?: Room,
sfuConfig?: SFUConfig
sfuConfig?: SFUConfig,
): ECConnectionState {
const [connState, setConnState] = useState(
sfuConfig && livekitRoom
? livekitRoom.state
: ECAddonConnectionState.ECWaiting
: ECAddonConnectionState.ECWaiting,
);
const [isSwitchingFocus, setSwitchingFocus] = useState(false);
@@ -116,7 +116,7 @@ export function useECConnectionState(
!sfuConfigEquals(currentSFUConfig.current, sfuConfig)
) {
logger.info(
`SFU config changed! URL was ${currentSFUConfig.current?.url} now ${sfuConfig?.url}`
`SFU config changed! URL was ${currentSFUConfig.current?.url} now ${sfuConfig?.url}`,
);
(async (): Promise<void> => {
@@ -128,7 +128,7 @@ export function useECConnectionState(
livekitRoom!,
sfuConfig!,
initialAudioEnabled,
initialAudioOptions
initialAudioOptions,
);
} finally {
setIsInDoConnect(false);
@@ -149,7 +149,7 @@ export function useECConnectionState(
livekitRoom!,
sfuConfig!,
initialAudioEnabled,
initialAudioOptions
initialAudioOptions,
).finally(() => setIsInDoConnect(false));
}

View File

@@ -52,7 +52,7 @@ interface UseLivekitResult {
export function useLiveKit(
muteStates: MuteStates,
sfuConfig?: SFUConfig,
e2eeConfig?: E2EEConfig
e2eeConfig?: E2EEConfig,
): UseLivekitResult {
const e2eeOptions = useMemo(() => {
if (!e2eeConfig?.sharedKey) return undefined;
@@ -67,7 +67,7 @@ export function useLiveKit(
if (!e2eeConfig?.sharedKey || !e2eeOptions) return;
(e2eeOptions.keyProvider as ExternalE2EEKeyProvider).setKey(
e2eeConfig?.sharedKey
e2eeConfig?.sharedKey,
);
}, [e2eeOptions, e2eeConfig?.sharedKey]);
@@ -93,7 +93,7 @@ export function useLiveKit(
},
e2ee: e2eeOptions,
}),
[e2eeOptions]
[e2eeOptions],
);
// useECConnectionState creates and publishes an audio track by hand. To keep
@@ -131,7 +131,7 @@ export function useLiveKit(
},
initialMuteStates.current.audio.enabled,
room,
sfuConfig
sfuConfig,
);
// Unblock audio once the connection is finished
@@ -215,11 +215,11 @@ export function useLiveKit(
room.options.audioCaptureDefaults?.deviceId === "default"
) {
const activeMicTrack = Array.from(
room.localParticipant.audioTracks.values()
room.localParticipant.audioTracks.values(),
).find((d) => d.source === Track.Source.Microphone)?.track;
const defaultDevice = device.available.find(
(d) => d.deviceId === "default"
(d) => d.deviceId === "default",
);
if (
defaultDevice &&
@@ -245,7 +245,7 @@ export function useLiveKit(
room
.switchActiveDevice(kind, id)
.catch((e) =>
logger.error(`Failed to sync ${kind} device with LiveKit`, e)
logger.error(`Failed to sync ${kind} device with LiveKit`, e),
);
}
}

View File

@@ -48,7 +48,7 @@ if (!window.isSecureContext) {
fatalError = new Error(
"This app cannot run in an insecure context. To fix this, access the app " +
"via a local loopback address, or serve it over HTTPS.\n" +
"https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts"
"https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts",
);
} else if (!navigator.mediaDevices) {
fatalError = new Error("Your browser does not support WebRTC.");
@@ -66,5 +66,5 @@ const history = createBrowserHistory();
root.render(
<StrictMode>
<App history={history} />
</StrictMode>
</StrictMode>,
);

View File

@@ -59,7 +59,7 @@ function waitForSync(client: MatrixClient): Promise<void> {
const onSync = (
state: SyncState,
_old: SyncState | null,
data?: ISyncStateData
data?: ISyncStateData,
): void => {
if (state === "PREPARED") {
client.removeListener(ClientEvent.Sync, onSync);
@@ -83,7 +83,7 @@ function secureRandomString(entropyBytes: number): string {
// yet) so just use the built-in one and convert, replace the chars and strip the
// padding from the end (otherwise we'd need to pull in another dependency).
return btoa(
key.reduce((acc, current) => acc + String.fromCharCode(current), "")
key.reduce((acc, current) => acc + String.fromCharCode(current), ""),
)
.replace("+", "-")
.replace("/", "_")
@@ -101,7 +101,7 @@ function secureRandomString(entropyBytes: number): string {
*/
export async function initClient(
clientOptions: ICreateClientOpts,
restore: boolean
restore: boolean,
): Promise<MatrixClient> {
await loadOlm();
@@ -148,7 +148,7 @@ export async function initClient(
if (indexedDB) {
const cryptoStoreExists = await IndexedDBCryptoStore.exists(
indexedDB,
CRYPTO_STORE_NAME
CRYPTO_STORE_NAME,
);
if (!cryptoStoreExists) throw new CryptoStoreIntegrityError();
} else if (localStorage) {
@@ -164,7 +164,7 @@ export async function initClient(
if (indexedDB) {
baseOpts.cryptoStore = new IndexedDBCryptoStore(
indexedDB,
CRYPTO_STORE_NAME
CRYPTO_STORE_NAME,
);
} else if (localStorage) {
baseOpts.cryptoStore = new LocalStorageCryptoStore(localStorage);
@@ -198,7 +198,7 @@ export async function initClient(
} catch (error) {
logger.error(
"Error starting matrix client store. Falling back to memory store.",
error
error,
);
client.store = new MemoryStore({ localStorage });
await client.store.startup();
@@ -268,7 +268,7 @@ export function roomNameFromRoomId(roomId: string): string {
.substring(1)
.split("-")
.map((part) =>
part.length > 0 ? part.charAt(0).toUpperCase() + part.slice(1) : part
part.length > 0 ? part.charAt(0).toUpperCase() + part.slice(1) : part,
)
.join(" ")
.toLowerCase();
@@ -297,7 +297,7 @@ interface CreateRoomResult {
export async function createRoom(
client: MatrixClient,
name: string,
e2ee: boolean
e2ee: boolean,
): Promise<CreateRoomResult> {
logger.log(`Creating room for group call`);
const createPromise = client.createRoom({
@@ -358,7 +358,7 @@ export async function createRoom(
GroupCallType.Video,
false,
GroupCallIntent.Room,
true
true,
);
let password;
@@ -366,7 +366,7 @@ export async function createRoom(
password = secureRandomString(16);
setLocalStorageItem(
getRoomSharedKeyLocalStorageKey(result.room_id),
password
password,
);
}
@@ -386,7 +386,7 @@ export async function createRoom(
export function getAbsoluteRoomUrl(
roomId: string,
roomName?: string,
password?: string
password?: string,
): string {
return `${window.location.protocol}//${
window.location.host
@@ -402,7 +402,7 @@ export function getAbsoluteRoomUrl(
export function getRelativeRoomUrl(
roomId: string,
roomName?: string,
password?: string
password?: string,
): string {
// The password shouldn't need URL encoding here (we generate URL-safe ones) but encode
// it in case it came from another client that generated a non url-safe one
@@ -419,7 +419,7 @@ export function getRelativeRoomUrl(
export function getAvatarUrl(
client: MatrixClient,
mxcUrl: string,
avatarSize = 96
avatarSize = 96,
): string {
const width = Math.floor(avatarSize * window.devicePixelRatio);
const height = Math.floor(avatarSize * window.devicePixelRatio);

View File

@@ -23,10 +23,10 @@ limitations under the License.
export async function findDeviceByName(
deviceName: string,
kind: MediaDeviceKind,
devices: MediaDeviceInfo[]
devices: MediaDeviceInfo[],
): Promise<string | undefined> {
const deviceInfo = devices.find(
(d) => d.kind === kind && d.label === deviceName
(d) => d.kind === kind && d.label === deviceName,
);
return deviceInfo?.deviceId;
}

View File

@@ -48,14 +48,14 @@ export class OTelCall {
public userId: string,
public deviceId: string,
public call: MatrixCall,
public span: Span
public span: Span,
) {
if (call.peerConn) {
this.addCallPeerConnListeners();
} else {
this.call.once(
CallEvent.PeerConnectionCreated,
this.addCallPeerConnListeners
this.addCallPeerConnListeners,
);
}
}
@@ -63,46 +63,46 @@ export class OTelCall {
public dispose(): void {
this.call.peerConn?.removeEventListener(
"connectionstatechange",
this.onCallConnectionStateChanged
this.onCallConnectionStateChanged,
);
this.call.peerConn?.removeEventListener(
"signalingstatechange",
this.onCallSignalingStateChanged
this.onCallSignalingStateChanged,
);
this.call.peerConn?.removeEventListener(
"iceconnectionstatechange",
this.onIceConnectionStateChanged
this.onIceConnectionStateChanged,
);
this.call.peerConn?.removeEventListener(
"icegatheringstatechange",
this.onIceGatheringStateChanged
this.onIceGatheringStateChanged,
);
this.call.peerConn?.removeEventListener(
"icecandidateerror",
this.onIceCandidateError
this.onIceCandidateError,
);
}
private addCallPeerConnListeners = (): void => {
this.call.peerConn?.addEventListener(
"connectionstatechange",
this.onCallConnectionStateChanged
this.onCallConnectionStateChanged,
);
this.call.peerConn?.addEventListener(
"signalingstatechange",
this.onCallSignalingStateChanged
this.onCallSignalingStateChanged,
);
this.call.peerConn?.addEventListener(
"iceconnectionstatechange",
this.onIceConnectionStateChanged
this.onIceConnectionStateChanged,
);
this.call.peerConn?.addEventListener(
"icegatheringstatechange",
this.onIceGatheringStateChanged
this.onIceGatheringStateChanged,
);
this.call.peerConn?.addEventListener(
"icecandidateerror",
this.onIceCandidateError
this.onIceCandidateError,
);
};
@@ -147,8 +147,8 @@ export class OTelCall {
new OTelCallFeedMediaStreamSpan(
ElementCallOpenTelemetry.instance,
this.span,
feed
)
feed,
),
);
}
this.trackFeedSpan.get(feed.stream)?.update(feed);
@@ -171,13 +171,13 @@ export class OTelCall {
new OTelCallTransceiverMediaStreamSpan(
ElementCallOpenTelemetry.instance,
this.span,
transStats
)
transStats,
),
);
}
this.trackTransceiverSpan.get(transStats.mid)?.update(transStats);
prvTransSpan = prvTransSpan.filter(
(prvStreamId) => prvStreamId !== transStats.mid
(prvStreamId) => prvStreamId !== transStats.mid,
);
});
@@ -190,7 +190,7 @@ export class OTelCall {
public end(): void {
this.trackFeedSpan.forEach((feedSpan) => feedSpan.end());
this.trackTransceiverSpan.forEach((transceiverSpan) =>
transceiverSpan.end()
transceiverSpan.end(),
);
this.span.end();
}

View File

@@ -32,11 +32,11 @@ export abstract class OTelCallAbstractMediaStreamSpan {
public constructor(
protected readonly oTel: ElementCallOpenTelemetry,
protected readonly callSpan: Span,
protected readonly type: string
protected readonly type: string,
) {
const ctx = opentelemetry.trace.setSpan(
opentelemetry.context.active(),
callSpan
callSpan,
);
const options = {
links: [
@@ -54,7 +54,7 @@ export abstract class OTelCallAbstractMediaStreamSpan {
if (!this.trackSpans.has(t.id)) {
this.trackSpans.set(
t.id,
new OTelCallMediaStreamTrackSpan(this.oTel, this.span, t)
new OTelCallMediaStreamTrackSpan(this.oTel, this.span, t),
);
}
this.trackSpans.get(t.id)?.update(t);

View File

@@ -29,7 +29,7 @@ export class OTelCallFeedMediaStreamSpan extends OTelCallAbstractMediaStreamSpan
public constructor(
protected readonly oTel: ElementCallOpenTelemetry,
protected readonly callSpan: Span,
callFeed: CallFeedStats
callFeed: CallFeedStats,
) {
const postFix =
callFeed.type === "local" && callFeed.prefix === "from-call-feed"

View File

@@ -26,11 +26,11 @@ export class OTelCallMediaStreamTrackSpan {
public constructor(
protected readonly oTel: ElementCallOpenTelemetry,
protected readonly streamSpan: Span,
data: TrackStats
data: TrackStats,
) {
const ctx = opentelemetry.trace.setSpan(
opentelemetry.context.active(),
streamSpan
streamSpan,
);
const options = {
links: [

View File

@@ -32,7 +32,7 @@ export class OTelCallTransceiverMediaStreamSpan extends OTelCallAbstractMediaStr
public constructor(
protected readonly oTel: ElementCallOpenTelemetry,
protected readonly callSpan: Span,
stats: TransceiverStats
stats: TransceiverStats,
) {
super(oTel, callSpan, `matrix.call.transceiver.${stats.mid}`);
this.span.setAttribute("transceiver.mid", stats.mid);

View File

@@ -62,7 +62,10 @@ export class OTelGroupCallMembership {
};
private readonly speakingSpans = new Map<RoomMember, Map<string, Span>>();
public constructor(private groupCall: GroupCall, client: MatrixClient) {
public constructor(
private groupCall: GroupCall,
client: MatrixClient,
) {
const clientId = client.getUserId();
if (clientId) {
this.myUserId = clientId;
@@ -79,7 +82,7 @@ export class OTelGroupCallMembership {
public dispose(): void {
this.groupCall.removeListener(
GroupCallEvent.CallsChanged,
this.onCallsChanged
this.onCallsChanged,
);
}
@@ -93,22 +96,22 @@ export class OTelGroupCallMembership {
// Create the main span that tracks the time we intend to be in the call
this.callMembershipSpan =
ElementCallOpenTelemetry.instance.tracer.startSpan(
"matrix.groupCallMembership"
"matrix.groupCallMembership",
);
this.callMembershipSpan.setAttribute(
"matrix.confId",
this.groupCall.groupCallId
this.groupCall.groupCallId,
);
this.callMembershipSpan.setAttribute("matrix.userId", this.myUserId);
this.callMembershipSpan.setAttribute("matrix.deviceId", this.myDeviceId);
this.callMembershipSpan.setAttribute(
"matrix.displayName",
this.myMember ? this.myMember.name : "unknown-name"
this.myMember ? this.myMember.name : "unknown-name",
);
this.groupCallContext = opentelemetry.trace.setSpan(
opentelemetry.context.active(),
this.callMembershipSpan
this.callMembershipSpan,
);
this.callMembershipSpan?.addEvent("matrix.joinCall");
@@ -138,7 +141,7 @@ export class OTelGroupCallMembership {
this.callMembershipSpan?.addEvent(
`matrix.roomStateEvent_${event.getType()}`,
ObjectFlattener.flattenVoipEvent(event.getContent())
ObjectFlattener.flattenVoipEvent(event.getContent()),
);
}
@@ -150,7 +153,7 @@ export class OTelGroupCallMembership {
const span = ElementCallOpenTelemetry.instance.tracer.startSpan(
`matrix.call`,
undefined,
this.groupCallContext
this.groupCallContext,
);
// XXX: anonymity
span.setAttribute("matrix.call.target.userId", userId);
@@ -160,7 +163,7 @@ export class OTelGroupCallMembership {
span.setAttribute("matrix.call.target.displayName", displayName);
this.callsByCallId.set(
call.callId,
new OTelCall(userId, deviceId, call, span)
new OTelCall(userId, deviceId, call, span),
);
}
}
@@ -210,12 +213,12 @@ export class OTelGroupCallMembership {
if (event.type === "toDevice") {
callTrackingInfo.span.addEvent(
`matrix.sendToDeviceEvent_${event.eventType}`,
ObjectFlattener.flattenVoipEvent(event)
ObjectFlattener.flattenVoipEvent(event),
);
} else if (event.type === "sendEvent") {
callTrackingInfo.span.addEvent(
`matrix.sendToRoomEvent_${event.eventType}`,
ObjectFlattener.flattenVoipEvent(event)
ObjectFlattener.flattenVoipEvent(event),
);
}
}
@@ -239,7 +242,7 @@ export class OTelGroupCallMembership {
"matrix.receive_voip_event_unknown_callid",
{
"sender.userId": event.getSender(),
}
},
);
logger.error("Received call event for unknown call ID " + callId);
return;
@@ -284,7 +287,7 @@ export class OTelGroupCallMembership {
public onSpeaking(
member: RoomMember,
deviceId: string,
speaking: boolean
speaking: boolean,
): void {
if (speaking) {
// Ensure that there's an audio activity span for this speaker
@@ -298,7 +301,7 @@ export class OTelGroupCallMembership {
const span = ElementCallOpenTelemetry.instance.tracer.startSpan(
"matrix.audioActivity",
undefined,
this.groupCallContext
this.groupCallContext,
);
span.setAttribute("matrix.userId", member.userId);
span.setAttribute("matrix.displayName", member.rawDisplayName);
@@ -336,7 +339,7 @@ export class OTelGroupCallMembership {
}
public onCallFeedStatsReport(
report: GroupCallStatsReport<CallFeedReport>
report: GroupCallStatsReport<CallFeedReport>,
): void {
if (!ElementCallOpenTelemetry.instance) return;
let call: OTelCall | undefined;
@@ -354,10 +357,10 @@ export class OTelGroupCallMembership {
"call.opponentMemberId": report.report?.opponentMemberId
? report.report?.opponentMemberId
: "unknown",
}
},
);
logger.error(
`Received ${OTelStatsReportType.CallFeedReport} with unknown call ID: ${callId}`
`Received ${OTelStatsReportType.CallFeedReport} with unknown call ID: ${callId}`,
);
return;
} else {
@@ -367,26 +370,26 @@ export class OTelGroupCallMembership {
}
public onConnectionStatsReport(
statsReport: GroupCallStatsReport<ConnectionStatsReport>
statsReport: GroupCallStatsReport<ConnectionStatsReport>,
): void {
this.buildCallStatsSpan(
OTelStatsReportType.ConnectionReport,
statsReport.report
statsReport.report,
);
}
public onByteSentStatsReport(
statsReport: GroupCallStatsReport<ByteSentStatsReport>
statsReport: GroupCallStatsReport<ByteSentStatsReport>,
): void {
this.buildCallStatsSpan(
OTelStatsReportType.ByteSentReport,
statsReport.report
statsReport.report,
);
}
public buildCallStatsSpan(
type: OTelStatsReportType,
report: ByteSentStatsReport | ConnectionStatsReport
report: ByteSentStatsReport | ConnectionStatsReport,
): void {
if (!ElementCallOpenTelemetry.instance) return;
let call: OTelCall | undefined;
@@ -409,7 +412,7 @@ export class OTelGroupCallMembership {
const data = ObjectFlattener.flattenReportObject(type, report);
const ctx = opentelemetry.trace.setSpan(
opentelemetry.context.active(),
call.span
call.span,
);
const options = {
@@ -423,20 +426,20 @@ export class OTelGroupCallMembership {
const span = ElementCallOpenTelemetry.instance.tracer.startSpan(
type,
options,
ctx
ctx,
);
span.setAttribute("matrix.callId", callId ?? "unknown");
span.setAttribute(
"matrix.opponentMemberId",
report.opponentMemberId ? report.opponentMemberId : "unknown"
report.opponentMemberId ? report.opponentMemberId : "unknown",
);
span.addEvent("matrix.call.connection_stats_event", data);
span.end();
}
public onSummaryStatsReport(
statsReport: GroupCallStatsReport<SummaryStatsReport>
statsReport: GroupCallStatsReport<SummaryStatsReport>,
): void {
if (!ElementCallOpenTelemetry.instance) return;
@@ -445,12 +448,12 @@ export class OTelGroupCallMembership {
if (this.statsReportSpan.span === undefined && this.callMembershipSpan) {
const ctx = setSpan(
opentelemetry.context.active(),
this.callMembershipSpan
this.callMembershipSpan,
);
const span = ElementCallOpenTelemetry.instance?.tracer.startSpan(
"matrix.groupCallMembership.summaryReport",
undefined,
ctx
ctx,
);
if (span === undefined) {
return;
@@ -459,7 +462,7 @@ export class OTelGroupCallMembership {
span.setAttribute("matrix.userId", this.myUserId);
span.setAttribute(
"matrix.displayName",
this.myMember ? this.myMember.name : "unknown-name"
this.myMember ? this.myMember.name : "unknown-name",
);
span.addEvent(type, data);
span.end();

View File

@@ -25,7 +25,7 @@ import {
export class ObjectFlattener {
public static flattenReportObject(
prefix: string,
report: ConnectionStatsReport | ByteSentStatsReport
report: ConnectionStatsReport | ByteSentStatsReport,
): Attributes {
const flatObject = {};
ObjectFlattener.flattenObjectRecursive(report, flatObject, `${prefix}.`, 0);
@@ -33,27 +33,27 @@ export class ObjectFlattener {
}
public static flattenByteSentStatsReportObject(
statsReport: GroupCallStatsReport<ByteSentStatsReport>
statsReport: GroupCallStatsReport<ByteSentStatsReport>,
): Attributes {
const flatObject = {};
ObjectFlattener.flattenObjectRecursive(
statsReport.report,
flatObject,
"matrix.stats.bytesSent.",
0
0,
);
return flatObject;
}
public static flattenSummaryStatsReportObject(
statsReport: GroupCallStatsReport<SummaryStatsReport>
statsReport: GroupCallStatsReport<SummaryStatsReport>,
): Attributes {
const flatObject = {};
ObjectFlattener.flattenObjectRecursive(
statsReport.report,
flatObject,
"matrix.stats.summary.",
0
0,
);
return flatObject;
}
@@ -67,7 +67,7 @@ export class ObjectFlattener {
event as unknown as Record<string, unknown>, // XXX Types
flatObject,
"matrix.event.",
0
0,
);
return flatObject;
@@ -77,12 +77,12 @@ export class ObjectFlattener {
obj: Object,
flatObject: Attributes,
prefix: string,
depth: number
depth: number,
): void {
if (depth > 10)
throw new Error(
"Depth limit exceeded: aborting VoipEvent recursion. Prefix is " +
prefix
prefix,
);
let entries;
if (obj instanceof Map) {
@@ -101,7 +101,7 @@ export class ObjectFlattener {
v,
flatObject,
prefix + k + ".",
depth + 1
depth + 1,
);
}
}

View File

@@ -50,7 +50,7 @@ export class ElementCallOpenTelemetry {
sharedInstance = new ElementCallOpenTelemetry(
config.opentelemetry?.collector_url,
config.rageshake?.submit_url
config.rageshake?.submit_url,
);
}
}
@@ -61,7 +61,7 @@ export class ElementCallOpenTelemetry {
private constructor(
collectorUrl: string | undefined,
rageshakeUrl: string | undefined
rageshakeUrl: string | undefined,
) {
// This is how we can make Jaeger show a reasonable service in the dropdown on the left.
const providerConfig = {
@@ -77,7 +77,7 @@ export class ElementCallOpenTelemetry {
url: collectorUrl,
});
this._provider.addSpanProcessor(
new SimpleSpanProcessor(this.otlpExporter)
new SimpleSpanProcessor(this.otlpExporter),
);
} else {
logger.info("OTLP collector disabled");
@@ -93,7 +93,7 @@ export class ElementCallOpenTelemetry {
this._tracer = opentelemetry.trace.getTracer(
// This is not the serviceName shown in jaeger
"my-element-call-otl-tracer"
"my-element-call-otl-tracer",
);
}

View File

@@ -40,7 +40,7 @@ export const Popover = forwardRef<HTMLDivElement, Props>(
shouldCloseOnBlur: true,
isDismissable: true,
},
popoverRef
popoverRef,
);
return (
@@ -56,5 +56,5 @@ export const Popover = forwardRef<HTMLDivElement, Props>(
</div>
</FocusScope>
);
}
},
);

View File

@@ -43,7 +43,7 @@ export const PopoverMenuTrigger = forwardRef<
const { menuTriggerProps, menuProps } = useMenuTrigger(
{},
popoverMenuState,
buttonRef
buttonRef,
);
const popoverRef = useRef(null);
@@ -62,7 +62,7 @@ export const PopoverMenuTrigger = forwardRef<
typeof children[1] !== "function"
) {
throw new Error(
"PopoverMenu must have two props. The first being a button and the second being a render prop."
"PopoverMenu must have two props. The first being a button and the second being a render prop.",
);
}

View File

@@ -63,7 +63,7 @@ export function useProfile(client: MatrixClient | undefined): UseProfile {
useEffect(() => {
const onChangeUser = (
_event: MatrixEvent | undefined,
{ displayName, avatarUrl }: User
{ displayName, avatarUrl }: User,
): void => {
setState({
success: false,
@@ -108,9 +108,8 @@ export function useProfile(client: MatrixClient | undefined): UseProfile {
if (removeAvatar) {
await client.setAvatarUrl("");
} else if (avatar) {
({ content_uri: mxcAvatarUrl } = await client.uploadContent(
avatar
));
({ content_uri: mxcAvatarUrl } =
await client.uploadContent(avatar));
await client.setAvatarUrl(mxcAvatarUrl);
}
@@ -135,7 +134,7 @@ export function useProfile(client: MatrixClient | undefined): UseProfile {
logger.error("Client not initialized before calling saveProfile");
}
},
[client]
[client],
);
return {

View File

@@ -40,14 +40,14 @@ export const AppSelectionModal: FC<Props> = ({ roomId }) => {
e.stopPropagation();
setOpen(false);
},
[setOpen]
[setOpen],
);
const roomSharedKey = useRoomSharedKey(roomId ?? "");
const roomIsEncrypted = useIsRoomE2EE(roomId ?? "");
if (roomIsEncrypted && roomSharedKey === undefined) {
logger.error(
"Generating app redirect URL for encrypted room but don't have key available!"
"Generating app redirect URL for encrypted room but don't have key available!",
);
}
@@ -60,7 +60,7 @@ export const AppSelectionModal: FC<Props> = ({ roomId }) => {
const url = new URL(
roomId === null
? window.location.href
: getAbsoluteRoomUrl(roomId, undefined, roomSharedKey ?? undefined)
: getAbsoluteRoomUrl(roomId, undefined, roomSharedKey ?? undefined),
);
// Edit the URL to prevent the app selection prompt from appearing a second
// time within the app, and to keep the user confined to the current room

View File

@@ -64,7 +64,7 @@ export const CallEndedView: FC<Props> = ({
PosthogAnalytics.instance.eventQualitySurvey.track(
endedCallId,
feedbackText,
starRating
starRating,
);
setSubmitting(true);
@@ -83,7 +83,7 @@ export const CallEndedView: FC<Props> = ({
}, 1000);
}, 1000);
},
[endedCallId, history, isPasswordlessUser, confineToRoom, starRating]
[endedCallId, history, isPasswordlessUser, confineToRoom, starRating],
);
const createAccountDialog = isPasswordlessUser && (

View File

@@ -47,7 +47,7 @@ export function GroupCallLoader({
ev.preventDefault();
history.push("/");
},
[history]
[history],
);
switch (groupCallState.kind) {
@@ -66,7 +66,7 @@ export function GroupCallLoader({
<Heading>{t("Call not found")}</Heading>
<Text>
{t(
"Calls are now end-to-end encrypted and need to be created from the home page. This helps make sure everyone's using the same encryption key."
"Calls are now end-to-end encrypted and need to be created from the home page. This helps make sure everyone's using the same encryption key.",
)}
</Text>
{/* XXX: A 'create it for me' button would be the obvious UX here. Two screens already have

View File

@@ -111,7 +111,7 @@ export const GroupCallView: FC<Props> = ({
// Count each member only once, regardless of how many devices they use
const participantCount = useMemo(
() => new Set<string>(memberships.map((m) => m.sender!)).size,
[memberships]
[memberships],
);
const deviceContext = useMediaDevices();
@@ -126,7 +126,7 @@ export const GroupCallView: FC<Props> = ({
if (widget && preload) {
// In preload mode, wait for a join action before entering
const onJoin = async (
ev: CustomEvent<IWidgetApiRequest>
ev: CustomEvent<IWidgetApiRequest>,
): Promise<void> => {
// XXX: I think this is broken currently - LiveKit *won't* request
// permissions and give you device names unless you specify a kind, but
@@ -143,14 +143,14 @@ export const GroupCallView: FC<Props> = ({
const deviceId = await findDeviceByName(
audioInput,
"audioinput",
devices
devices,
);
if (!deviceId) {
logger.warn("Unknown audio input: " + audioInput);
latestMuteStates.current!.audio.setEnabled?.(false);
} else {
logger.debug(
`Found audio input ID ${deviceId} for name ${audioInput}`
`Found audio input ID ${deviceId} for name ${audioInput}`,
);
latestDevices.current!.audioInput.select(deviceId);
latestMuteStates.current!.audio.setEnabled?.(true);
@@ -163,14 +163,14 @@ export const GroupCallView: FC<Props> = ({
const deviceId = await findDeviceByName(
videoInput,
"videoinput",
devices
devices,
);
if (!deviceId) {
logger.warn("Unknown video input: " + videoInput);
latestMuteStates.current!.video.setEnabled?.(false);
} else {
logger.debug(
`Found video input ID ${deviceId} for name ${videoInput}`
`Found video input ID ${deviceId} for name ${videoInput}`,
);
latestDevices.current!.videoInput.select(deviceId);
latestMuteStates.current!.video.setEnabled?.(true);
@@ -182,7 +182,7 @@ export const GroupCallView: FC<Props> = ({
PosthogAnalytics.instance.eventCallEnded.cacheStartCall(new Date());
// we only have room sessions right now, so call ID is the emprty string - we use the room ID
PosthogAnalytics.instance.eventCallStarted.track(
rtcSession.room.roomId
rtcSession.room.roomId,
);
await Promise.all([
@@ -213,7 +213,7 @@ export const GroupCallView: FC<Props> = ({
PosthogAnalytics.instance.eventCallEnded.track(
rtcSession.room.roomId,
rtcSession.memberships.length,
sendInstantly
sendInstantly,
);
await leaveRTCSession(rtcSession);
@@ -237,13 +237,13 @@ export const GroupCallView: FC<Props> = ({
history.push("/");
}
},
[rtcSession, isPasswordlessUser, confineToRoom, history]
[rtcSession, isPasswordlessUser, confineToRoom, history],
);
useEffect(() => {
if (widget && isJoined) {
const onHangup = async (
ev: CustomEvent<IWidgetApiRequest>
ev: CustomEvent<IWidgetApiRequest>,
): Promise<void> => {
leaveRTCSession(rtcSession);
widget!.api.transport.reply(ev.detail, {});
@@ -260,7 +260,7 @@ export const GroupCallView: FC<Props> = ({
const e2eeConfig = useMemo(
() => (e2eeSharedKey ? { sharedKey: e2eeSharedKey } : undefined),
[e2eeSharedKey]
[e2eeSharedKey],
);
const onReconnect = useCallback(() => {
@@ -274,12 +274,12 @@ export const GroupCallView: FC<Props> = ({
const [shareModalOpen, setInviteModalOpen] = useState(false);
const onDismissInviteModal = useCallback(
() => setInviteModalOpen(false),
[setInviteModalOpen]
[setInviteModalOpen],
);
const onShareClickFn = useCallback(
() => setInviteModalOpen(true),
[setInviteModalOpen]
[setInviteModalOpen],
);
const onShareClick = joinRule === JoinRule.Public ? onShareClickFn : null;
@@ -288,7 +288,7 @@ export const GroupCallView: FC<Props> = ({
ev.preventDefault();
history.push("/");
},
[history]
[history],
);
const { t } = useTranslation();
@@ -298,7 +298,7 @@ export const GroupCallView: FC<Props> = ({
<ErrorView
error={
new Error(
"No E2EE key provided: please make sure the URL you're using to join this call has been retrieved using the in-app button."
"No E2EE key provided: please make sure the URL you're using to join this call has been retrieved using the in-app button.",
)
}
/>
@@ -309,7 +309,7 @@ export const GroupCallView: FC<Props> = ({
<Heading>Incompatible Browser</Heading>
<Text>
{t(
"Your web browser does not support media end-to-end encryption. Supported Browsers are Chrome, Safari, Firefox >=117"
"Your web browser does not support media end-to-end encryption. Supported Browsers are Chrome, Safari, Firefox >=117",
)}
</Text>
<Link href="/" onClick={onHomeClick}>

View File

@@ -105,7 +105,7 @@ export const ActiveCall: FC<ActiveCallProps> = (props) => {
const { livekitRoom, connState } = useLiveKit(
props.muteStates,
sfuConfig,
props.e2eeConfig
props.e2eeConfig,
);
if (!livekitRoom) {
@@ -172,10 +172,10 @@ export const InCallView: FC<InCallViewProps> = ({
[{ source: Track.Source.ScreenShare, withPlaceholder: false }],
{
room: livekitRoom,
}
},
);
const { layout, setLayout } = useVideoGridLayout(
screenSharingTracks.length > 0
screenSharingTracks.length > 0,
);
const [showConnectionStats] = useShowConnectionStats();
@@ -188,11 +188,11 @@ export const InCallView: FC<InCallViewProps> = ({
const toggleMicrophone = useCallback(
() => muteStates.audio.setEnabled?.((e) => !e),
[muteStates]
[muteStates],
);
const toggleCamera = useCallback(
() => muteStates.video.setEnabled?.((e) => !e),
[muteStates]
[muteStates],
);
// This function incorrectly assumes that there is a camera and microphone, which is not always the case.
@@ -201,7 +201,7 @@ export const InCallView: FC<InCallViewProps> = ({
containerRef1,
toggleMicrophone,
toggleCamera,
(muted) => muteStates.audio.setEnabled?.(!muted)
(muted) => muteStates.audio.setEnabled?.(!muted),
);
const onLeavePress = useCallback(() => {
@@ -213,7 +213,7 @@ export const InCallView: FC<InCallViewProps> = ({
layout === "grid"
? ElementWidgetActions.TileLayout
: ElementWidgetActions.SpotlightLayout,
{}
{},
);
}, [layout]);
@@ -231,14 +231,14 @@ export const InCallView: FC<InCallViewProps> = ({
widget.lazyActions.on(ElementWidgetActions.TileLayout, onTileLayout);
widget.lazyActions.on(
ElementWidgetActions.SpotlightLayout,
onSpotlightLayout
onSpotlightLayout,
);
return () => {
widget!.lazyActions.off(ElementWidgetActions.TileLayout, onTileLayout);
widget!.lazyActions.off(
ElementWidgetActions.SpotlightLayout,
onSpotlightLayout
onSpotlightLayout,
);
};
}
@@ -261,7 +261,7 @@ export const InCallView: FC<InCallViewProps> = ({
(noControls
? items.find((item) => item.isSpeaker) ?? items.at(0) ?? null
: null),
[fullscreenItem, noControls, items]
[fullscreenItem, noControls, items],
);
const Grid =
@@ -320,18 +320,18 @@ export const InCallView: FC<InCallViewProps> = ({
};
const rageshakeRequestModalProps = useRageshakeRequestModal(
rtcSession.room.roomId
rtcSession.room.roomId,
);
const [settingsModalOpen, setSettingsModalOpen] = useState(false);
const openSettings = useCallback(
() => setSettingsModalOpen(true),
[setSettingsModalOpen]
[setSettingsModalOpen],
);
const closeSettings = useCallback(
() => setSettingsModalOpen(false),
[setSettingsModalOpen]
[setSettingsModalOpen],
);
const toggleScreensharing = useCallback(async () => {
@@ -365,7 +365,7 @@ export const InCallView: FC<InCallViewProps> = ({
onPress={toggleCamera}
disabled={muteStates.video.setEnabled === null}
data-testid="incall_videomute"
/>
/>,
);
if (!reducedControls) {
@@ -376,14 +376,18 @@ export const InCallView: FC<InCallViewProps> = ({
enabled={isScreenShareEnabled}
onPress={toggleScreensharing}
data-testid="incall_screenshare"
/>
/>,
);
}
buttons.push(<SettingsButton key="4" onPress={openSettings} />);
}
buttons.push(
<HangupButton key="6" onPress={onLeavePress} data-testid="incall_leave" />
<HangupButton
key="6"
onPress={onLeavePress}
data-testid="incall_leave"
/>,
);
footer = (
<div className={styles.footer}>
@@ -447,7 +451,7 @@ export const InCallView: FC<InCallViewProps> = ({
function findMatrixMember(
room: MatrixRoom,
id: string
id: string,
): RoomMember | undefined {
if (!id) return undefined;
@@ -455,7 +459,7 @@ function findMatrixMember(
// must be at least 3 parts because we know the first part is a userId which must necessarily contain a colon
if (parts.length < 3) {
logger.warn(
"Livekit participants ID doesn't look like a userId:deviceId combination"
"Livekit participants ID doesn't look like a userId:deviceId combination",
);
return undefined;
}
@@ -469,7 +473,7 @@ function findMatrixMember(
function useParticipantTiles(
livekitRoom: Room,
matrixRoom: MatrixRoom,
connState: ECConnectionState
connState: ECConnectionState,
): TileDescriptor<ItemData>[] {
const previousTiles = useRef<TileDescriptor<ItemData>[]>([]);
@@ -498,7 +502,7 @@ function useParticipantTiles(
// connected, this is fine and we'll be in "all ghosts" mode.
if (id !== "" && member === undefined) {
logger.warn(
`Ruh, roh! No matrix member found for SFU participant '${id}': creating g-g-g-ghost!`
`Ruh, roh! No matrix member found for SFU participant '${id}': creating g-g-g-ghost!`,
);
}
allGhosts &&= member === undefined;
@@ -542,11 +546,11 @@ function useParticipantTiles(
return screenShareTile
? [userMediaTile, screenShareTile]
: [userMediaTile];
}
},
);
PosthogAnalytics.instance.eventCallEnded.cacheParticipantCountChanged(
tiles.length
tiles.length,
);
// If every item is a ghost, that probably means we're still connecting and

View File

@@ -40,7 +40,7 @@ export const InviteModal: FC<Props> = ({ room, open, onDismiss }) => {
const url = useMemo(
() =>
getAbsoluteRoomUrl(room.roomId, room.name, roomSharedKey ?? undefined),
[room, roomSharedKey]
[room, roomSharedKey],
);
const [, setCopied] = useClipboard(url);
const [toastOpen, setToastOpen] = useState(false);
@@ -53,7 +53,7 @@ export const InviteModal: FC<Props> = ({ room, open, onDismiss }) => {
onDismiss();
setToastOpen(true);
},
[setCopied, onDismiss]
[setCopied, onDismiss],
);
return (

View File

@@ -36,7 +36,7 @@ export const LayoutToggle: FC<Props> = ({ layout, setLayout, className }) => {
const onChange = useCallback(
(e: ChangeEvent<HTMLInputElement>) => setLayout(e.target.value as Layout),
[setLayout]
[setLayout],
);
const spotlightId = useId();

View File

@@ -63,22 +63,22 @@ export const LobbyView: FC<Props> = ({
const onAudioPress = useCallback(
() => muteStates.audio.setEnabled?.((e) => !e),
[muteStates]
[muteStates],
);
const onVideoPress = useCallback(
() => muteStates.video.setEnabled?.((e) => !e),
[muteStates]
[muteStates],
);
const [settingsModalOpen, setSettingsModalOpen] = useState(false);
const openSettings = useCallback(
() => setSettingsModalOpen(true),
[setSettingsModalOpen]
[setSettingsModalOpen],
);
const closeSettings = useCallback(
() => setSettingsModalOpen(false),
[setSettingsModalOpen]
[setSettingsModalOpen],
);
const history = useHistory();

View File

@@ -49,18 +49,18 @@ export interface MuteStates {
function useMuteState(
device: MediaDevice,
enabledByDefault: () => boolean
enabledByDefault: () => boolean,
): MuteState {
const [enabled, setEnabled] = useReactiveState<boolean>(
(prev) => device.available.length > 0 && (prev ?? enabledByDefault()),
[device]
[device],
);
return useMemo(
() =>
device.available.length === 0
? deviceUnavailable
: { enabled, setEnabled },
[device, enabled, setEnabled]
[device, enabled, setEnabled],
);
}
@@ -69,7 +69,7 @@ export function useMuteStates(participantCount: number): MuteStates {
const audio = useMuteState(
devices.audioInput,
() => participantCount <= MUTE_PARTICIPANT_COUNT
() => participantCount <= MUTE_PARTICIPANT_COUNT,
);
const video = useMuteState(devices.videoInput, () => true);

View File

@@ -47,7 +47,7 @@ export const RageshakeRequestModal: FC<Props> = ({
<Modal title={t("Debug log request")} open={open} onDismiss={onDismiss}>
<Body>
{t(
"Another user on this call is having an issue. In order to better diagnose these issues we'd like to collect a debug log."
"Another user on this call is having an issue. In order to better diagnose these issues we'd like to collect a debug log.",
)}
</Body>
<FieldRow>

View File

@@ -52,7 +52,7 @@ export const RoomAuthView: FC = () => {
setError(error);
});
},
[registerPasswordlessUser]
[registerPasswordlessUser],
);
const { t } = useTranslation();

View File

@@ -81,7 +81,7 @@ export const RoomPage: FC = () => {
hideHeader={hideHeader}
/>
),
[client, passwordlessUser, confineToRoom, preload, hideHeader]
[client, passwordlessUser, confineToRoom, preload, hideHeader],
);
let content: ReactNode;

View File

@@ -82,14 +82,14 @@ export const VideoPreview: FC<Props> = ({
},
(error) => {
logger.error("Error while creating preview Tracks:", error);
}
},
);
const videoTrack = useMemo(
() =>
tracks?.find((t) => t.kind === Track.Kind.Video) as
| LocalVideoTrack
| undefined,
[tracks]
[tracks],
);
const videoEl = useRef<HTMLVideoElement | null>(null);

View File

@@ -24,7 +24,7 @@ import { deepCompare } from "matrix-js-sdk/src/utils";
import { LivekitFocus } from "../livekit/LivekitFocus";
function getActiveFocus(
rtcSession: MatrixRTCSession
rtcSession: MatrixRTCSession,
): LivekitFocus | undefined {
const oldestMembership = rtcSession.getOldestMembership();
return oldestMembership?.getActiveFoci()[0] as LivekitFocus;
@@ -36,10 +36,10 @@ function getActiveFocus(
* and the same focus.
*/
export function useActiveFocus(
rtcSession: MatrixRTCSession
rtcSession: MatrixRTCSession,
): LivekitFocus | undefined {
const [activeFocus, setActiveFocus] = useState(() =>
getActiveFocus(rtcSession)
getActiveFocus(rtcSession),
);
const onMembershipsChanged = useCallback(() => {
@@ -53,13 +53,13 @@ export function useActiveFocus(
useEffect(() => {
rtcSession.on(
MatrixRTCSessionEvent.MembershipsChanged,
onMembershipsChanged
onMembershipsChanged,
);
return () => {
rtcSession.off(
MatrixRTCSessionEvent.MembershipsChanged,
onMembershipsChanged
onMembershipsChanged,
);
};
});

View File

@@ -66,7 +66,7 @@ export function useFullscreen<T>(items: TileDescriptor<T>[]): {
prevItem == null
? null
: items.find((i) => i.id === prevItem.id) ?? null,
[items]
[items],
);
const latestItems = useRef<TileDescriptor<T>[]>(items);
@@ -80,15 +80,15 @@ export function useFullscreen<T>(items: TileDescriptor<T>[]): {
setFullscreenItem(
latestFullscreenItem.current === null
? latestItems.current.find((i) => i.id === itemId) ?? null
: null
: null,
);
},
[setFullscreenItem]
[setFullscreenItem],
);
const exitFullscreenCallback = useCallback(
() => setFullscreenItem(null),
[setFullscreenItem]
[setFullscreenItem],
);
useLayoutEffect(() => {
@@ -103,7 +103,7 @@ export function useFullscreen<T>(items: TileDescriptor<T>[]): {
useFullscreenChange(
useCallback(() => {
if (!isFullscreen()) setFullscreenItem(null);
}, [setFullscreenItem])
}, [setFullscreenItem]),
);
return {

View File

@@ -23,6 +23,6 @@ import { useRoomState } from "./useRoomState";
export function useJoinRule(room: Room): JoinRule {
return useRoomState(
room,
useCallback((state) => state.getJoinRule(), [])
useCallback((state) => state.getJoinRule(), []),
);
}

View File

@@ -52,7 +52,7 @@ export interface GroupCallLoadState {
export const useLoadGroupCall = (
client: MatrixClient,
roomIdOrAlias: string,
viaServers: string[]
viaServers: string[],
): GroupCallStatus => {
const { t } = useTranslation();
const [state, setState] = useState<GroupCallStatus>({ kind: "loading" });
@@ -70,7 +70,7 @@ export const useLoadGroupCall = (
// join anyway but the js-sdk recreates the room if you pass the alias for a
// room you're already joined to (which it probably ought not to).
const lookupResult = await client.getRoomIdForAlias(
roomIdOrAlias.toLowerCase()
roomIdOrAlias.toLowerCase(),
);
logger.info(`${roomIdOrAlias} resolved to ${lookupResult.room_id}`);
room = client.getRoom(lookupResult.room_id);
@@ -81,7 +81,7 @@ export const useLoadGroupCall = (
});
} else {
logger.info(
`Already in room ${lookupResult.room_id}, not rejoining.`
`Already in room ${lookupResult.room_id}, not rejoining.`,
);
}
} else {
@@ -92,7 +92,7 @@ export const useLoadGroupCall = (
}
logger.info(
`Joined ${roomIdOrAlias}, waiting room to be ready for group calls`
`Joined ${roomIdOrAlias}, waiting room to be ready for group calls`,
);
await client.waitUntilRoomReadyForGroupCalls(room.roomId);
logger.info(`${roomIdOrAlias}, is ready for group calls`);
@@ -110,7 +110,7 @@ export const useLoadGroupCall = (
const waitForClientSyncing = async (): Promise<void> => {
if (client.getSyncState() !== SyncState.Syncing) {
logger.debug(
"useLoadGroupCall: waiting for client to start syncing..."
"useLoadGroupCall: waiting for client to start syncing...",
);
await new Promise<void>((resolve) => {
const onSync = (): void => {

View File

@@ -22,6 +22,6 @@ import { useRoomState } from "./useRoomState";
export function useRoomAvatar(room: Room): string | null {
return useRoomState(
room,
useCallback(() => room.getMxcAvatarUrl(), [room])
useCallback(() => room.getMxcAvatarUrl(), [room]),
);
}

View File

@@ -31,7 +31,7 @@ export const useRoomState = <T>(room: Room, f: (state: RoomState) => T): T => {
useTypedEventEmitter(
room,
RoomStateEvent.Update,
useCallback(() => setNumUpdates((n) => n + 1), [setNumUpdates])
useCallback(() => setNumUpdates((n) => n + 1), [setNumUpdates]),
);
// We want any change to the update counter to trigger an update here
// eslint-disable-next-line react-hooks/exhaustive-deps

View File

@@ -48,7 +48,7 @@ export function enterRTCSession(rtcSession: MatrixRTCSession): void {
}
export async function leaveRTCSession(
rtcSession: MatrixRTCSession
rtcSession: MatrixRTCSession,
): Promise<void> {
//groupCallOTelMembership?.onLeaveCall();
await rtcSession.leaveRoomSession();

View File

@@ -57,7 +57,7 @@ export const FeedbackSettingsTab: FC<Props> = ({ roomId }) => {
sendRageshakeRequest(roomId, rageshakeRequestId);
}
},
[submitRageshake, roomId, sendRageshakeRequest]
[submitRageshake, roomId, sendRageshakeRequest],
);
return (
@@ -65,7 +65,7 @@ export const FeedbackSettingsTab: FC<Props> = ({ roomId }) => {
<h4 className={styles.label}>{t("Submit feedback")}</h4>
<Body>
{t(
"If you are experiencing issues or simply would like to provide some feedback, please send us a short description below."
"If you are experiencing issues or simply would like to provide some feedback, please send us a short description below.",
)}
</Body>
<form onSubmit={onSubmitFeedback}>

View File

@@ -69,7 +69,7 @@ export const SettingsModal: FC<Props> = (props) => {
// Generate a `SelectInput` with a list of devices for a given device kind.
const generateDeviceSelection = (
devices: MediaDevice,
caption: string
caption: string,
): ReactNode => {
if (devices.available.length == 0) return null;
@@ -100,7 +100,7 @@ export const SettingsModal: FC<Props> = (props) => {
(tab: Key) => {
setSelectedTab(tab.toString());
},
[setSelectedTab]
[setSelectedTab],
);
const optInDescription = (

View File

@@ -133,7 +133,7 @@ class IndexedDBLogStore {
public constructor(
private indexedDB: IDBFactory,
private loggerInstance: ConsoleLogger
private loggerInstance: ConsoleLogger,
) {
this.id = "instance-" + randomString(16);
@@ -177,7 +177,7 @@ class IndexedDBLogStore {
logObjStore.createIndex("id", "id", { unique: false });
logObjStore.add(
this.generateLogEntry(new Date() + " ::: Log database was created.")
this.generateLogEntry(new Date() + " ::: Log database was created."),
);
// This records the last time each instance ID generated a log message, such
@@ -208,7 +208,7 @@ class IndexedDBLogStore {
{
leading: false,
trailing: true,
}
},
);
/**
@@ -366,8 +366,8 @@ class IndexedDBLogStore {
txn.onerror = (): void => {
reject(
new Error(
"Failed to delete logs for " + `'${id}' : ${txn?.error?.message}`
)
"Failed to delete logs for " + `'${id}' : ${txn?.error?.message}`,
),
);
};
// delete last modified entries
@@ -410,7 +410,7 @@ class IndexedDBLogStore {
},
(err) => {
logger.error(err);
}
},
);
}
return logs;
@@ -445,7 +445,7 @@ class IndexedDBLogStore {
function selectQuery<T>(
store: IDBObjectStore,
keyRange: IDBKeyRange | undefined,
resultMapper: (cursor: IDBCursorWithValue) => T
resultMapper: (cursor: IDBCursorWithValue) => T,
): Promise<T[]> {
const query = store.openCursor(keyRange);
return new Promise((resolve, reject) => {
@@ -510,7 +510,7 @@ function tryInitStorage(): Promise<void> {
if (indexedDB) {
global.mx_rage_store = new IndexedDBLogStore(
indexedDB,
global.mx_rage_logger
global.mx_rage_logger,
);
global.mx_rage_initStoragePromise = global.mx_rage_store.connect();
return global.mx_rage_initStoragePromise;
@@ -547,7 +547,7 @@ export async function getLogsForReport(): Promise<LogEntry[]> {
type StringifyReplacer = (
this: unknown,
key: string,
value: unknown
value: unknown,
) => unknown;
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cyclic_object_value#circular_references
@@ -600,7 +600,7 @@ export function setLogExtension(extension: LogExtensionFunc): void {
logger.methodFactory = function (
methodName,
configLevel,
loggerName
loggerName,
): LoggingMethod {
const rawMethod = originalFactory(methodName, configLevel, loggerName);

View File

@@ -95,12 +95,12 @@ export function useSubmitRageshake(): {
const body = new FormData();
body.append(
"text",
description ?? "User did not supply any additional text."
description ?? "User did not supply any additional text.",
);
body.append("app", "matrix-video-chat");
body.append(
"version",
(import.meta.env.VITE_APP_VERSION as string) || "dev"
(import.meta.env.VITE_APP_VERSION as string) || "dev",
);
body.append("user_agent", userAgent);
body.append("installed_pwa", "false");
@@ -132,22 +132,22 @@ export function useSubmitRageshake(): {
body.append(
"cross_signing_ready",
String(await client.isCrossSigningReady())
String(await client.isCrossSigningReady()),
);
body.append(
"cross_signing_supported_by_hs",
String(
await client.doesServerSupportUnstableFeature(
"org.matrix.e2e_cross_signing"
)
)
"org.matrix.e2e_cross_signing",
),
),
);
body.append("cross_signing_key", crossSigning.getId()!);
body.append(
"cross_signing_privkey_in_secret_storage",
String(
!!(await crossSigning.isStoredInSecretStorage(secretStorage))
)
!!(await crossSigning.isStoredInSecretStorage(secretStorage)),
),
);
const pkCache = client.getCrossSigningCacheCallbacks();
@@ -157,8 +157,8 @@ export function useSubmitRageshake(): {
!!(
pkCache?.getCrossSigningKeyCache &&
(await pkCache.getCrossSigningKeyCache("master"))
)
)
),
),
);
body.append(
"cross_signing_self_signing_privkey_cached",
@@ -166,8 +166,8 @@ export function useSubmitRageshake(): {
!!(
pkCache?.getCrossSigningKeyCache &&
(await pkCache.getCrossSigningKeyCache("self_signing"))
)
)
),
),
);
body.append(
"cross_signing_user_signing_privkey_cached",
@@ -175,32 +175,32 @@ export function useSubmitRageshake(): {
!!(
pkCache?.getCrossSigningKeyCache &&
(await pkCache.getCrossSigningKeyCache("user_signing"))
)
)
),
),
);
body.append(
"secret_storage_ready",
String(await client.isSecretStorageReady())
String(await client.isSecretStorageReady()),
);
body.append(
"secret_storage_key_in_account",
String(!!(await secretStorage.hasKey()))
String(!!(await secretStorage.hasKey())),
);
body.append(
"session_backup_key_in_secret_storage",
String(!!(await client.isKeyBackupKeyStored()))
String(!!(await client.isKeyBackupKeyStored())),
);
const sessionBackupKeyFromCache =
await client.crypto!.getSessionBackupPrivateKey();
body.append(
"session_backup_key_cached",
String(!!sessionBackupKeyFromCache)
String(!!sessionBackupKeyFromCache),
);
body.append(
"session_backup_key_well_formed",
String(sessionBackupKeyFromCache instanceof Uint8Array)
String(sessionBackupKeyFromCache instanceof Uint8Array),
);
}
}
@@ -214,7 +214,7 @@ export function useSubmitRageshake(): {
try {
body.append(
"storageManager_persisted",
String(await navigator.storage.persisted())
String(await navigator.storage.persisted()),
);
} catch (e) {}
} else if (document.hasStorageAccess) {
@@ -222,7 +222,7 @@ export function useSubmitRageshake(): {
try {
body.append(
"storageManager_persisted",
String(await document.hasStorageAccess())
String(await document.hasStorageAccess()),
);
} catch (e) {}
}
@@ -240,7 +240,7 @@ export function useSubmitRageshake(): {
Object.keys(estimate.usageDetails).forEach((k) => {
body.append(
`storageManager_usage_${k}`,
String(estimate.usageDetails![k])
String(estimate.usageDetails![k]),
);
});
}
@@ -257,14 +257,14 @@ export function useSubmitRageshake(): {
body.append(
"file",
gzip(ElementCallOpenTelemetry.instance.rageshakeProcessor!.dump()),
"traces.json.gz"
"traces.json.gz",
);
}
if (opts.rageshakeRequestId) {
body.append(
"group_call_rageshake_request_id",
opts.rageshakeRequestId
opts.rageshakeRequestId,
);
}
@@ -279,7 +279,7 @@ export function useSubmitRageshake(): {
logger.error(error);
}
},
[client, sending]
[client, sending],
);
return {
@@ -292,7 +292,7 @@ export function useSubmitRageshake(): {
export function useRageshakeRequest(): (
roomId: string,
rageshakeRequestId: string
rageshakeRequestId: string,
) => void {
const { client } = useClient();
@@ -302,14 +302,14 @@ export function useRageshakeRequest(): (
request_id: rageshakeRequestId,
});
},
[client]
[client],
);
return sendRageshakeRequest;
}
export function useRageshakeRequestModal(
roomId: string
roomId: string,
): ComponentProps<typeof RageshakeRequestModal> {
const [open, setOpen] = useState(false);
const onDismiss = useCallback(() => setOpen(false), [setOpen]);

View File

@@ -38,13 +38,13 @@ export const useSetting = <T>(name: string, defaultValue: T): Setting<T> => {
const value = useMemo(
() => (item == null ? defaultValue : JSON.parse(item)),
[item, defaultValue]
[item, defaultValue],
);
const setValue = useCallback(
(value: T) => {
setItem(JSON.stringify(value));
},
[setItem]
[setItem],
);
return [value, setValue];
@@ -94,7 +94,7 @@ export const useOptInAnalytics = (): DisableableSetting<boolean | null> => {
export const useEnableE2EE = (): DisableableSetting<boolean | null> => {
const settingVal = useSetting<boolean | null>(
"enable-end-to-end-encryption",
true
true,
);
if (isE2EESupported()) return settingVal;

View File

@@ -29,7 +29,7 @@ interface TabContainerProps<T> extends TabListProps<T> {
}
export function TabContainer<T extends object>(
props: TabContainerProps<T>
props: TabContainerProps<T>,
): JSX.Element {
const state = useTabListState<T>(props);
const ref = useRef<HTMLUListElement>(null);

View File

@@ -39,7 +39,7 @@ export const Headline = forwardRef<HTMLHeadingElement, TypographyProps>(
overflowEllipsis,
...rest
},
ref
ref,
) => {
return createElement(
Component,
@@ -48,13 +48,13 @@ export const Headline = forwardRef<HTMLHeadingElement, TypographyProps>(
className: classNames(
styles[fontWeight ?? ""],
{ [styles.overflowEllipsis]: overflowEllipsis },
className
className,
),
ref,
},
children
children,
);
}
},
);
export const Title = forwardRef<HTMLHeadingElement, TypographyProps>(
@@ -67,7 +67,7 @@ export const Title = forwardRef<HTMLHeadingElement, TypographyProps>(
overflowEllipsis,
...rest
},
ref
ref,
) => {
return createElement(
Component,
@@ -76,13 +76,13 @@ export const Title = forwardRef<HTMLHeadingElement, TypographyProps>(
className: classNames(
styles[fontWeight ?? ""],
{ [styles.overflowEllipsis]: overflowEllipsis },
className
className,
),
ref,
},
children
children,
);
}
},
);
export const Subtitle = forwardRef<HTMLParagraphElement, TypographyProps>(
@@ -95,7 +95,7 @@ export const Subtitle = forwardRef<HTMLParagraphElement, TypographyProps>(
overflowEllipsis,
...rest
},
ref
ref,
) => {
return createElement(
Component,
@@ -104,13 +104,13 @@ export const Subtitle = forwardRef<HTMLParagraphElement, TypographyProps>(
className: classNames(
styles[fontWeight ?? ""],
{ [styles.overflowEllipsis]: overflowEllipsis },
className
className,
),
ref,
},
children
children,
);
}
},
);
export const Body = forwardRef<HTMLParagraphElement, TypographyProps>(
@@ -123,7 +123,7 @@ export const Body = forwardRef<HTMLParagraphElement, TypographyProps>(
overflowEllipsis,
...rest
},
ref
ref,
) => {
return createElement(
Component,
@@ -132,13 +132,13 @@ export const Body = forwardRef<HTMLParagraphElement, TypographyProps>(
className: classNames(
styles[fontWeight ?? ""],
{ [styles.overflowEllipsis]: overflowEllipsis },
className
className,
),
ref,
},
children
children,
);
}
},
);
export const Caption = forwardRef<HTMLParagraphElement, TypographyProps>(
@@ -151,7 +151,7 @@ export const Caption = forwardRef<HTMLParagraphElement, TypographyProps>(
overflowEllipsis,
...rest
},
ref
ref,
) => {
return createElement(
Component,
@@ -161,13 +161,13 @@ export const Caption = forwardRef<HTMLParagraphElement, TypographyProps>(
styles.caption,
styles[fontWeight ?? ""],
{ [styles.overflowEllipsis]: overflowEllipsis },
className
className,
),
ref,
},
children
children,
);
}
},
);
export const Micro = forwardRef<HTMLParagraphElement, TypographyProps>(
@@ -180,7 +180,7 @@ export const Micro = forwardRef<HTMLParagraphElement, TypographyProps>(
overflowEllipsis,
...rest
},
ref
ref,
) => {
return createElement(
Component,
@@ -190,13 +190,13 @@ export const Micro = forwardRef<HTMLParagraphElement, TypographyProps>(
styles.micro,
styles[fontWeight ?? ""],
{ [styles.overflowEllipsis]: overflowEllipsis },
className
className,
),
ref,
},
children
children,
);
}
},
);
interface LinkProps extends TypographyProps {
@@ -217,7 +217,7 @@ export const Link = forwardRef<HTMLAnchorElement, LinkProps>(
overflowEllipsis,
...rest
},
ref
ref,
) => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
@@ -246,11 +246,11 @@ export const Link = forwardRef<HTMLAnchorElement, LinkProps>(
styles[color],
styles[fontWeight ?? ""],
{ [styles.overflowEllipsis]: overflowEllipsis },
className
className,
),
ref: ref,
},
children
children,
);
}
},
);

View File

@@ -34,7 +34,7 @@ export function useCallViewKeyboardShortcuts(
focusElement: RefObject<HTMLElement | null>,
toggleMicrophoneMuted: () => void,
toggleLocalVideoMuted: () => void,
setMicrophoneMuted: (muted: boolean) => void
setMicrophoneMuted: (muted: boolean) => void,
): void {
const spacebarHeld = useRef(false);
@@ -63,8 +63,8 @@ export function useCallViewKeyboardShortcuts(
toggleLocalVideoMuted,
toggleMicrophoneMuted,
setMicrophoneMuted,
]
)
],
),
);
useEventTarget(
@@ -80,8 +80,8 @@ export function useCallViewKeyboardShortcuts(
setMicrophoneMuted(true);
}
},
[focusElement, setMicrophoneMuted]
)
[focusElement, setMicrophoneMuted],
),
);
useEventTarget(
@@ -92,6 +92,6 @@ export function useCallViewKeyboardShortcuts(
spacebarHeld.current = false;
setMicrophoneMuted(true);
}
}, [setMicrophoneMuted, spacebarHeld])
}, [setMicrophoneMuted, spacebarHeld]),
);
}

View File

@@ -28,7 +28,7 @@ export function useEventTarget<T extends Event>(
target: EventTarget | null | undefined,
eventType: string,
listener: (event: T) => void,
options?: AddEventListenerOptions
options?: AddEventListenerOptions,
): void {
useEffect(() => {
if (target) {
@@ -37,7 +37,7 @@ export function useEventTarget<T extends Event>(
target.removeEventListener(
eventType,
listener as EventListener,
options
options,
);
}
}, [target, eventType, listener, options]);
@@ -47,11 +47,11 @@ export function useEventTarget<T extends Event>(
export function useTypedEventEmitter<
Events extends string,
Arguments extends ListenerMap<Events>,
T extends Events
T extends Events,
>(
emitter: TypedEventEmitter<Events, Arguments>,
eventType: T,
listener: Listener<Events, Arguments, T>
listener: Listener<Events, Arguments, T>,
): void {
useEffect(() => {
emitter.on(eventType, listener);
@@ -64,11 +64,11 @@ export function useTypedEventEmitter<
// 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
T extends EventMap,
>(
emitter: EventEmitter<T>,
eventType: EventType,
listener: T[EventType]
listener: T[EventType],
): void {
useEffect(() => {
emitter.on(eventType, listener);

View File

@@ -24,10 +24,10 @@ export const localStorageBus = new EventEmitter();
// Like useState, but reads from and persists the value to localStorage
export const useLocalStorage = (
key: string
key: string,
): [LocalStorageItem, (value: string) => void] => {
const [value, setValue] = useState<LocalStorageItem>(() =>
localStorage.getItem(key)
localStorage.getItem(key),
);
useEffect(() => {
@@ -45,7 +45,7 @@ export const useLocalStorage = (
localStorage.setItem(key, newValue);
localStorageBus.emit(key, newValue);
},
[key, setValue]
[key, setValue],
),
];
};

View File

@@ -22,7 +22,7 @@ import {
import { useCallback, useEffect, useState } from "react";
export function useMatrixRTCSessionJoinState(
rtcSession: MatrixRTCSession
rtcSession: MatrixRTCSession,
): boolean {
const [isJoined, setJoined] = useState(rtcSession.isJoined());
@@ -30,7 +30,7 @@ export function useMatrixRTCSessionJoinState(
logger.info(
`Session in room ${rtcSession.room.roomId} changed to ${
rtcSession.isJoined() ? "joined" : "left"
}`
}`,
);
setJoined(rtcSession.isJoined());
}, [rtcSession]);
@@ -41,7 +41,7 @@ export function useMatrixRTCSessionJoinState(
return () => {
rtcSession.off(
MatrixRTCSessionEvent.JoinStateChanged,
onJoinStateChanged
onJoinStateChanged,
);
};
}, [rtcSession, onJoinStateChanged]);

View File

@@ -23,13 +23,13 @@ import {
import { useCallback, useEffect, useState } from "react";
export function useMatrixRTCSessionMemberships(
rtcSession: MatrixRTCSession
rtcSession: MatrixRTCSession,
): CallMembership[] {
const [memberships, setMemberships] = useState(rtcSession.memberships);
const onMembershipsChanged = useCallback(() => {
logger.info(
`Memberships changed for call in room ${rtcSession.room.roomId} (${rtcSession.memberships.length} members)`
`Memberships changed for call in room ${rtcSession.room.roomId} (${rtcSession.memberships.length} members)`,
);
setMemberships(rtcSession.memberships);
}, [rtcSession]);
@@ -37,13 +37,13 @@ export function useMatrixRTCSessionMemberships(
useEffect(() => {
rtcSession.on(
MatrixRTCSessionEvent.MembershipsChanged,
onMembershipsChanged
onMembershipsChanged,
);
return () => {
rtcSession.off(
MatrixRTCSessionEvent.MembershipsChanged,
onMembershipsChanged
onMembershipsChanged,
);
};
}, [rtcSession, onMembershipsChanged]);

View File

@@ -28,7 +28,7 @@ export function useMediaQuery(query: string): boolean {
useEventTarget(
mediaQuery,
"change",
useCallback(() => setNumChanges((n) => n + 1), [setNumChanges])
useCallback(() => setNumChanges((n) => n + 1), [setNumChanges]),
);
// We want any change to the update counter to trigger an update here

View File

@@ -35,5 +35,5 @@ export const useMergedRefs = <T>(
// Since this isn't an array literal, we can't use the static dependency
// checker, but that's okay
// eslint-disable-next-line react-hooks/exhaustive-deps
refs
refs,
);

View File

@@ -30,7 +30,7 @@ import {
*/
export const useReactiveState = <T>(
updateFn: (prevState?: T) => T,
deps: DependencyList
deps: DependencyList,
): [T, Dispatch<SetStateAction<T>>] => {
const state = useRef<T>();
if (state.current === undefined) state.current = updateFn();
@@ -61,7 +61,7 @@ export const useReactiveState = <T>(
}
setNumUpdates((n) => n + 1); // Force an update
},
[setNumUpdates]
[setNumUpdates],
),
];
};

View File

@@ -78,7 +78,7 @@ export interface SparseGrid {
export function getPaths(
g: SparseGrid,
dest: number,
avoid: (cell: number) => boolean = (): boolean => false
avoid: (cell: number) => boolean = (): boolean => false,
): (number | null)[] {
const destRow = row(dest, g);
const destColumn = column(dest, g);
@@ -145,7 +145,7 @@ function inArea(
index: number,
start: number,
end: number,
g: SparseGrid
g: SparseGrid,
): boolean {
const indexColumn = column(index, g);
const indexRow = row(index, g);
@@ -160,7 +160,7 @@ function inArea(
function* cellsInArea(
start: number,
end: number,
g: SparseGrid
g: SparseGrid,
): Generator<number, void, unknown> {
const startColumn = column(start, g);
const endColumn = column(end, g);
@@ -179,7 +179,7 @@ export function forEachCellInArea<G extends Grid | SparseGrid>(
start: number,
end: number,
g: G,
fn: (c: G["cells"][0], i: number) => void
fn: (c: G["cells"][0], i: number) => void,
): void {
for (const i of cellsInArea(start, end, g)) fn(g.cells[i], i);
}
@@ -188,7 +188,7 @@ function allCellsInArea<G extends Grid | SparseGrid>(
start: number,
end: number,
g: G,
fn: (c: G["cells"][0], i: number) => boolean
fn: (c: G["cells"][0], i: number) => boolean,
): boolean {
for (const i of cellsInArea(start, end, g)) {
if (!fn(g.cells[i], i)) return false;
@@ -204,7 +204,7 @@ function countCellsInArea<G extends Grid | SparseGrid>(
start: number,
end: number,
g: G,
predicate: (c: G["cells"][0], i: number) => boolean
predicate: (c: G["cells"][0], i: number) => boolean,
): number {
let count = 0;
for (const i of cellsInArea(start, end, g)) {
@@ -217,7 +217,7 @@ const areaEnd = (
start: number,
columns: number,
rows: number,
g: SparseGrid
g: SparseGrid,
): number => start + columns - 1 + g.columns * (rows - 1);
const cloneGrid = <G extends Grid | SparseGrid>(g: G): G => ({
@@ -231,7 +231,7 @@ const cloneGrid = <G extends Grid | SparseGrid>(g: G): G => ({
*/
function getNextGap(
g: SparseGrid,
ignoreGap: (cell: number) => boolean
ignoreGap: (cell: number) => boolean,
): number | null {
const last1By1Index = findLast1By1Index(g);
if (last1By1Index === null) return null;
@@ -278,13 +278,13 @@ function moveTileUnchecked(g: SparseGrid, from: number, to: number): void {
to,
toEnd,
g,
(_c, i) => (g.cells[i] = movingCells.shift())
(_c, i) => (g.cells[i] = movingCells.shift()),
);
forEachCellInArea(
from,
fromEnd,
g,
(_c, i) => (g.cells[i] ??= displacedTiles.shift())
(_c, i) => (g.cells[i] ??= displacedTiles.shift()),
);
}
@@ -294,7 +294,7 @@ function moveTileUnchecked(g: SparseGrid, from: number, to: number): void {
export function moveTile<G extends Grid | SparseGrid>(
g: G,
from: number,
to: number
to: number,
): G {
const tile = g.cells[from]!;
@@ -333,7 +333,7 @@ function pushTileUp(
g: SparseGrid,
from: number,
rows: number,
avoid: (cell: number) => boolean = (): boolean => false
avoid: (cell: number) => boolean = (): boolean => false,
): number {
const tile = g.cells[from]!;
@@ -347,7 +347,7 @@ function pushTileUp(
to,
Math.min(from - g.columns + tile.columns - 1, toEnd),
g,
(c, i) => (c === undefined || is1By1(c)) && !avoid(i)
(c, i) => (c === undefined || is1By1(c)) && !avoid(i),
);
if (cellsAboveAreDisplacable) {
@@ -376,7 +376,7 @@ function canVacateArea(g: SparseGrid, start: number, end: number): boolean {
start,
end - newFullRows * g.columns,
g,
(c) => c === undefined || is1By1(c)
(c) => c === undefined || is1By1(c),
);
}
@@ -391,7 +391,7 @@ function vacateArea(g: SparseGrid, start: number, end: number): SparseGrid {
start,
end,
g,
(c, i) => c !== undefined || i >= g.cells.length
(c, i) => c !== undefined || i >= g.cells.length,
);
const newFullRows = Math.floor(newCellCount / g.columns);
const endRow = row(end, g);
@@ -452,7 +452,7 @@ function vacateArea(g: SparseGrid, start: number, end: number): SparseGrid {
const inputStructure = fillGaps(
outputStructure,
false,
(i) => inArea(i, start, end, g) && g.cells[i] === undefined
(i) => inArea(i, start, end, g) && g.cells[i] === undefined,
);
// We exploit the fact that g and inputStructure have the same structure to
@@ -464,7 +464,7 @@ function vacateArea(g: SparseGrid, start: number, end: number): SparseGrid {
return {
columns: g.columns,
cells: outputStructure.cells.map((placeholder) =>
structureMapping.get(placeholder)
structureMapping.get(placeholder),
),
};
}
@@ -475,21 +475,21 @@ function vacateArea(g: SparseGrid, start: number, end: number): SparseGrid {
export function fillGaps(
g: SparseGrid,
packLargeTiles?: true,
ignoreGap?: () => false
ignoreGap?: () => false,
): Grid;
export function fillGaps(
g: SparseGrid,
packLargeTiles?: boolean,
ignoreGap?: (cell: number) => boolean
ignoreGap?: (cell: number) => boolean,
): SparseGrid;
export function fillGaps(
g: SparseGrid,
packLargeTiles = true,
ignoreGap: (cell: number) => boolean = (): boolean => false
ignoreGap: (cell: number) => boolean = (): boolean => false,
): SparseGrid {
const lastGap = findLastIndex(
g.cells,
(c, i) => c === undefined && !ignoreGap(i)
(c, i) => c === undefined && !ignoreGap(i),
);
if (lastGap === null) return g; // There are no gaps to fill
const lastGapRow = row(lastGap, g);
@@ -500,10 +500,10 @@ export function fillGaps(
// allowed to pack the large tiles into the rest of the grid as necessary)
let idealLength = count(
result.cells,
(c, i) => c !== undefined || ignoreGap(i)
(c, i) => c !== undefined || ignoreGap(i),
);
const fullRowsRemoved = Math.floor(
(g.cells.length - idealLength) / g.columns
(g.cells.length - idealLength) / g.columns,
);
// Step 1: Push all large tiles below the last gap upwards, so that they move
@@ -620,7 +620,7 @@ function createRows(g: SparseGrid, count: number, atRow: number): SparseGrid {
g,
(c, i) => {
result.cells[i + offset] = c;
}
},
);
}
});
@@ -633,7 +633,7 @@ function createRows(g: SparseGrid, count: number, atRow: number): SparseGrid {
*/
export function addItems(
items: TileDescriptor<unknown>[],
g: SparseGrid
g: SparseGrid,
): SparseGrid {
let result: SparseGrid = cloneGrid(g);
@@ -655,7 +655,7 @@ export function addItems(
// This item wants to be placed near another; let's put it on a row
// directly below the related tile
const placeNear = result.cells.findIndex(
(c) => c?.item.id === item.placeNear
(c) => c?.item.id === item.placeNear,
);
if (placeNear === -1) {
// Can't find the related tile, so let's give up and place it at the end
@@ -666,7 +666,7 @@ export function addItems(
placeNear,
placeNearCell.columns,
placeNearCell.rows,
result
result,
);
result = createRows(result, 1, row(placeNearEnd, result) + 1);
@@ -699,7 +699,7 @@ const extraLargeTileDimensions = (g: SparseGrid): [number, number] =>
export function cycleTileSize<G extends Grid | SparseGrid>(
g: G,
tile: TileDescriptor<unknown>
tile: TileDescriptor<unknown>,
): G {
const from = g.cells.findIndex((c) => c?.item === tile);
if (from === -1) return g; // Tile removed, no change
@@ -727,7 +727,7 @@ function findNearestCell<G extends Grid | SparseGrid>(
g: G,
nearestTo: number,
shouldScan: (index: number) => boolean,
predicate: (cell: G["cells"][0], index: number) => boolean
predicate: (cell: G["cells"][0], index: number) => boolean,
): number | null {
const scanLocations = new Set([nearestTo]);
@@ -758,7 +758,7 @@ export function setTileSize<G extends Grid | SparseGrid>(
g: G,
from: number,
toWidth: number,
toHeight: number
toHeight: number,
): G {
const fromCell = g.cells[from]!;
const fromWidth = fromCell.columns;
@@ -771,12 +771,12 @@ export function setTileSize<G extends Grid | SparseGrid>(
0,
Math.min(
g.columns - toWidth,
column(from, g) + Math.trunc((fromWidth - toWidth) / 2)
)
column(from, g) + Math.trunc((fromWidth - toWidth) / 2),
),
);
const toRow = Math.max(
0,
row(from, g) + Math.trunc((fromHeight - toHeight) / 2)
row(from, g) + Math.trunc((fromHeight - toHeight) / 2),
);
const targetDest = toColumn + toRow * g.columns;
@@ -788,7 +788,7 @@ export function setTileSize<G extends Grid | SparseGrid>(
const placeTile = (
to: number,
toEnd: number,
grid: Grid | SparseGrid
grid: Grid | SparseGrid,
): void => {
forEachCellInArea(to, toEnd, grid, (_c, i) => {
grid.cells[i] = {
@@ -824,7 +824,7 @@ export function setTileSize<G extends Grid | SparseGrid>(
(_c, i) => {
const end = areaEnd(i, toWidth, toHeight, g);
return end < newGridSize && canVacateArea(gridWithoutTile, i, end);
}
},
);
if (to !== null) {
@@ -848,7 +848,7 @@ export function setTileSize<G extends Grid | SparseGrid>(
(_c, i) => {
const end = areaEnd(i, toWidth, toHeight, g);
return end < newGridSize && canVacateArea(packedGridWithoutTile, i, end);
}
},
);
if (to === null) return g; // There's no space anywhere; give up
@@ -949,7 +949,7 @@ function updateTiles(g: Grid, tiles: TileDescriptor<unknown>[]): Grid {
// Step 2: Add new tiles
const existingItemIds = new Set(
grid1.cells.filter((c) => c !== undefined).map((c) => c!.item.id)
grid1.cells.filter((c) => c !== undefined).map((c) => c!.item.id),
);
const newItems = tiles.filter((i) => !existingItemIds.has(i.id));
const grid2 = addItems(newItems, grid1);
@@ -967,7 +967,7 @@ function updateBounds(g: Grid, bounds: RectReadOnly): Grid {
const Slots: FC<{ s: Grid }> = memo(({ s: g }) => {
const areas = new Array<(number | null)[]>(
Math.ceil(g.cells.length / g.columns)
Math.ceil(g.cells.length / g.columns),
);
for (let i = 0; i < areas.length; i++)
areas[i] = new Array<number | null>(g.columns).fill(null);
@@ -981,7 +981,7 @@ const Slots: FC<{ s: Grid }> = memo(({ s: g }) => {
i,
slotEnd,
g,
(_c, j) => (areas[row(j, g)][column(j, g)] = slotCount)
(_c, j) => (areas[row(j, g)][column(j, g)] = slotCount),
);
slotCount++;
}
@@ -993,7 +993,7 @@ const Slots: FC<{ s: Grid }> = memo(({ s: g }) => {
(row) =>
`'${row
.map((slotId) => (slotId === null ? "." : `s${slotId}`))
.join(" ")}'`
.join(" ")}'`,
)
.join(" "),
gridTemplateColumns: `repeat(${g.columns}, 1fr)`,
@@ -1019,7 +1019,7 @@ function positionOnTileToCell(
g: SparseGrid,
tileOriginIndex: number,
xPositionOnTile: number,
yPositionOnTile: number
yPositionOnTile: number,
): number {
const tileOrigin = g.cells[tileOriginIndex]!;
const columnOnTile = Math.floor(xPositionOnTile * tileOrigin.columns);
@@ -1034,7 +1034,7 @@ function dragTile(
xPositionOnFrom: number,
yPositionOnFrom: number,
xPositionOnTo: number,
yPositionOnTo: number
yPositionOnTo: number,
): Grid {
const fromOrigin = g.cells.findIndex((c) => c.item === from);
const toOrigin = g.cells.findIndex((c) => c.item === to);
@@ -1042,13 +1042,13 @@ function dragTile(
g,
fromOrigin,
xPositionOnFrom,
yPositionOnFrom
yPositionOnFrom,
);
const toCell = positionOnTileToCell(
g,
toOrigin,
xPositionOnTo,
yPositionOnTo
yPositionOnTo,
);
return moveTile(g, fromOrigin, fromOrigin + toCell - fromCell);

View File

@@ -61,7 +61,7 @@ export interface Layout<State> {
xPositionOnFrom: number,
yPositionOnFrom: number,
xPositionOnTo: number,
yPositionOnTo: number
yPositionOnTo: number,
) => State;
/**
* Toggles the focus of the given tile (if this layout has the concept of
@@ -109,7 +109,7 @@ interface UseLayout<State, T> {
xPositionOnFrom: number,
yPositionOnFrom: number,
xPositionOnTo: number,
yPositionOnTo: number
yPositionOnTo: number,
) => void;
toggleFocus: ((tile: TileDescriptor<T>) => void) | undefined;
slots: ReactNode;
@@ -123,7 +123,7 @@ export function useLayout<State, T>(
layout: Layout<State>,
items: TileDescriptor<T>[],
bounds: RectReadOnly,
layoutStates: LayoutStatesMap
layoutStates: LayoutStatesMap,
): UseLayout<State, T> {
const prevLayout = useRef<Layout<unknown>>();
const prevState = layoutStates.get(layout);
@@ -159,7 +159,7 @@ export function useLayout<State, T>(
generation: generation.current,
canDragTile: useCallback(
(tile: TileDescriptor<T>) => layout.canDragTile(state, tile),
[layout, state]
[layout, state],
),
dragTile: useCallback(
(
@@ -168,7 +168,7 @@ export function useLayout<State, T>(
xPositionOnFrom: number,
yPositionOnFrom: number,
xPositionOnTo: number,
yPositionOnTo: number
yPositionOnTo: number,
) =>
setState((s) =>
layout.dragTile(
@@ -178,17 +178,17 @@ export function useLayout<State, T>(
xPositionOnFrom,
yPositionOnFrom,
xPositionOnTo,
yPositionOnTo
)
yPositionOnTo,
),
),
[layout, setState]
[layout, setState],
),
toggleFocus: useMemo(
() =>
layout.toggleFocus &&
((tile: TileDescriptor<T>): void =>
setState((s) => layout.toggleFocus!(s, tile))),
[layout, setState]
[layout, setState],
),
slots: <layout.Slots s={state} />,
};

View File

@@ -98,13 +98,13 @@ export function NewVideoGrid<T>({
useEffect(() => {
if (slotsRoot !== null) {
setRenderedGeneration(
parseInt(slotsRoot.getAttribute("data-generation")!)
parseInt(slotsRoot.getAttribute("data-generation")!),
);
const observer = new MutationObserver((mutations) => {
if (mutations.some((m) => m.type === "attributes")) {
setRenderedGeneration(
parseInt(slotsRoot.getAttribute("data-generation")!)
parseInt(slotsRoot.getAttribute("data-generation")!),
);
}
});
@@ -158,13 +158,13 @@ export function NewVideoGrid<T>({
if (renderedGeneration !== generation) return prevTiles ?? [];
const tileRects = new Map(
zip(orderedItems, slotRects) as [TileDescriptor<T>, Rect][]
zip(orderedItems, slotRects) as [TileDescriptor<T>, Rect][],
);
// In order to not break drag gestures, it's critical that we render tiles
// in a stable order (that of 'items')
return items.map((item) => ({ ...tileRects.get(item)!, item }));
},
[slotRects, grid, renderedGeneration]
[slotRects, grid, renderedGeneration],
);
// Drag state is stored in a ref rather than component state, because we use
@@ -200,7 +200,7 @@ export function NewVideoGrid<T>({
},
leave: { opacity: 0, scale: 0, immediate: disableAnimations },
config: { mass: 0.7, tension: 252, friction: 25 },
})
}),
// react-spring's types are bugged and can't infer the spring type
) as unknown as [TransitionFn<Tile<T>, TileSpring>, SpringRef<TileSpring>];
@@ -242,7 +242,7 @@ export function NewVideoGrid<T>({
disableAnimations ||
((key): boolean =>
key === "zIndex" || key === "x" || key === "y"),
}
},
);
const overTile = tiles.find(
@@ -250,7 +250,7 @@ export function NewVideoGrid<T>({
cursorX >= t.x &&
cursorX < t.x + t.width &&
cursorY >= t.y &&
cursorY < t.y + t.height
cursorY < t.y + t.height,
);
if (overTile !== undefined)
@@ -260,7 +260,7 @@ export function NewVideoGrid<T>({
(cursorX - tileX) / tile.width,
(cursorY - tileY) / tile.height,
(cursorX - overTile.x) / overTile.width,
(cursorY - overTile.y) / overTile.height
(cursorY - overTile.y) / overTile.height,
);
};
@@ -287,7 +287,7 @@ export function NewVideoGrid<T>({
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
last,
}: Parameters<Handler<"drag", EventTypes["drag"]>>[0]
}: Parameters<Handler<"drag", EventTypes["drag"]>>[0],
): void => {
if (tap) {
const now = Date.now();
@@ -303,7 +303,7 @@ export function NewVideoGrid<T>({
}
} else {
const tileController = springRef.current.find(
(c) => (c.item as Tile<T>).item.id === tileId
(c) => (c.item as Tile<T>).item.id === tileId,
)!;
if (canDragTile((tileController.item as Tile<T>).item)) {
@@ -347,7 +347,7 @@ export function NewVideoGrid<T>({
animateDraggedTile(false);
}
},
{ target: gridRef2 }
{ target: gridRef2 },
);
// Render nothing if the grid has yet to be generated

View File

@@ -25,7 +25,7 @@ interface Props<T> {
onDragRef: RefObject<
(
tileId: string,
state: Parameters<Handler<"drag", EventTypes["drag"]>>[0]
state: Parameters<Handler<"drag", EventTypes["drag"]>>[0],
) => void
>;
targetWidth: number;
@@ -87,7 +87,7 @@ export const TileWrapper = memo(
height,
boxShadow: to(
[shadow, shadowSpread],
(s, ss) => `rgba(0, 0, 0, 0.5) 0px ${s}px ${2 * s}px ${ss}px`
(s, ss) => `rgba(0, 0, 0, 0.5) 0px ${s}px ${2 * s}px ${ss}px`,
),
},
targetWidth,
@@ -96,7 +96,7 @@ export const TileWrapper = memo(
})}
</>
);
}
},
// We pretend this component is a simple function rather than a
// NamedExoticComponent, because that's the only way we can fit in a type
// parameter

View File

@@ -151,7 +151,7 @@ function getTilePositions(
gridHeight: number,
pipXRatio: number,
pipYRatio: number,
layout: Layout
layout: Layout,
): TilePosition[] {
if (layout === "grid") {
if (tileCount === 2 && focusedTileCount === 0) {
@@ -159,7 +159,7 @@ function getTilePositions(
gridWidth,
gridHeight,
pipXRatio,
pipYRatio
pipYRatio,
);
}
@@ -167,7 +167,7 @@ function getTilePositions(
tileCount,
focusedTileCount,
gridWidth,
gridHeight
gridHeight,
);
} else {
return getSpotlightLayoutTilePositions(tileCount, gridWidth, gridHeight);
@@ -178,13 +178,13 @@ function getOneOnOneLayoutTilePositions(
gridWidth: number,
gridHeight: number,
pipXRatio: number,
pipYRatio: number
pipYRatio: number,
): TilePosition[] {
const [remotePosition] = getFreedomLayoutTilePositions(
1,
0,
gridWidth,
gridHeight
gridHeight,
);
const gridAspectRatio = gridWidth / gridHeight;
@@ -196,7 +196,7 @@ function getOneOnOneLayoutTilePositions(
const pipScaleFactor = Math.min(
1,
remotePosition.width / 3 / maxPipWidth,
remotePosition.height / 3 / maxPipHeight
remotePosition.height / 3 / maxPipHeight,
);
const pipWidth = maxPipWidth * pipScaleFactor;
const pipHeight = maxPipHeight * pipScaleFactor;
@@ -223,7 +223,7 @@ function getOneOnOneLayoutTilePositions(
function getSpotlightLayoutTilePositions(
tileCount: number,
gridWidth: number,
gridHeight: number
gridHeight: number,
): TilePosition[] {
const tilePositions: TilePosition[] = [];
@@ -293,7 +293,7 @@ function getFreedomLayoutTilePositions(
tileCount: number,
focusedTileCount: number,
gridWidth: number,
gridHeight: number
gridHeight: number,
): TilePosition[] {
if (tileCount === 0) {
return [];
@@ -307,7 +307,7 @@ function getFreedomLayoutTilePositions(
tileCount,
focusedTileCount,
gridWidth,
gridHeight
gridHeight,
);
let itemGridWidth;
@@ -335,7 +335,7 @@ function getFreedomLayoutTilePositions(
itemRowCount,
itemTileAspectRatio,
itemGridWidth,
itemGridHeight
itemGridHeight,
);
const itemGridBounds = getSubGridBoundingBox(itemGridPositions);
@@ -367,7 +367,7 @@ function getFreedomLayoutTilePositions(
focusedRowCount,
focusedTileAspectRatio,
focusedGridWidth,
focusedGridHeight
focusedGridHeight,
);
const tilePositions = [...focusedGridPositions, ...itemGridPositions];
@@ -380,7 +380,7 @@ function getFreedomLayoutTilePositions(
gridWidth,
gridHeight - focusedGridHeight,
0,
focusedGridHeight
focusedGridHeight,
);
} else {
centerTiles(
@@ -388,7 +388,7 @@ function getFreedomLayoutTilePositions(
gridWidth - focusedGridWidth,
gridHeight,
focusedGridWidth,
0
0,
);
}
@@ -454,7 +454,7 @@ function getGridLayout(
tileCount: number,
focusedTileCount: number,
gridWidth: number,
gridHeight: number
gridHeight: number,
): { itemGridRatio: number; layoutDirection: LayoutDirection } {
let layoutDirection: LayoutDirection = "horizontal";
let itemGridRatio = 1;
@@ -479,7 +479,7 @@ function centerTiles(
gridWidth: number,
gridHeight: number,
offsetLeft: number,
offsetTop: number
offsetTop: number,
): TilePosition[] {
const bounds = getSubGridBoundingBox(positions);
@@ -494,7 +494,7 @@ function centerTiles(
function applyTileOffsets(
positions: TilePosition[],
leftOffset: number,
topOffset: number
topOffset: number,
): TilePosition[] {
for (const position of positions) {
position.x += leftOffset;
@@ -507,7 +507,7 @@ function applyTileOffsets(
function getSubGridLayout(
tileCount: number,
gridWidth: number,
gridHeight: number
gridHeight: number,
): { columnCount: number; rowCount: number; tileAspectRatio: number } {
const gridAspectRatio = gridWidth / gridHeight;
@@ -624,7 +624,7 @@ function getSubGridPositions(
rowCount: number,
tileAspectRatio: number,
gridWidth: number,
gridHeight: number
gridHeight: number,
): TilePosition[] {
if (tileCount === 0) {
return [];
@@ -633,7 +633,7 @@ function getSubGridPositions(
const newTilePositions: TilePosition[] = [];
const boxWidth = Math.round(
(gridWidth - GAP * (columnCount + 1)) / columnCount
(gridWidth - GAP * (columnCount + 1)) / columnCount,
);
const boxHeight = Math.round((gridHeight - GAP * (rowCount + 1)) / rowCount);
@@ -675,7 +675,7 @@ function getSubGridPositions(
const subgridWidth = tileWidth * columnCount + (GAP * columnCount - 1);
centeringPadding = Math.round(
(subgridWidth - (tileWidth * rowItemCount + (GAP * rowItemCount - 1))) /
2
2,
);
}
@@ -699,7 +699,7 @@ function displayedTileCount(
layout: Layout,
tileCount: number,
gridWidth: number,
gridHeight: number
gridHeight: number,
): number {
let displayedTile = -1;
if (layout === "grid") {
@@ -731,7 +731,7 @@ function displayedTileCount(
function reorderTiles<T>(
tiles: Tile<T>[],
layout: Layout,
displayedTile = -1
displayedTile = -1,
): void {
// We use a special layout for 1:1 to always put the local tile first.
// We only do this if there are two tiles (obviously) and exactly one
@@ -919,7 +919,7 @@ export function VideoGrid<T>({
for (const item of items) {
const existingTileIndex = newTiles.findIndex(
({ key }) => item.id === key
({ key }) => item.id === key,
);
const existingTile = newTiles[existingTileIndex];
@@ -956,7 +956,7 @@ export function VideoGrid<T>({
layout,
newTiles.length,
gridBounds.width,
gridBounds.height
gridBounds.height,
);
}
@@ -976,7 +976,7 @@ export function VideoGrid<T>({
const focusedTileCount = newTiles.reduce(
(count, tile) => count + (tile.focused ? 1 : 0),
0
0,
);
return {
@@ -989,7 +989,7 @@ export function VideoGrid<T>({
gridBounds.height,
pipXRatio,
pipYRatio,
layout
layout,
),
};
});
@@ -998,7 +998,7 @@ export function VideoGrid<T>({
const focusedTileCount = newTiles.reduce(
(count, tile) => count + (tile.focused ? 1 : 0),
0
0,
);
lastLayoutRef.current = layout;
@@ -1013,7 +1013,7 @@ export function VideoGrid<T>({
gridBounds.height,
pipXRatio,
pipYRatio,
layout
layout,
),
};
});
@@ -1066,7 +1066,7 @@ export function VideoGrid<T>({
} else {
const isMobile = isMobileBreakpoint(
gridBounds.width,
gridBounds.height
gridBounds.height,
);
const x =
@@ -1127,7 +1127,7 @@ export function VideoGrid<T>({
}
};
},
[tilePositions, disableAnimations, scrollPosition, layout, gridBounds]
[tilePositions, disableAnimations, scrollPosition, layout, gridBounds],
);
const [springs, api] = useSprings(tiles.length, animate(tiles), [
@@ -1179,12 +1179,12 @@ export function VideoGrid<T>({
gridBounds.height,
pipXRatio,
pipYRatio,
layout
layout,
),
};
});
},
[tiles, layout, gridBounds.width, gridBounds.height, pipXRatio, pipYRatio]
[tiles, layout, gridBounds.width, gridBounds.height, pipXRatio, pipYRatio],
);
// Callback for useDrag. We could call useDrag here, but the default
@@ -1213,7 +1213,7 @@ export function VideoGrid<T>({
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
event,
}: Parameters<Handler<"drag", EventTypes["drag"]>>[0]
}: Parameters<Handler<"drag", EventTypes["drag"]>>[0],
): void => {
event.preventDefault();
@@ -1243,7 +1243,7 @@ export function VideoGrid<T>({
const pipGap = getPipGap(
gridBounds.width / gridBounds.height,
gridBounds.width
gridBounds.width,
);
const pipMinX = remotePosition.x + pipGap;
const pipMinY = remotePosition.y + pipGap;
@@ -1270,7 +1270,7 @@ export function VideoGrid<T>({
const hoverTile = tiles.find(
(tile) =>
tile.key !== tileId &&
isInside(cursorPosition, tilePositions[tile.order])
isInside(cursorPosition, tilePositions[tile.order]),
);
if (hoverTile) {
@@ -1331,7 +1331,7 @@ export function VideoGrid<T>({
e:
| Omit<FullGestureState<"wheel">, "event">
| Omit<FullGestureState<"drag">, "event">,
isWheel: boolean
isWheel: boolean,
) => {
if (layout !== "spotlight") {
return;
@@ -1355,10 +1355,10 @@ export function VideoGrid<T>({
}
setScrollPosition((scrollPosition) =>
Math.min(Math.max(movement + scrollPosition, min), 0)
Math.min(Math.max(movement + scrollPosition, min), 0),
);
},
[layout, gridBounds, tilePositions]
[layout, gridBounds, tilePositions],
);
const bindGrid = useGesture(
@@ -1370,7 +1370,7 @@ export function VideoGrid<T>({
// @ts-ignore
onDrag: (e) => onGridGesture(e, false),
},
{}
{},
);
return (

Some files were not shown because too many files have changed in this diff Show More