From 386a66c19c71be554e9e35b3eaf10b2790cde135 Mon Sep 17 00:00:00 2001 From: hayyaksi <193020925+hayaksi1@users.noreply.github.com> Date: Wed, 5 Aug 2026 11:56:26 +0300 Subject: [PATCH] Show the filename in the audio player title when the event has one (#34479) MAudioBody passed the event body straight to the player, so an audio message sent with a caption showed the caption text instead of the file name. It now uses presentableTextForFile, the same helper m.file and m.image already use. Fixes https://github.com/element-hq/element-web/issues/31116 --- .../components/views/messages/MAudioBody.tsx | 10 +++++- .../views/messages/MAudioBody-test.tsx | 34 ++++++++++++++----- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/apps/web/src/components/views/messages/MAudioBody.tsx b/apps/web/src/components/views/messages/MAudioBody.tsx index 997d32b75d..978c4688a6 100644 --- a/apps/web/src/components/views/messages/MAudioBody.tsx +++ b/apps/web/src/components/views/messages/MAudioBody.tsx @@ -21,6 +21,7 @@ import RoomContext, { TimelineRenderingType } from "../../../contexts/RoomContex import MediaProcessingError from "./shared/MediaProcessingError"; import { AudioPlayerViewModel } from "../../../viewmodels/room/timeline/event-tile/body/AudioPlayerViewModel"; import { FileBodyFactory, renderMBody } from "./MBodyFactory"; +import { presentableTextForFile } from "../../../utils/FileUtils"; interface IState { error?: boolean; @@ -110,7 +111,14 @@ export default class MAudioBody extends React.PureComponent // At this point we should have a playable state return ( - + (), + undefined, + false, + )} + /> {this.showFileBody && renderMBody({ ...this.props, showFileInfo: false }, FileBodyFactory)} ); diff --git a/apps/web/test/unit-tests/components/views/messages/MAudioBody-test.tsx b/apps/web/test/unit-tests/components/views/messages/MAudioBody-test.tsx index e2e2245c13..2198ce1e64 100644 --- a/apps/web/test/unit-tests/components/views/messages/MAudioBody-test.tsx +++ b/apps/web/test/unit-tests/components/views/messages/MAudioBody-test.tsx @@ -17,6 +17,15 @@ import { type MediaEventHelper } from "../../../../../src/utils/MediaEventHelper describe("", () => { let event: MatrixEvent; + + const mediaEventHelper = { + sourceBlob: { + value: { + arrayBuffer: () => new ArrayBuffer(8), + }, + }, + } as unknown as MediaEventHelper; + beforeEach(() => { const playback = new MockedPlayback(PlaybackState.Decoding, 50, 10) as unknown as Playback; jest.spyOn(PlaybackManager.instance, "createPlaybackInstance").mockReturnValue(playback); @@ -34,15 +43,24 @@ describe("", () => { }); it("should render", async () => { - const mediaEventHelper = { - sourceBlob: { - value: { - arrayBuffer: () => new ArrayBuffer(8), - }, - }, - } as unknown as MediaEventHelper; - await act(() => render()); expect(await screen.findByRole("region", { name: "Audio player" })).toBeInTheDocument(); }); + + it("should show the body as the title when there is no filename", async () => { + await act(() => render()); + expect(await screen.findByRole("region", { name: "Audio player" })).toBeInTheDocument(); + expect(screen.getByText("audio name")).toBeInTheDocument(); + }); + + it("should prefer the filename over the body as the title", async () => { + // A caption puts the human readable text in `body` and the actual file name in `filename`. + event.getContent().filename = "recording.ogg"; + event.getContent().body = "Listen to this!"; + + await act(() => render()); + expect(await screen.findByRole("region", { name: "Audio player" })).toBeInTheDocument(); + expect(screen.getByText("recording.ogg")).toBeInTheDocument(); + expect(screen.queryByText("Listen to this!")).not.toBeInTheDocument(); + }); });