diff --git a/src/Notifier.ts b/src/Notifier.ts index dd624e2dc7..7e1f9eb0a4 100644 --- a/src/Notifier.ts +++ b/src/Notifier.ts @@ -50,6 +50,7 @@ import { localNotificationsAreSilenced, createLocalNotificationSettingsIfNeeded import { getIncomingCallToastKey, IncomingCallToast } from "./toasts/IncomingCallToast"; import ToastStore from "./stores/ToastStore"; import { ElementCall } from "./models/Call"; +import { VoiceBroadcastChunkEventType } from "./voice-broadcast"; /* * Dispatches: @@ -77,6 +78,13 @@ const msgTypeHandlers = { [M_LOCATION.altName]: (event: MatrixEvent) => { return TextForEvent.textForLocationEvent(event)(); }, + [MsgType.Audio]: (event: MatrixEvent): string | null => { + if (event.getContent()?.[VoiceBroadcastChunkEventType]) { + // mute broadcast chunks + return null; + } + return TextForEvent.textForEvent(event); + }, }; export const Notifier = { diff --git a/test/Notifier-test.ts b/test/Notifier-test.ts index bfa1e1d1f3..a3b1f9b2db 100644 --- a/test/Notifier-test.ts +++ b/test/Notifier-test.ts @@ -20,6 +20,7 @@ import { Room, RoomEvent } from "matrix-js-sdk/src/models/room"; import { IContent, MatrixEvent } from "matrix-js-sdk/src/models/event"; import { SyncState } from "matrix-js-sdk/src/sync"; import { waitFor } from "@testing-library/react"; +import { EventType, MsgType } from "matrix-js-sdk/src/matrix"; import BasePlatform from "../src/BasePlatform"; import { ElementCall } from "../src/models/Call"; @@ -39,6 +40,7 @@ import { mkThread } from "./test-utils/threads"; import dis from "../src/dispatcher/dispatcher"; import { ThreadPayload } from "../src/dispatcher/payloads/ThreadPayload"; import { Action } from "../src/dispatcher/actions"; +import { VoiceBroadcastChunkEventType } from "../src/voice-broadcast"; jest.mock("../src/utils/notifications", () => ({ // @ts-ignore @@ -73,6 +75,22 @@ describe("Notifier", () => { }); }; + const mkAudioEvent = (broadcastChunk = false): MatrixEvent => { + const chunkContent = broadcastChunk ? { [VoiceBroadcastChunkEventType]: {} } : {}; + + return mkEvent({ + event: true, + type: EventType.RoomMessage, + user: "@user:example.com", + room: "!room:example.com", + content: { + ...chunkContent, + msgtype: MsgType.Audio, + body: "test audio message", + }, + }); + }; + beforeEach(() => { accountDataStore = {}; mockClient = getMockClientWithEventEmitter({ @@ -94,11 +112,11 @@ describe("Notifier", () => { }); mockClient.pushRules = { - global: undefined, + global: {}, }; - accountDataEventKey = getLocalNotificationAccountDataEventType(mockClient.deviceId); + accountDataEventKey = getLocalNotificationAccountDataEventType(mockClient.deviceId!); - testRoom = new Room(roomId, mockClient, mockClient.getUserId()); + testRoom = new Room(roomId, mockClient, mockClient.getSafeUserId()); MockPlatform = mockPlatformPeg({ supportsNotifications: jest.fn().mockReturnValue(true), @@ -109,8 +127,10 @@ describe("Notifier", () => { Notifier.isBodyEnabled = jest.fn().mockReturnValue(true); - mockClient.getRoom.mockImplementation((id) => { - return id === roomId ? testRoom : new Room(id, mockClient, mockClient.getUserId()); + mockClient.getRoom.mockImplementation((id: string | undefined): Room | null => { + if (id === roomId) return testRoom; + if (id) return new Room(id, mockClient, mockClient.getSafeUserId()); + return null; }); }); @@ -256,6 +276,24 @@ describe("Notifier", () => { Notifier._displayPopupNotification(testEvent, testRoom); expect(MockPlatform.displayNotification).toHaveBeenCalledTimes(count); }); + + it("should display a notification for a voice message", () => { + const audioEvent = mkAudioEvent(); + Notifier._displayPopupNotification(audioEvent, testRoom); + expect(MockPlatform.displayNotification).toHaveBeenCalledWith( + "@user:example.com (!room1:server)", + "@user:example.com: test audio message", + "data:image/png;base64,00", + testRoom, + audioEvent, + ); + }); + + it("should not display a notification for a broadcast chunk", () => { + const audioEvent = mkAudioEvent(true); + Notifier._displayPopupNotification(audioEvent, testRoom); + expect(MockPlatform.displayNotification).not.toHaveBeenCalled(); + }); }); describe("getSoundForRoom", () => { @@ -448,7 +486,7 @@ describe("Notifier", () => { dis.dispatch({ action: Action.ViewThread, - thread_id: rootEvent.getId(), + thread_id: rootEvent.getId()!, }); await waitFor(() => expect(SdkContextClass.instance.roomViewStore.getThreadId()).toBe(rootEvent.getId())); @@ -456,6 +494,11 @@ describe("Notifier", () => { Notifier._evaluateEvent(events[1]); expect(Notifier._displayPopupNotification).toHaveBeenCalledTimes(1); }); + + it("should show a pop-up for an audio message", () => { + Notifier._evaluateEvent(mkAudioEvent()); + expect(Notifier._displayPopupNotification).toHaveBeenCalledTimes(1); + }); }); describe("setPromptHidden", () => { diff --git a/test/test-utils/client.ts b/test/test-utils/client.ts index 47e037b8fd..47040dcb4b 100644 --- a/test/test-utils/client.ts +++ b/test/test-utils/client.ts @@ -92,6 +92,7 @@ export const unmockClientPeg = () => jest.spyOn(MatrixClientPeg, "get").mockRest */ export const mockClientMethodsUser = (userId = "@alice:domain") => ({ getUserId: jest.fn().mockReturnValue(userId), + getSafeUserId: jest.fn().mockReturnValue(userId), getUser: jest.fn().mockReturnValue(new User(userId)), isGuest: jest.fn().mockReturnValue(false), mxcUrlToHttp: jest.fn().mockReturnValue("mock-mxcUrlToHttp"),