mirror of https://github.com/vector-im/riot-web
Fix incoming call toast crash due to audio refactor (#12737)
* Fix incoming call toast crash due to audio refactor Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix tests Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>pull/28217/head
parent
466f37a83d
commit
8679ace2b2
|
@ -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
|
||||
|
|
|
@ -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";
|
||||
|
@ -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";
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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(
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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;
|
||||
|
@ -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();
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue