diff --git a/src/components/views/messages/MAudioBody.tsx b/src/components/views/messages/MAudioBody.tsx
index db61672c9c..967e0d5fc7 100644
--- a/src/components/views/messages/MAudioBody.tsx
+++ b/src/components/views/messages/MAudioBody.tsx
@@ -6,11 +6,11 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
-import React, { type JSX, useEffect, useMemo } from "react";
+import React, { type JSX, useEffect } from "react";
import { logger } from "matrix-js-sdk/src/logger";
import { type IContent } from "matrix-js-sdk/src/matrix";
import { type MediaEventContent } from "matrix-js-sdk/src/types";
-import { AudioPlayerView } from "@element-hq/web-shared-components";
+import { AudioPlayerView, useCreateAutoDisposedViewModel } from "@element-hq/web-shared-components";
import { type Playback } from "../../../audio/Playback";
import InlineSpinner from "../elements/InlineSpinner";
@@ -132,13 +132,10 @@ interface AudioPlayerProps {
* AudioPlayer component that initializes the AudioPlayerViewModel and renders the AudioPlayerView.
*/
function AudioPlayer({ playback, mediaName }: AudioPlayerProps): JSX.Element {
- const vm = useMemo(() => new AudioPlayerViewModel({ playback, mediaName }), [playback, mediaName]);
-
+ const vm = useCreateAutoDisposedViewModel(() => new AudioPlayerViewModel({ playback, mediaName }));
useEffect(() => {
- return () => {
- vm.dispose();
- };
- }, [vm]);
+ vm.setProps({ playback, mediaName });
+ }, [playback, mediaName, vm]);
return ;
}
diff --git a/src/viewmodels/audio/AudioPlayerViewModel.ts b/src/viewmodels/audio/AudioPlayerViewModel.ts
index f0f5f87989..37588c5afd 100644
--- a/src/viewmodels/audio/AudioPlayerViewModel.ts
+++ b/src/viewmodels/audio/AudioPlayerViewModel.ts
@@ -141,4 +141,13 @@ export class AudioPlayerViewModel
public onSeekbarChange = async (ev: ChangeEvent): Promise => {
await this.props.playback.skipTo((Number(ev.target.value) / 100) * this.props.playback.durationSeconds);
};
+
+ /**
+ * Updates the properties of the view model and recomputes the snapshot.
+ * @param newProps
+ */
+ public setProps(newProps: Partial): void {
+ this.props = { ...this.props, ...newProps };
+ this.setSnapshot();
+ }
}
diff --git a/test/viewmodels/audio/AudioPlayerViewModel-test.tsx b/test/viewmodels/audio/AudioPlayerViewModel-test.tsx
index a6c4a04166..4fc10fe596 100644
--- a/test/viewmodels/audio/AudioPlayerViewModel-test.tsx
+++ b/test/viewmodels/audio/AudioPlayerViewModel-test.tsx
@@ -64,4 +64,12 @@ describe("AudioPlayerViewModel", () => {
vm.onKeyDown(event);
expect(playback.skipTo).toHaveBeenCalledWith(10 + 5); // 5 seconds forward
});
+
+ it("should update snapshot when setProps is called with new mediaName", () => {
+ const vm = new AudioPlayerViewModel({ playback, mediaName: "oldName" });
+ expect(vm.getSnapshot().mediaName).toBe("oldName");
+
+ vm.setProps({ mediaName: "newName" });
+ expect(vm.getSnapshot().mediaName).toBe("newName");
+ });
});