Replace some custom React hooks with observable-hooks (#2710)

The observable-hooks package provides hooks that do exactly the same thing as these custom React hooks I had written a while back. (even the names are the same, wow)

Co-authored-by: Hugh Nimmo-Smith <hughns@element.io>
This commit is contained in:
Robin 2024-11-06 04:43:27 -05:00 committed by GitHub
parent d3f069e763
commit 110914a4d6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 12 additions and 42 deletions

View File

@ -28,8 +28,8 @@ import {
import useMeasure from "react-use-measure";
import { MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession";
import classNames from "classnames";
import { BehaviorSubject } from "rxjs";
import { useObservableEagerState } from "observable-hooks";
import { BehaviorSubject, map } from "rxjs";
import { useObservable, useObservableEagerState } from "observable-hooks";
import { logger } from "matrix-js-sdk/src/logger";
import LogoMark from "../icons/LogoMark.svg?react";
@ -65,7 +65,6 @@ import { ECConnectionState } from "../livekit/useECConnectionState";
import { useOpenIDSFU } from "../livekit/openIDSFU";
import { CallViewModel, GridMode, Layout } from "../state/CallViewModel";
import { Grid, TileProps } from "../grid/Grid";
import { useObservable } from "../state/useObservable";
import { useInitial } from "../useInitial";
import { SpotlightTile } from "../tile/SpotlightTile";
import { EncryptionSystem } from "../e2ee/sharedKeyManagement";
@ -103,7 +102,10 @@ export const ActiveCall: FC<ActiveCallProps> = (props) => {
sfuConfig,
props.e2eeSystem,
);
const connStateObservable = useObservable(connState);
const connStateObservable = useObservable(
(inputs) => inputs.pipe(map(([connState]) => connState)),
[connState],
);
const [vm, setVm] = useState<CallViewModel | null>(null);
useEffect(() => {
@ -308,7 +310,10 @@ export const InCallView: FC<InCallViewProps> = ({
windowMode,
],
);
const gridBoundsObservable = useObservable(gridBounds);
const gridBoundsObservable = useObservable(
(inputs) => inputs.pipe(map(([gridBounds]) => gridBounds)),
[gridBounds],
);
const spotlightAlignment = useInitial(
() => new BehaviorSubject(defaultSpotlightAlignment),

View File

@ -1,34 +0,0 @@
/*
Copyright 2023, 2024 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only
Please see LICENSE in the repository root for full details.
*/
import { Ref, useCallback, useRef } from "react";
import { BehaviorSubject, Observable } from "rxjs";
import { useInitial } from "../useInitial";
/**
* React hook that creates an Observable from a changing value. The Observable
* replays its current value upon subscription and emits whenever the value
* changes.
*/
export function useObservable<T>(value: T): Observable<T> {
const subject = useRef<BehaviorSubject<T>>();
subject.current ??= new BehaviorSubject(value);
if (value !== subject.current.value) subject.current.next(value);
return subject.current;
}
/**
* React hook that creates a ref and an Observable that emits any values
* stored in the ref. The Observable replays the value currently stored in the
* ref upon subscription.
*/
export function useObservableRef<T>(initialValue: T): [Observable<T>, Ref<T>] {
const subject = useInitial(() => new BehaviorSubject(initialValue));
const ref = useCallback((value: T) => subject.next(value), [subject]);
return [subject, ref];
}

View File

@ -22,7 +22,7 @@ import {
} from "@vector-im/compound-design-tokens/assets/web/icons";
import { animated } from "@react-spring/web";
import { Observable, map } from "rxjs";
import { useObservableEagerState } from "observable-hooks";
import { useObservableEagerState, useObservableRef } from "observable-hooks";
import { useTranslation } from "react-i18next";
import classNames from "classnames";
import { TrackReferenceOrPlaceholder } from "@livekit/components-core";
@ -39,7 +39,6 @@ import {
} from "../state/MediaViewModel";
import { useInitial } from "../useInitial";
import { useMergedRefs } from "../useMergedRefs";
import { useObservableRef } from "../state/useObservable";
import { useReactiveState } from "../useReactiveState";
import { useLatest } from "../useLatest";
import { SpotlightTileViewModel } from "../state/TileViewModel";
@ -203,7 +202,7 @@ export const SpotlightTile = forwardRef<HTMLDivElement, Props>(
theirRef,
) => {
const { t } = useTranslation();
const [root, ourRef] = useObservableRef<HTMLDivElement | null>(null);
const [ourRef, root] = useObservableRef<HTMLDivElement | null>(null);
const ref = useMergedRefs(ourRef, theirRef);
const maximised = useObservableEagerState(vm.maximised);
const media = useObservableEagerState(vm.media);