Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Fix incoming call toast crash due to audio refactor (#12737)
Browse files Browse the repository at this point in the history
* Fix incoming call toast crash due to audio refactor

Signed-off-by: Michael Telatynski <[email protected]>

* Fix tests

Signed-off-by: Michael Telatynski <[email protected]>

* Iterate

Signed-off-by: Michael Telatynski <[email protected]>

---------

Signed-off-by: Michael Telatynski <[email protected]>
  • Loading branch information
t3chguy authored Jul 8, 2024
1 parent 466f37a commit 8679ace
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 14 deletions.
9 changes: 9 additions & 0 deletions src/LegacyCallHandler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,15 @@ export default class LegacyCallHandler extends EventEmitter {
logger.debug(`${logPrefix} paused audio`);
}

/**
* Returns whether the given audio is currently playing
* Only supported for looping audio tracks
* @param audioId the ID of the audio to query for playing state
*/
public isPlaying(audioId: AudioID.Ring | AudioID.Ringback): boolean {
return !!this.playingSources[audioId];
}

private matchesCallForThisRoom(call: MatrixCall): boolean {
// We don't allow placing more than one call per room, but that doesn't mean there
// can't be more than one, eg. in a glare situation. This checks that the given call
Expand Down
15 changes: 7 additions & 8 deletions src/toasts/IncomingCallToast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import React, { useCallback, useEffect, useMemo, useState } from "react";
import React, { useCallback, useEffect, useState } from "react";
import { MatrixEvent } from "matrix-js-sdk/src/matrix";
import { Button, Tooltip } from "@vector-im/compound-web";
import { Icon as VideoCallIcon } from "@vector-im/compound-design-tokens/icons/video-call-solid.svg";
Expand All @@ -36,7 +36,7 @@ import AccessibleButton, { ButtonEvent } from "../components/views/elements/Acce
import { useDispatcher } from "../hooks/useDispatcher";
import { ActionPayload } from "../dispatcher/payloads";
import { Call } from "../models/Call";
import { AudioID } from "../LegacyCallHandler";
import LegacyCallHandler, { AudioID } from "../LegacyCallHandler";
import { useEventEmitter } from "../hooks/useEventEmitter";
import { CallStore, CallStoreEvent } from "../stores/CallStore";

Expand Down Expand Up @@ -78,7 +78,6 @@ export function IncomingCallToast({ notifyEvent }: Props): JSX.Element {
const roomId = notifyEvent.getRoomId()!;
const room = MatrixClientPeg.safeGet().getRoom(roomId) ?? undefined;
const call = useCall(roomId);
const audio = useMemo(() => document.getElementById(AudioID.Ring) as HTMLMediaElement, []);
const [connectedCalls, setConnectedCalls] = useState<Call[]>(Array.from(CallStore.instance.connectedCalls));
useEventEmitter(CallStore.instance, CallStoreEvent.ConnectedCalls, () => {
setConnectedCalls(Array.from(CallStore.instance.connectedCalls));
Expand All @@ -87,18 +86,18 @@ export function IncomingCallToast({ notifyEvent }: Props): JSX.Element {
// Start ringing if not already.
useEffect(() => {
const isRingToast = (notifyEvent.getContent() as unknown as { notify_type: string })["notify_type"] == "ring";
if (isRingToast && audio.paused) {
audio.play();
if (isRingToast && !LegacyCallHandler.instance.isPlaying(AudioID.Ring)) {
LegacyCallHandler.instance.play(AudioID.Ring);
}
}, [audio, notifyEvent]);
}, [notifyEvent]);

// Stop ringing on dismiss.
const dismissToast = useCallback((): void => {
ToastStore.sharedInstance().dismissToast(
getIncomingCallToastKey(notifyEvent.getContent().call_id ?? "", roomId),
);
audio.pause();
}, [audio, notifyEvent, roomId]);
LegacyCallHandler.instance.pause(AudioID.Ring);
}, [notifyEvent, roomId]);

// Dismiss if session got ended remotely.
const onCall = useCallback(
Expand Down
1 change: 1 addition & 0 deletions test/setup/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const mocks = {
AudioBufferSourceNode: {
connect: jest.fn(),
start: jest.fn(),
stop: jest.fn(),
} as unknown as AudioBufferSourceNode,
AudioContext: {
close: jest.fn(),
Expand Down
9 changes: 3 additions & 6 deletions test/toasts/IncomingCallToast-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,10 @@ import { WidgetMessagingStore } from "../../src/stores/widgets/WidgetMessagingSt
import DMRoomMap from "../../src/utils/DMRoomMap";
import ToastStore from "../../src/stores/ToastStore";
import { getIncomingCallToastKey, IncomingCallToast } from "../../src/toasts/IncomingCallToast";
import { AudioID } from "../../src/LegacyCallHandler";
import LegacyCallHandler, { AudioID } from "../../src/LegacyCallHandler";

describe("IncomingCallEvent", () => {
describe("IncomingCallToast", () => {
useMockedCalls();
jest.spyOn(HTMLMediaElement.prototype, "play").mockImplementation(async () => {});

let client: Mocked<MatrixClient>;
let room: Room;
Expand Down Expand Up @@ -133,10 +132,8 @@ describe("IncomingCallEvent", () => {
...notifyContent,
notify_type: "ring",
}) as any;
const playMock = jest.fn();
const audio = { play: playMock, paused: true };

jest.spyOn(document, "getElementById").mockReturnValue(audio as any);
const playMock = jest.spyOn(LegacyCallHandler.instance, "play");
render(<IncomingCallToast notifyEvent={call.event} />);
expect(playMock).toHaveBeenCalled();
});
Expand Down

0 comments on commit 8679ace

Please sign in to comment.