mirror of
https://github.com/element-hq/element-web.git
synced 2025-12-11 01:40:42 +00:00
Compare commits
12 Commits
hs/update-
...
t3chguy/re
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
24d4ecf912 | ||
|
|
9ef3ea630c | ||
|
|
6946b90b11 | ||
|
|
c3f3c9364f | ||
|
|
72f155640d | ||
|
|
b597abf567 | ||
|
|
9443426edb | ||
|
|
6c2334c029 | ||
|
|
eb1a09a912 | ||
|
|
e730074e1b | ||
|
|
c8c5ef5e6e | ||
|
|
b61a2225b7 |
@@ -1,5 +1,5 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
plugins: ["matrix-org"],
|
plugins: ["matrix-org", "eslint-plugin-react-compiler"],
|
||||||
extends: ["plugin:matrix-org/babel", "plugin:matrix-org/react", "plugin:matrix-org/a11y"],
|
extends: ["plugin:matrix-org/babel", "plugin:matrix-org/react", "plugin:matrix-org/a11y"],
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
project: ["./tsconfig.json"],
|
project: ["./tsconfig.json"],
|
||||||
@@ -170,6 +170,8 @@ module.exports = {
|
|||||||
"jsx-a11y/role-supports-aria-props": "off",
|
"jsx-a11y/role-supports-aria-props": "off",
|
||||||
|
|
||||||
"matrix-org/require-copyright-header": "error",
|
"matrix-org/require-copyright-header": "error",
|
||||||
|
|
||||||
|
"react-compiler/react-compiler": "error",
|
||||||
},
|
},
|
||||||
overrides: [
|
overrides: [
|
||||||
{
|
{
|
||||||
@@ -262,6 +264,7 @@ module.exports = {
|
|||||||
|
|
||||||
// These are fine in tests
|
// These are fine in tests
|
||||||
"no-restricted-globals": "off",
|
"no-restricted-globals": "off",
|
||||||
|
"react-compiler/react-compiler": "off",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ class MockMap extends EventEmitter {
|
|||||||
setCenter = jest.fn();
|
setCenter = jest.fn();
|
||||||
setStyle = jest.fn();
|
setStyle = jest.fn();
|
||||||
fitBounds = jest.fn();
|
fitBounds = jest.fn();
|
||||||
|
remove = jest.fn();
|
||||||
}
|
}
|
||||||
const MockMapInstance = new MockMap();
|
const MockMapInstance = new MockMap();
|
||||||
|
|
||||||
|
|||||||
@@ -233,6 +233,7 @@
|
|||||||
"eslint-plugin-jsx-a11y": "^6.5.1",
|
"eslint-plugin-jsx-a11y": "^6.5.1",
|
||||||
"eslint-plugin-matrix-org": "^2.0.2",
|
"eslint-plugin-matrix-org": "^2.0.2",
|
||||||
"eslint-plugin-react": "^7.28.0",
|
"eslint-plugin-react": "^7.28.0",
|
||||||
|
"eslint-plugin-react-compiler": "^19.0.0-beta-df7b47d-20241124",
|
||||||
"eslint-plugin-react-hooks": "^5.0.0",
|
"eslint-plugin-react-hooks": "^5.0.0",
|
||||||
"eslint-plugin-unicorn": "^56.0.0",
|
"eslint-plugin-unicorn": "^56.0.0",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
|
|||||||
@@ -392,6 +392,7 @@ export const useRovingTabIndex = <T extends HTMLElement>(
|
|||||||
});
|
});
|
||||||
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
||||||
|
|
||||||
|
// eslint-disable-next-line react-compiler/react-compiler
|
||||||
const isActive = context.state.activeNode === nodeRef.current;
|
const isActive = context.state.activeNode === nodeRef.current;
|
||||||
return [onFocus, isActive, ref, nodeRef];
|
return [onFocus, isActive, ref, nodeRef];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -142,6 +142,7 @@ export const AutocompleteInput: React.FC<AutocompleteInputProps> = ({
|
|||||||
{isFocused && suggestions.length ? (
|
{isFocused && suggestions.length ? (
|
||||||
<div
|
<div
|
||||||
className="mx_AutocompleteInput_matches"
|
className="mx_AutocompleteInput_matches"
|
||||||
|
// eslint-disable-next-line react-compiler/react-compiler
|
||||||
style={{ top: editorContainerRef.current?.clientHeight }}
|
style={{ top: editorContainerRef.current?.clientHeight }}
|
||||||
data-testid="autocomplete-matches"
|
data-testid="autocomplete-matches"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -607,6 +607,7 @@ export const useContextMenu = <T extends any = HTMLElement>(inputRef?: RefObject
|
|||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// eslint-disable-next-line react-compiler/react-compiler
|
||||||
return [button.current ? isOpen : false, button, open, close, setIsOpen];
|
return [button.current ? isOpen : false, button, open, close, setIsOpen];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -286,9 +286,7 @@ class FilePanel extends React.Component<IProps, IState> {
|
|||||||
ref={this.card}
|
ref={this.card}
|
||||||
header={_t("right_panel|files_button")}
|
header={_t("right_panel|files_button")}
|
||||||
>
|
>
|
||||||
{this.card.current && (
|
<Measured sensor={this.card} onMeasurement={this.onMeasurement} />
|
||||||
<Measured sensor={this.card.current} onMeasurement={this.onMeasurement} />
|
|
||||||
)}
|
|
||||||
<SearchWarning isRoomEncrypted={isRoomEncrypted} kind={WarningKind.Files} />
|
<SearchWarning isRoomEncrypted={isRoomEncrypted} kind={WarningKind.Files} />
|
||||||
<TimelinePanel
|
<TimelinePanel
|
||||||
manageReadReceipts={false}
|
manageReadReceipts={false}
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ export default class NotificationPanel extends React.PureComponent<IProps, IStat
|
|||||||
onClose={this.props.onClose}
|
onClose={this.props.onClose}
|
||||||
withoutScrollContainer={true}
|
withoutScrollContainer={true}
|
||||||
>
|
>
|
||||||
{this.card.current && <Measured sensor={this.card.current} onMeasurement={this.onMeasurement} />}
|
<Measured sensor={this.card} onMeasurement={this.onMeasurement} />
|
||||||
{content}
|
{content}
|
||||||
</BaseCard>
|
</BaseCard>
|
||||||
</ScopedRoomContextProvider>
|
</ScopedRoomContextProvider>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
|||||||
Please see LICENSE files in the repository root for full details.
|
Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { forwardRef, useCallback, useContext, useEffect, useRef, useState } from "react";
|
import React, { forwardRef, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
|
||||||
import {
|
import {
|
||||||
ISearchResults,
|
ISearchResults,
|
||||||
IThreadBundledRelationship,
|
IThreadBundledRelationship,
|
||||||
@@ -58,7 +58,7 @@ export const RoomSearchView = forwardRef<ScrollPanel, Props>(
|
|||||||
const [results, setResults] = useState<ISearchResults | null>(null);
|
const [results, setResults] = useState<ISearchResults | null>(null);
|
||||||
const aborted = useRef(false);
|
const aborted = useRef(false);
|
||||||
// A map from room ID to permalink creator
|
// A map from room ID to permalink creator
|
||||||
const permalinkCreators = useRef(new Map<string, RoomPermalinkCreator>()).current;
|
const permalinkCreators = useMemo(() => new Map<string, RoomPermalinkCreator>(), []);
|
||||||
const innerRef = useRef<ScrollPanel | null>();
|
const innerRef = useRef<ScrollPanel | null>();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -273,6 +273,7 @@ function LocalRoomView(props: LocalRoomViewProps): ReactElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const onRetryClicked = (): void => {
|
const onRetryClicked = (): void => {
|
||||||
|
// eslint-disable-next-line react-compiler/react-compiler
|
||||||
room.state = LocalRoomState.NEW;
|
room.state = LocalRoomState.NEW;
|
||||||
defaultDispatcher.dispatch({
|
defaultDispatcher.dispatch({
|
||||||
action: "local_room_event",
|
action: "local_room_event",
|
||||||
@@ -2514,9 +2515,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
|
|||||||
mainSplitContentClassName = "mx_MainSplit_timeline";
|
mainSplitContentClassName = "mx_MainSplit_timeline";
|
||||||
mainSplitBody = (
|
mainSplitBody = (
|
||||||
<>
|
<>
|
||||||
{this.roomViewBody.current && (
|
<Measured sensor={this.roomViewBody} onMeasurement={this.onMeasurement} />
|
||||||
<Measured sensor={this.roomViewBody.current} onMeasurement={this.onMeasurement} />
|
|
||||||
)}
|
|
||||||
{auxPanel}
|
{auxPanel}
|
||||||
{pinnedMessageBanner}
|
{pinnedMessageBanner}
|
||||||
<main className={timelineClasses}>
|
<main className={timelineClasses}>
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ const ThreadPanel: React.FC<IProps> = ({ roomId, onClose, permalinkCreator }) =>
|
|||||||
ref={card}
|
ref={card}
|
||||||
closeButtonRef={closeButonRef}
|
closeButtonRef={closeButonRef}
|
||||||
>
|
>
|
||||||
{card.current && <Measured sensor={card.current} onMeasurement={setNarrow} />}
|
<Measured sensor={card} onMeasurement={setNarrow} />
|
||||||
{timelineSet ? (
|
{timelineSet ? (
|
||||||
<TimelinePanel
|
<TimelinePanel
|
||||||
key={filterOption + ":" + (timelineSet.getFilter()?.filterId ?? roomId)}
|
key={filterOption + ":" + (timelineSet.getFilter()?.filterId ?? roomId)}
|
||||||
|
|||||||
@@ -443,7 +443,7 @@ export default class ThreadView extends React.Component<IProps, IState> {
|
|||||||
PosthogTrackers.trackInteraction("WebThreadViewBackButton", ev);
|
PosthogTrackers.trackInteraction("WebThreadViewBackButton", ev);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{this.card.current && <Measured sensor={this.card.current} onMeasurement={this.onMeasurement} />}
|
<Measured sensor={this.card} onMeasurement={this.onMeasurement} />
|
||||||
<div className="mx_ThreadView_timelinePanelWrapper">{timeline}</div>
|
<div className="mx_ThreadView_timelinePanelWrapper">{timeline}</div>
|
||||||
|
|
||||||
{ContentMessages.sharedInstance().getCurrentUploads(threadRelation).length > 0 && (
|
{ContentMessages.sharedInstance().getCurrentUploads(threadRelation).length > 0 && (
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import React, { useEffect, useRef } from "react";
|
import React, { useMemo } from "react";
|
||||||
|
|
||||||
type FlexProps = {
|
type FlexProps = {
|
||||||
/**
|
/**
|
||||||
@@ -40,25 +40,6 @@ type FlexProps = {
|
|||||||
grow?: string | null;
|
grow?: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Set or remove a CSS property
|
|
||||||
* @param ref the reference
|
|
||||||
* @param name the CSS property name
|
|
||||||
* @param value the CSS property value
|
|
||||||
*/
|
|
||||||
function addOrRemoveProperty(
|
|
||||||
ref: React.MutableRefObject<HTMLElement | undefined>,
|
|
||||||
name: string,
|
|
||||||
value?: string | null,
|
|
||||||
): void {
|
|
||||||
const style = ref.current!.style;
|
|
||||||
if (value) {
|
|
||||||
style.setProperty(name, value);
|
|
||||||
} else {
|
|
||||||
style.removeProperty(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A flex child helper
|
* A flex child helper
|
||||||
*/
|
*/
|
||||||
@@ -71,12 +52,12 @@ export function Box({
|
|||||||
children,
|
children,
|
||||||
...props
|
...props
|
||||||
}: React.PropsWithChildren<FlexProps>): JSX.Element {
|
}: React.PropsWithChildren<FlexProps>): JSX.Element {
|
||||||
const ref = useRef<HTMLElement>();
|
const style = useMemo(() => {
|
||||||
|
const style: Record<string, any> = {};
|
||||||
useEffect(() => {
|
if (flex) style["--mx-box-flex"] = flex;
|
||||||
addOrRemoveProperty(ref, `--mx-box-flex`, flex);
|
if (shrink) style["--mx-box-shrink"] = shrink;
|
||||||
addOrRemoveProperty(ref, `--mx-box-shrink`, shrink);
|
if (grow) style["--mx-box-grow"] = grow;
|
||||||
addOrRemoveProperty(ref, `--mx-box-grow`, grow);
|
return style;
|
||||||
}, [flex, grow, shrink]);
|
}, [flex, grow, shrink]);
|
||||||
|
|
||||||
return React.createElement(
|
return React.createElement(
|
||||||
@@ -88,7 +69,7 @@ export function Box({
|
|||||||
"mx_Box--shrink": !!shrink,
|
"mx_Box--shrink": !!shrink,
|
||||||
"mx_Box--grow": !!grow,
|
"mx_Box--grow": !!grow,
|
||||||
}),
|
}),
|
||||||
ref,
|
style,
|
||||||
},
|
},
|
||||||
children,
|
children,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import React, { useEffect, useRef } from "react";
|
import React, { useMemo } from "react";
|
||||||
|
|
||||||
type FlexProps = {
|
type FlexProps = {
|
||||||
/**
|
/**
|
||||||
@@ -64,15 +64,16 @@ export function Flex({
|
|||||||
children,
|
children,
|
||||||
...props
|
...props
|
||||||
}: React.PropsWithChildren<FlexProps>): JSX.Element {
|
}: React.PropsWithChildren<FlexProps>): JSX.Element {
|
||||||
const ref = useRef<HTMLElement>();
|
const style = useMemo(
|
||||||
|
() => ({
|
||||||
|
"--mx-flex-display": display,
|
||||||
|
"--mx-flex-direction": direction,
|
||||||
|
"--mx-flex-align": align,
|
||||||
|
"--mx-flex-justify": justify,
|
||||||
|
"--mx-flex-gap": gap,
|
||||||
|
}),
|
||||||
|
[align, direction, display, gap, justify],
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
return React.createElement(as, { ...props, className: classNames("mx_Flex", className), style }, children);
|
||||||
ref.current!.style.setProperty(`--mx-flex-display`, display);
|
|
||||||
ref.current!.style.setProperty(`--mx-flex-direction`, direction);
|
|
||||||
ref.current!.style.setProperty(`--mx-flex-align`, align);
|
|
||||||
ref.current!.style.setProperty(`--mx-flex-justify`, justify);
|
|
||||||
ref.current!.style.setProperty(`--mx-flex-gap`, gap);
|
|
||||||
}, [align, direction, display, gap, justify]);
|
|
||||||
|
|
||||||
return React.createElement(as, { ...props, className: classNames("mx_Flex", className), ref }, children);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,11 +58,10 @@ const EffectsOverlay: FunctionComponent<IProps> = ({ roomWidth }) => {
|
|||||||
if (canvas) canvas.height = UIStore.instance.windowHeight;
|
if (canvas) canvas.height = UIStore.instance.windowHeight;
|
||||||
UIStore.instance.on(UI_EVENTS.Resize, resize);
|
UIStore.instance.on(UI_EVENTS.Resize, resize);
|
||||||
|
|
||||||
|
const currentEffects = effectsRef.current; // this is not a react node ref, warning can be safely ignored
|
||||||
return () => {
|
return () => {
|
||||||
dis.unregister(dispatcherRef);
|
dis.unregister(dispatcherRef);
|
||||||
UIStore.instance.off(UI_EVENTS.Resize, resize);
|
UIStore.instance.off(UI_EVENTS.Resize, resize);
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
const currentEffects = effectsRef.current; // this is not a react node ref, warning can be safely ignored
|
|
||||||
for (const effect in currentEffects) {
|
for (const effect in currentEffects) {
|
||||||
const effectModule: ICanvasEffect = currentEffects.get(effect)!;
|
const effectModule: ICanvasEffect = currentEffects.get(effect)!;
|
||||||
if (effectModule && effectModule.isRunning) {
|
if (effectModule && effectModule.isRunning) {
|
||||||
|
|||||||
@@ -6,12 +6,12 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
|||||||
Please see LICENSE files in the repository root for full details.
|
Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from "react";
|
import React, { RefObject } from "react";
|
||||||
|
|
||||||
import UIStore, { UI_EVENTS } from "../../../stores/UIStore";
|
import UIStore, { UI_EVENTS } from "../../../stores/UIStore";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
sensor: Element;
|
sensor: RefObject<Element>;
|
||||||
breakpoint: number;
|
breakpoint: number;
|
||||||
onMeasurement(narrow: boolean): void;
|
onMeasurement(narrow: boolean): void;
|
||||||
}
|
}
|
||||||
@@ -35,14 +35,14 @@ export default class Measured extends React.PureComponent<IProps> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public componentDidUpdate(prevProps: Readonly<IProps>): void {
|
public componentDidUpdate(prevProps: Readonly<IProps>): void {
|
||||||
const previous = prevProps.sensor;
|
const previous = prevProps.sensor.current;
|
||||||
const current = this.props.sensor;
|
const current = this.props.sensor.current;
|
||||||
if (previous === current) return;
|
if (previous === current) return;
|
||||||
if (previous) {
|
if (previous) {
|
||||||
UIStore.instance.stopTrackingElementDimensions(`Measured${this.instanceId}`);
|
UIStore.instance.stopTrackingElementDimensions(`Measured${this.instanceId}`);
|
||||||
}
|
}
|
||||||
if (current) {
|
if (current) {
|
||||||
UIStore.instance.trackElementDimensions(`Measured${this.instanceId}`, this.props.sensor);
|
UIStore.instance.trackElementDimensions(`Measured${this.instanceId}`, this.props.sensor.current);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ export default class TimelineCard extends React.Component<IProps, IState> {
|
|||||||
header={_t("right_panel|video_room_chat|title")}
|
header={_t("right_panel|video_room_chat|title")}
|
||||||
ref={this.card}
|
ref={this.card}
|
||||||
>
|
>
|
||||||
{this.card.current && <Measured sensor={this.card.current} onMeasurement={this.onMeasurement} />}
|
<Measured sensor={this.card} onMeasurement={this.onMeasurement} />
|
||||||
<div className="mx_TimelineCard_timeline">
|
<div className="mx_TimelineCard_timeline">
|
||||||
{jumpToBottom}
|
{jumpToBottom}
|
||||||
<TimelinePanel
|
<TimelinePanel
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ export function ReadReceiptGroup({
|
|||||||
readReceiptPosition = readReceiptMap[userId];
|
readReceiptPosition = readReceiptMap[userId];
|
||||||
if (!readReceiptPosition) {
|
if (!readReceiptPosition) {
|
||||||
readReceiptPosition = {};
|
readReceiptPosition = {};
|
||||||
|
// eslint-disable-next-line react-compiler/react-compiler
|
||||||
readReceiptMap[userId] = readReceiptPosition;
|
readReceiptMap[userId] = readReceiptPosition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
|||||||
Please see LICENSE files in the repository root for full details.
|
Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useCallback, useRef, useState } from "react";
|
import React, { useCallback, useEffect, useRef, useState } from "react";
|
||||||
import { EventType, KnownMembership, MatrixEvent, Room, RoomStateEvent, RoomMember } from "matrix-js-sdk/src/matrix";
|
import { EventType, KnownMembership, MatrixEvent, Room, RoomStateEvent, RoomMember } from "matrix-js-sdk/src/matrix";
|
||||||
import { CryptoApi, CryptoEvent, UserVerificationStatus } from "matrix-js-sdk/src/crypto-api";
|
import { CryptoApi, CryptoEvent, UserVerificationStatus } from "matrix-js-sdk/src/crypto-api";
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
@@ -213,9 +213,11 @@ export const UserIdentityWarning: React.FC<UserIdentityWarningProps> = ({ room }
|
|||||||
initialisedRef.current = InitialisationStatus.Completed;
|
initialisedRef.current = InitialisationStatus.Completed;
|
||||||
}, [crypto, room, addMembersWhoNeedApproval, updateCurrentPrompt]);
|
}, [crypto, room, addMembersWhoNeedApproval, updateCurrentPrompt]);
|
||||||
|
|
||||||
loadMembers().catch((e) => {
|
useEffect(() => {
|
||||||
logger.error("Error initialising UserIdentityWarning:", e);
|
loadMembers().catch((e) => {
|
||||||
});
|
logger.error("Error initialising UserIdentityWarning:", e);
|
||||||
|
});
|
||||||
|
}, [loadMembers]);
|
||||||
|
|
||||||
// When a user's verification status changes, we check if they need to be
|
// When a user's verification status changes, we check if they need to be
|
||||||
// added/removed from the set of members needing approval.
|
// added/removed from the set of members needing approval.
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
|||||||
Please see LICENSE files in the repository root for full details.
|
Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { ForwardedRef, forwardRef, MutableRefObject, useRef } from "react";
|
import React, { ForwardedRef, forwardRef, MutableRefObject, useMemo } from "react";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
|
|
||||||
import EditorStateTransfer from "../../../../utils/EditorStateTransfer";
|
import EditorStateTransfer from "../../../../utils/EditorStateTransfer";
|
||||||
@@ -44,7 +44,7 @@ export default function EditWysiwygComposer({
|
|||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: EditWysiwygComposerProps): JSX.Element {
|
}: EditWysiwygComposerProps): JSX.Element {
|
||||||
const defaultContextValue = useRef(getDefaultContextValue({ editorStateTransfer }));
|
const defaultContextValue = useMemo(() => getDefaultContextValue({ editorStateTransfer }), [editorStateTransfer]);
|
||||||
const initialContent = useInitialContent(editorStateTransfer);
|
const initialContent = useInitialContent(editorStateTransfer);
|
||||||
const isReady = !editorStateTransfer || initialContent !== undefined;
|
const isReady = !editorStateTransfer || initialContent !== undefined;
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ export default function EditWysiwygComposer({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ComposerContext.Provider value={defaultContextValue.current}>
|
<ComposerContext.Provider value={defaultContextValue}>
|
||||||
<WysiwygComposer
|
<WysiwygComposer
|
||||||
className={classNames("mx_EditWysiwygComposer", className)}
|
className={classNames("mx_EditWysiwygComposer", className)}
|
||||||
initialContent={initialContent}
|
initialContent={initialContent}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
|||||||
Please see LICENSE files in the repository root for full details.
|
Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { ForwardedRef, forwardRef, MutableRefObject, useRef } from "react";
|
import React, { ForwardedRef, forwardRef, MutableRefObject, useMemo } from "react";
|
||||||
import { IEventRelation } from "matrix-js-sdk/src/matrix";
|
import { IEventRelation } from "matrix-js-sdk/src/matrix";
|
||||||
|
|
||||||
import { useWysiwygSendActionHandler } from "./hooks/useWysiwygSendActionHandler";
|
import { useWysiwygSendActionHandler } from "./hooks/useWysiwygSendActionHandler";
|
||||||
@@ -52,10 +52,13 @@ export default function SendWysiwygComposer({
|
|||||||
...props
|
...props
|
||||||
}: SendWysiwygComposerProps): JSX.Element {
|
}: SendWysiwygComposerProps): JSX.Element {
|
||||||
const Composer = isRichTextEnabled ? WysiwygComposer : PlainTextComposer;
|
const Composer = isRichTextEnabled ? WysiwygComposer : PlainTextComposer;
|
||||||
const defaultContextValue = useRef(getDefaultContextValue({ eventRelation: props.eventRelation }));
|
const defaultContextValue = useMemo(
|
||||||
|
() => getDefaultContextValue({ eventRelation: props.eventRelation }),
|
||||||
|
[props.eventRelation],
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ComposerContext.Provider value={defaultContextValue.current}>
|
<ComposerContext.Provider value={defaultContextValue}>
|
||||||
<Composer
|
<Composer
|
||||||
className="mx_SendWysiwygComposer"
|
className="mx_SendWysiwygComposer"
|
||||||
leftComponent={e2eStatus && <E2EIcon status={e2eStatus} />}
|
leftComponent={e2eStatus && <E2EIcon status={e2eStatus} />}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ export function useComposerFunctions(
|
|||||||
() => ({
|
() => ({
|
||||||
clear: () => {
|
clear: () => {
|
||||||
if (ref.current) {
|
if (ref.current) {
|
||||||
|
// eslint-disable-next-line react-compiler/react-compiler
|
||||||
ref.current.innerHTML = "";
|
ref.current.innerHTML = "";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export function usePlainTextInitialization(initialContent = "", ref: RefObject<H
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// always read and write the ref.current using .innerHTML for consistency in linebreak and HTML entity handling
|
// always read and write the ref.current using .innerHTML for consistency in linebreak and HTML entity handling
|
||||||
if (ref.current) {
|
if (ref.current) {
|
||||||
|
// eslint-disable-next-line react-compiler/react-compiler
|
||||||
ref.current.innerHTML = initialContent;
|
ref.current.innerHTML = initialContent;
|
||||||
}
|
}
|
||||||
}, [ref, initialContent]);
|
}, [ref, initialContent]);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { ChangeEvent, JSX, useCallback, useMemo, useRef, useState } from "react";
|
import React, { ChangeEvent, JSX, useCallback, useMemo, useState } from "react";
|
||||||
import {
|
import {
|
||||||
InlineField,
|
InlineField,
|
||||||
ToggleControl,
|
ToggleControl,
|
||||||
@@ -39,12 +39,12 @@ import { useSettingValue } from "../../../hooks/useSettings";
|
|||||||
*/
|
*/
|
||||||
export function ThemeChoicePanel(): JSX.Element {
|
export function ThemeChoicePanel(): JSX.Element {
|
||||||
const themeState = useTheme();
|
const themeState = useTheme();
|
||||||
const themeWatcher = useRef(new ThemeWatcher());
|
const themeWatcher = useMemo(() => new ThemeWatcher(), []);
|
||||||
const customThemeEnabled = useSettingValue<boolean>("feature_custom_themes");
|
const customThemeEnabled = useSettingValue<boolean>("feature_custom_themes");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SettingsSubsection heading={_t("common|theme")} legacy={false} data-testid="themePanel">
|
<SettingsSubsection heading={_t("common|theme")} legacy={false} data-testid="themePanel">
|
||||||
{themeWatcher.current.isSystemThemeSupported() && (
|
{themeWatcher.isSystemThemeSupported() && (
|
||||||
<SystemTheme systemThemeActivated={themeState.systemThemeActivated} />
|
<SystemTheme systemThemeActivated={themeState.systemThemeActivated} />
|
||||||
)}
|
)}
|
||||||
<ThemeSelectors theme={themeState.theme} disabled={themeState.systemThemeActivated} />
|
<ThemeSelectors theme={themeState.theme} disabled={themeState.systemThemeActivated} />
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ Please see LICENSE files in the repository root for full details.
|
|||||||
|
|
||||||
import React, { useCallback, useMemo, useState } from "react";
|
import React, { useCallback, useMemo, useState } from "react";
|
||||||
import { JoinRule, EventType, RoomState, Room } from "matrix-js-sdk/src/matrix";
|
import { JoinRule, EventType, RoomState, Room } from "matrix-js-sdk/src/matrix";
|
||||||
|
import { RoomPowerLevelsEventContent } from "matrix-js-sdk/src/types";
|
||||||
|
|
||||||
import { _t } from "../../../../../languageHandler";
|
import { _t } from "../../../../../languageHandler";
|
||||||
import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch";
|
import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch";
|
||||||
@@ -24,48 +25,49 @@ interface ElementCallSwitchProps {
|
|||||||
|
|
||||||
const ElementCallSwitch: React.FC<ElementCallSwitchProps> = ({ room }) => {
|
const ElementCallSwitch: React.FC<ElementCallSwitchProps> = ({ room }) => {
|
||||||
const isPublic = useMemo(() => room.getJoinRule() === JoinRule.Public, [room]);
|
const isPublic = useMemo(() => room.getJoinRule() === JoinRule.Public, [room]);
|
||||||
const [content, events, maySend] = useRoomState(
|
const [content, maySend] = useRoomState(
|
||||||
room,
|
room,
|
||||||
useCallback(
|
useCallback(
|
||||||
(state: RoomState) => {
|
(state: RoomState) => {
|
||||||
const content = state?.getStateEvents(EventType.RoomPowerLevels, "")?.getContent();
|
const content = state
|
||||||
|
?.getStateEvents(EventType.RoomPowerLevels, "")
|
||||||
|
?.getContent<RoomPowerLevelsEventContent>();
|
||||||
return [
|
return [
|
||||||
content ?? {},
|
content ?? {},
|
||||||
content?.["events"] ?? {},
|
|
||||||
state?.maySendStateEvent(EventType.RoomPowerLevels, room.client.getSafeUserId()),
|
state?.maySendStateEvent(EventType.RoomPowerLevels, room.client.getSafeUserId()),
|
||||||
];
|
] as const;
|
||||||
},
|
},
|
||||||
[room.client],
|
[room.client],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
const [elementCallEnabled, setElementCallEnabled] = useState<boolean>(() => {
|
const [elementCallEnabled, setElementCallEnabled] = useState<boolean>(() => {
|
||||||
return events[ElementCall.MEMBER_EVENT_TYPE.name] === 0;
|
return content.events?.[ElementCall.MEMBER_EVENT_TYPE.name] === 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
const onChange = useCallback(
|
const onChange = useCallback(
|
||||||
(enabled: boolean): void => {
|
(enabled: boolean): void => {
|
||||||
setElementCallEnabled(enabled);
|
setElementCallEnabled(enabled);
|
||||||
|
|
||||||
|
// Take a copy to avoid mutating the original
|
||||||
|
const newContent = { events: {}, ...content };
|
||||||
|
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
const userLevel = events[EventType.RoomMessage] ?? content.users_default ?? 0;
|
const userLevel = newContent.events[EventType.RoomMessage] ?? content.users_default ?? 0;
|
||||||
const moderatorLevel = content.kick ?? 50;
|
const moderatorLevel = content.kick ?? 50;
|
||||||
|
|
||||||
events[ElementCall.CALL_EVENT_TYPE.name] = isPublic ? moderatorLevel : userLevel;
|
newContent.events[ElementCall.CALL_EVENT_TYPE.name] = isPublic ? moderatorLevel : userLevel;
|
||||||
events[ElementCall.MEMBER_EVENT_TYPE.name] = userLevel;
|
newContent.events[ElementCall.MEMBER_EVENT_TYPE.name] = userLevel;
|
||||||
} else {
|
} else {
|
||||||
const adminLevel = events[EventType.RoomPowerLevels] ?? content.state_default ?? 100;
|
const adminLevel = newContent.events[EventType.RoomPowerLevels] ?? content.state_default ?? 100;
|
||||||
|
|
||||||
events[ElementCall.CALL_EVENT_TYPE.name] = adminLevel;
|
newContent.events[ElementCall.CALL_EVENT_TYPE.name] = adminLevel;
|
||||||
events[ElementCall.MEMBER_EVENT_TYPE.name] = adminLevel;
|
newContent.events[ElementCall.MEMBER_EVENT_TYPE.name] = adminLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
room.client.sendStateEvent(room.roomId, EventType.RoomPowerLevels, {
|
room.client.sendStateEvent(room.roomId, EventType.RoomPowerLevels, newContent);
|
||||||
events: events,
|
|
||||||
...content,
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
[room.client, room.roomId, content, events, isPublic],
|
[room.client, room.roomId, content, isPublic],
|
||||||
);
|
);
|
||||||
|
|
||||||
const brand = SdkConfig.get("element_call").brand ?? DEFAULTS.element_call.brand;
|
const brand = SdkConfig.get("element_call").brand ?? DEFAULTS.element_call.brand;
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ type Props = {
|
|||||||
const MATCH_SYSTEM_THEME_ID = "MATCH_SYSTEM_THEME_ID";
|
const MATCH_SYSTEM_THEME_ID = "MATCH_SYSTEM_THEME_ID";
|
||||||
|
|
||||||
const QuickThemeSwitcher: React.FC<Props> = ({ requestClose }) => {
|
const QuickThemeSwitcher: React.FC<Props> = ({ requestClose }) => {
|
||||||
const orderedThemes = useMemo(getOrderedThemes, []);
|
const orderedThemes = useMemo(() => getOrderedThemes(), []);
|
||||||
|
|
||||||
const themeState = useTheme();
|
const themeState = useTheme();
|
||||||
const nonHighContrast = findNonHighContrastTheme(themeState.theme);
|
const nonHighContrast = findNonHighContrastTheme(themeState.theme);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { useCallback, useEffect, useState } from "react";
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||||
import { ClientEvent, MatrixClient, MatrixEventEvent, Room } from "matrix-js-sdk/src/matrix";
|
import { ClientEvent, MatrixClient, MatrixEventEvent, Room } from "matrix-js-sdk/src/matrix";
|
||||||
import { throttle } from "lodash";
|
import { throttle } from "lodash";
|
||||||
|
|
||||||
@@ -42,14 +42,12 @@ export function useUnreadThreadRooms(forceComputation: boolean): Result {
|
|||||||
setResult(computeUnreadThreadRooms(mxClient, msc3946ProcessDynamicPredecessor, settingTACOnlyNotifs));
|
setResult(computeUnreadThreadRooms(mxClient, msc3946ProcessDynamicPredecessor, settingTACOnlyNotifs));
|
||||||
}, [mxClient, msc3946ProcessDynamicPredecessor, settingTACOnlyNotifs]);
|
}, [mxClient, msc3946ProcessDynamicPredecessor, settingTACOnlyNotifs]);
|
||||||
|
|
||||||
// The exhautive deps lint rule can't compute dependencies here since it's not a plain inline func.
|
const scheduleUpdate = useMemo(
|
||||||
// We make this as simple as possible so its only dep is doUpdate itself.
|
() =>
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
throttle(doUpdate, MIN_UPDATE_INTERVAL_MS, {
|
||||||
const scheduleUpdate = useCallback(
|
leading: false,
|
||||||
throttle(doUpdate, MIN_UPDATE_INTERVAL_MS, {
|
trailing: true,
|
||||||
leading: false,
|
}),
|
||||||
trailing: true,
|
|
||||||
}),
|
|
||||||
[doUpdate],
|
[doUpdate],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { TypedEventEmitter } from "matrix-js-sdk/src/matrix";
|
import { TypedEventEmitter } from "matrix-js-sdk/src/matrix";
|
||||||
import React, { ContextType, createContext, memo, ReactNode, useContext, useEffect, useRef, useState } from "react";
|
import React, { ContextType, createContext, memo, ReactNode, useContext, useEffect, useMemo, useState } from "react";
|
||||||
|
|
||||||
import { objectKeyChanges } from "../utils/objects.ts";
|
import { objectKeyChanges } from "../utils/objects.ts";
|
||||||
import { useTypedEventEmitter } from "../hooks/useEventEmitter.ts";
|
import { useTypedEventEmitter } from "../hooks/useEventEmitter.ts";
|
||||||
@@ -48,15 +48,16 @@ const ScopedRoomContext = createContext<EfficientContext<ContextValue> | undefin
|
|||||||
// Uses react memo and leverages splatting the value to ensure that the context is only updated when the state changes (shallow compare)
|
// Uses react memo and leverages splatting the value to ensure that the context is only updated when the state changes (shallow compare)
|
||||||
export const ScopedRoomContextProvider = memo(
|
export const ScopedRoomContextProvider = memo(
|
||||||
({ children, ...state }: { children: ReactNode } & ContextValue): JSX.Element => {
|
({ children, ...state }: { children: ReactNode } & ContextValue): JSX.Element => {
|
||||||
const contextRef = useRef(new EfficientContext<ContextValue>(state));
|
// eslint-disable-next-line react-compiler/react-compiler,react-hooks/exhaustive-deps
|
||||||
|
const context = useMemo(() => new EfficientContext<ContextValue>(state), []);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
contextRef.current.setState(state);
|
context.setState(state);
|
||||||
}, [state]);
|
}, [context, state]);
|
||||||
|
|
||||||
// Includes the legacy RoomContext provider for backwards compatibility with class components
|
// Includes the legacy RoomContext provider for backwards compatibility with class components
|
||||||
return (
|
return (
|
||||||
<RoomContext.Provider value={state}>
|
<RoomContext.Provider value={state}>
|
||||||
<ScopedRoomContext.Provider value={contextRef.current}>{children}</ScopedRoomContext.Provider>
|
<ScopedRoomContext.Provider value={context}>{children}</ScopedRoomContext.Provider>
|
||||||
</RoomContext.Provider>
|
</RoomContext.Provider>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
|||||||
Please see LICENSE files in the repository root for full details.
|
Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ReactNode, createContext, useCallback, useContext, useEffect, useRef, useState } from "react";
|
import { ReactNode, createContext, useCallback, useContext, useEffect, useState, useMemo } from "react";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A ToastContext helps components display any kind of toast message and can be provided
|
* A ToastContext helps components display any kind of toast message and can be provided
|
||||||
@@ -33,19 +33,19 @@ export function useToastContext(): ToastRack {
|
|||||||
* the ToastRack object that should be provided to the context
|
* the ToastRack object that should be provided to the context
|
||||||
*/
|
*/
|
||||||
export function useActiveToast(): [ReactNode | undefined, ToastRack] {
|
export function useActiveToast(): [ReactNode | undefined, ToastRack] {
|
||||||
const toastRack = useRef(new ToastRack());
|
const toastRack = useMemo(() => new ToastRack(), []);
|
||||||
|
|
||||||
const [activeToast, setActiveToast] = useState<ReactNode | undefined>(toastRack.current.getActiveToast());
|
const [activeToast, setActiveToast] = useState<ReactNode | undefined>(toastRack.getActiveToast());
|
||||||
|
|
||||||
const updateCallback = useCallback(() => {
|
const updateCallback = useCallback(() => {
|
||||||
setActiveToast(toastRack.current.getActiveToast());
|
setActiveToast(toastRack.getActiveToast());
|
||||||
}, [setActiveToast, toastRack]);
|
}, [setActiveToast, toastRack]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
toastRack.current.setCallback(updateCallback);
|
toastRack.setCallback(updateCallback);
|
||||||
}, [toastRack, updateCallback]);
|
}, [toastRack, updateCallback]);
|
||||||
|
|
||||||
return [activeToast, toastRack.current];
|
return [activeToast, toastRack];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DisplayedToast {
|
interface DisplayedToast {
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export function useAsyncRefreshMemo<T>(fn: Fn<T>, deps: DependencyList, initialV
|
|||||||
return () => {
|
return () => {
|
||||||
discard = true;
|
discard = true;
|
||||||
};
|
};
|
||||||
}, deps); // eslint-disable-line react-hooks/exhaustive-deps
|
}, deps); // eslint-disable-line react-hooks/exhaustive-deps,react-compiler/react-compiler
|
||||||
useEffect(refresh, [refresh]);
|
useEffect(refresh, [refresh]);
|
||||||
return [value, refresh];
|
return [value, refresh];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ export const useNotificationState = (room: Room): [RoomNotifState | undefined, (
|
|||||||
setNotificationState(echoChamber.notificationVolume);
|
setNotificationState(echoChamber.notificationVolume);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// eslint-disable-next-line react-compiler/react-compiler
|
||||||
const setter = useCallback((state: RoomNotifState) => (echoChamber.notificationVolume = state), [echoChamber]);
|
const setter = useCallback((state: RoomNotifState) => (echoChamber.notificationVolume = state), [echoChamber]);
|
||||||
return [notificationState, setter];
|
return [notificationState, setter];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -22,6 +22,6 @@ export const useTransition = <D extends DependencyList>(callback: (...params: D)
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (args.current !== null) func.current(...args.current);
|
if (args.current !== null) func.current(...args.current);
|
||||||
args.current = deps;
|
args.current = deps;
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-compiler/react-compiler,react-hooks/exhaustive-deps
|
||||||
}, deps);
|
}, deps);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ const USER_ONBOARDING_CONTEXT_INTERVAL = 5000;
|
|||||||
*/
|
*/
|
||||||
function useRefOf<T extends any[], R>(value: (...values: T) => R): (...values: T) => R {
|
function useRefOf<T extends any[], R>(value: (...values: T) => R): (...values: T) => R {
|
||||||
const ref = useRef(value);
|
const ref = useRef(value);
|
||||||
|
// eslint-disable-next-line react-compiler/react-compiler
|
||||||
ref.current = value;
|
ref.current = value;
|
||||||
return useCallback((...values: T) => ref.current(...values), []);
|
return useCallback((...values: T) => ref.current(...values), []);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
|||||||
Please see LICENSE files in the repository root for full details.
|
Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useMemo } from "react";
|
||||||
|
|
||||||
import type { Map as MapLibreMap } from "maplibre-gl";
|
import type { Map as MapLibreMap } from "maplibre-gl";
|
||||||
import { createMap } from "./map";
|
import { createMap } from "./map";
|
||||||
@@ -26,29 +26,25 @@ interface UseMapProps {
|
|||||||
*/
|
*/
|
||||||
export const useMap = ({ interactive, bodyId, onError }: UseMapProps): MapLibreMap | undefined => {
|
export const useMap = ({ interactive, bodyId, onError }: UseMapProps): MapLibreMap | undefined => {
|
||||||
const cli = useMatrixClientContext();
|
const cli = useMatrixClientContext();
|
||||||
const [map, setMap] = useState<MapLibreMap>();
|
|
||||||
|
|
||||||
useEffect(
|
const map = useMemo(() => {
|
||||||
() => {
|
try {
|
||||||
try {
|
return createMap(cli, !!interactive, bodyId, onError);
|
||||||
setMap(createMap(cli, !!interactive, bodyId, onError));
|
} catch (error) {
|
||||||
} catch (error) {
|
console.error("Error encountered in useMap", error);
|
||||||
console.error("Error encountered in useMap", error);
|
if (error instanceof Error) {
|
||||||
if (error instanceof Error) {
|
onError?.(error);
|
||||||
onError?.(error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return () => {
|
}
|
||||||
if (map) {
|
}, [bodyId, cli, interactive, onError]);
|
||||||
map.remove();
|
|
||||||
setMap(undefined);
|
// cleanup
|
||||||
}
|
useEffect(() => {
|
||||||
};
|
if (!map) return;
|
||||||
},
|
return () => {
|
||||||
// map is excluded as a dependency
|
map.remove();
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
};
|
||||||
[interactive, bodyId, onError],
|
}, [map]);
|
||||||
);
|
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
};
|
};
|
||||||
|
|||||||
28
yarn.lock
28
yarn.lock
@@ -61,7 +61,7 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.3.tgz#99488264a56b2aded63983abd6a417f03b92ed02"
|
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.3.tgz#99488264a56b2aded63983abd6a417f03b92ed02"
|
||||||
integrity sha512-nHIxvKPniQXpmQLb0vhY3VaFb3S0YrTAwpOWJZh1wn3oJPjJk9Asva204PsBdmAE8vpzfHudT8DB0scYvy9q0g==
|
integrity sha512-nHIxvKPniQXpmQLb0vhY3VaFb3S0YrTAwpOWJZh1wn3oJPjJk9Asva204PsBdmAE8vpzfHudT8DB0scYvy9q0g==
|
||||||
|
|
||||||
"@babel/core@^7.0.0", "@babel/core@^7.11.6", "@babel/core@^7.12.10", "@babel/core@^7.12.3", "@babel/core@^7.18.5", "@babel/core@^7.21.3", "@babel/core@^7.23.9":
|
"@babel/core@^7.0.0", "@babel/core@^7.11.6", "@babel/core@^7.12.10", "@babel/core@^7.12.3", "@babel/core@^7.18.5", "@babel/core@^7.21.3", "@babel/core@^7.23.9", "@babel/core@^7.24.4":
|
||||||
version "7.26.0"
|
version "7.26.0"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.0.tgz#d78b6023cc8f3114ccf049eb219613f74a747b40"
|
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.0.tgz#d78b6023cc8f3114ccf049eb219613f74a747b40"
|
||||||
integrity sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==
|
integrity sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==
|
||||||
@@ -308,7 +308,7 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@babel/types" "^7.25.8"
|
"@babel/types" "^7.25.8"
|
||||||
|
|
||||||
"@babel/parser@^7.25.9", "@babel/parser@^7.26.0", "@babel/parser@^7.26.3":
|
"@babel/parser@^7.24.4", "@babel/parser@^7.25.9", "@babel/parser@^7.26.0", "@babel/parser@^7.26.3":
|
||||||
version "7.26.3"
|
version "7.26.3"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.3.tgz#8c51c5db6ddf08134af1ddbacf16aaab48bac234"
|
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.3.tgz#8c51c5db6ddf08134af1ddbacf16aaab48bac234"
|
||||||
integrity sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==
|
integrity sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==
|
||||||
@@ -5662,6 +5662,18 @@ eslint-plugin-matrix-org@^2.0.2:
|
|||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-matrix-org/-/eslint-plugin-matrix-org-2.0.2.tgz#95b86b0f16704ab19740f7c3c62eae69e20365e6"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-matrix-org/-/eslint-plugin-matrix-org-2.0.2.tgz#95b86b0f16704ab19740f7c3c62eae69e20365e6"
|
||||||
integrity sha512-cQy5Rjeq6uyu1mLXlPZwEJdyM0NmclrnEz68y792FSuuxzMyJNNYLGDQ5CkYW8H+PrD825HUFZ34pNXnjMOzOw==
|
integrity sha512-cQy5Rjeq6uyu1mLXlPZwEJdyM0NmclrnEz68y792FSuuxzMyJNNYLGDQ5CkYW8H+PrD825HUFZ34pNXnjMOzOw==
|
||||||
|
|
||||||
|
eslint-plugin-react-compiler@^19.0.0-beta-df7b47d-20241124:
|
||||||
|
version "19.0.0-beta-df7b47d-20241124"
|
||||||
|
resolved "https://registry.yarnpkg.com/eslint-plugin-react-compiler/-/eslint-plugin-react-compiler-19.0.0-beta-df7b47d-20241124.tgz#468751d3a8a6781189405ee56b39b80545306df8"
|
||||||
|
integrity sha512-82PfnllC8jP/68KdLAbpWuYTcfmtGLzkqy2IW85WopKMTr+4rdQpp+lfliQ/QE79wWrv/dRoADrk3Pdhq25nTw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/core" "^7.24.4"
|
||||||
|
"@babel/parser" "^7.24.4"
|
||||||
|
"@babel/plugin-transform-private-methods" "^7.25.9"
|
||||||
|
hermes-parser "^0.25.1"
|
||||||
|
zod "^3.22.4"
|
||||||
|
zod-validation-error "^3.0.3"
|
||||||
|
|
||||||
eslint-plugin-react-hooks@^5.0.0:
|
eslint-plugin-react-hooks@^5.0.0:
|
||||||
version "5.0.0"
|
version "5.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0.tgz#72e2eefbac4b694f5324154619fee44f5f60f101"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0.tgz#72e2eefbac4b694f5324154619fee44f5f60f101"
|
||||||
@@ -6639,6 +6651,18 @@ he@^1.2.0:
|
|||||||
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
|
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
|
||||||
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
|
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
|
||||||
|
|
||||||
|
hermes-estree@0.25.1:
|
||||||
|
version "0.25.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.25.1.tgz#6aeec17d1983b4eabf69721f3aa3eb705b17f480"
|
||||||
|
integrity sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==
|
||||||
|
|
||||||
|
hermes-parser@^0.25.1:
|
||||||
|
version "0.25.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.25.1.tgz#5be0e487b2090886c62bd8a11724cd766d5f54d1"
|
||||||
|
integrity sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==
|
||||||
|
dependencies:
|
||||||
|
hermes-estree "0.25.1"
|
||||||
|
|
||||||
highlight.js@^11.3.1:
|
highlight.js@^11.3.1:
|
||||||
version "11.10.0"
|
version "11.10.0"
|
||||||
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.10.0.tgz#6e3600dc4b33d6dc23d5bd94fbf72405f5892b92"
|
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.10.0.tgz#6e3600dc4b33d6dc23d5bd94fbf72405f5892b92"
|
||||||
|
|||||||
Reference in New Issue
Block a user