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

Commit 8679ace

Browse files
authored
Fix incoming call toast crash due to audio refactor (#12737)
* 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]>
1 parent 466f37a commit 8679ace

File tree

4 files changed

+20
-14
lines changed

4 files changed

+20
-14
lines changed

src/LegacyCallHandler.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,15 @@ export default class LegacyCallHandler extends EventEmitter {
457457
logger.debug(`${logPrefix} paused audio`);
458458
}
459459

460+
/**
461+
* Returns whether the given audio is currently playing
462+
* Only supported for looping audio tracks
463+
* @param audioId the ID of the audio to query for playing state
464+
*/
465+
public isPlaying(audioId: AudioID.Ring | AudioID.Ringback): boolean {
466+
return !!this.playingSources[audioId];
467+
}
468+
460469
private matchesCallForThisRoom(call: MatrixCall): boolean {
461470
// We don't allow placing more than one call per room, but that doesn't mean there
462471
// can't be more than one, eg. in a glare situation. This checks that the given call

src/toasts/IncomingCallToast.tsx

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

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

@@ -78,7 +78,6 @@ export function IncomingCallToast({ notifyEvent }: Props): JSX.Element {
7878
const roomId = notifyEvent.getRoomId()!;
7979
const room = MatrixClientPeg.safeGet().getRoom(roomId) ?? undefined;
8080
const call = useCall(roomId);
81-
const audio = useMemo(() => document.getElementById(AudioID.Ring) as HTMLMediaElement, []);
8281
const [connectedCalls, setConnectedCalls] = useState<Call[]>(Array.from(CallStore.instance.connectedCalls));
8382
useEventEmitter(CallStore.instance, CallStoreEvent.ConnectedCalls, () => {
8483
setConnectedCalls(Array.from(CallStore.instance.connectedCalls));
@@ -87,18 +86,18 @@ export function IncomingCallToast({ notifyEvent }: Props): JSX.Element {
8786
// Start ringing if not already.
8887
useEffect(() => {
8988
const isRingToast = (notifyEvent.getContent() as unknown as { notify_type: string })["notify_type"] == "ring";
90-
if (isRingToast && audio.paused) {
91-
audio.play();
89+
if (isRingToast && !LegacyCallHandler.instance.isPlaying(AudioID.Ring)) {
90+
LegacyCallHandler.instance.play(AudioID.Ring);
9291
}
93-
}, [audio, notifyEvent]);
92+
}, [notifyEvent]);
9493

9594
// Stop ringing on dismiss.
9695
const dismissToast = useCallback((): void => {
9796
ToastStore.sharedInstance().dismissToast(
9897
getIncomingCallToastKey(notifyEvent.getContent().call_id ?? "", roomId),
9998
);
100-
audio.pause();
101-
}, [audio, notifyEvent, roomId]);
99+
LegacyCallHandler.instance.pause(AudioID.Ring);
100+
}, [notifyEvent, roomId]);
102101

103102
// Dismiss if session got ended remotely.
104103
const onCall = useCallback(

test/setup/mocks.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export const mocks = {
1818
AudioBufferSourceNode: {
1919
connect: jest.fn(),
2020
start: jest.fn(),
21+
stop: jest.fn(),
2122
} as unknown as AudioBufferSourceNode,
2223
AudioContext: {
2324
close: jest.fn(),

test/toasts/IncomingCallToast-test.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,10 @@ import { WidgetMessagingStore } from "../../src/stores/widgets/WidgetMessagingSt
3939
import DMRoomMap from "../../src/utils/DMRoomMap";
4040
import ToastStore from "../../src/stores/ToastStore";
4141
import { getIncomingCallToastKey, IncomingCallToast } from "../../src/toasts/IncomingCallToast";
42-
import { AudioID } from "../../src/LegacyCallHandler";
42+
import LegacyCallHandler, { AudioID } from "../../src/LegacyCallHandler";
4343

44-
describe("IncomingCallEvent", () => {
44+
describe("IncomingCallToast", () => {
4545
useMockedCalls();
46-
jest.spyOn(HTMLMediaElement.prototype, "play").mockImplementation(async () => {});
4746

4847
let client: Mocked<MatrixClient>;
4948
let room: Room;
@@ -133,10 +132,8 @@ describe("IncomingCallEvent", () => {
133132
...notifyContent,
134133
notify_type: "ring",
135134
}) as any;
136-
const playMock = jest.fn();
137-
const audio = { play: playMock, paused: true };
138135

139-
jest.spyOn(document, "getElementById").mockReturnValue(audio as any);
136+
const playMock = jest.spyOn(LegacyCallHandler.instance, "play");
140137
render(<IncomingCallToast notifyEvent={call.event} />);
141138
expect(playMock).toHaveBeenCalled();
142139
});

0 commit comments

Comments
 (0)