+ { seekBackwardButton }
{ control }
+ { seekForwardButton }
diff --git a/src/voice-broadcast/hooks/useVoiceBroadcastPlayback.ts b/src/voice-broadcast/hooks/useVoiceBroadcastPlayback.ts
index 67b0cb8875..1828b31d01 100644
--- a/src/voice-broadcast/hooks/useVoiceBroadcastPlayback.ts
+++ b/src/voice-broadcast/hooks/useVoiceBroadcastPlayback.ts
@@ -47,6 +47,13 @@ export const useVoiceBroadcastPlayback = (playback: VoiceBroadcastPlayback) => {
d => setDuration(d / 1000),
);
+ const [position, setPosition] = useState(playback.timeSeconds);
+ useTypedEventEmitter(
+ playback,
+ VoiceBroadcastPlaybackEvent.PositionChanged,
+ p => setPosition(p / 1000),
+ );
+
const [liveness, setLiveness] = useState(playback.getLiveness());
useTypedEventEmitter(
playback,
@@ -57,9 +64,10 @@ export const useVoiceBroadcastPlayback = (playback: VoiceBroadcastPlayback) => {
return {
duration,
liveness: liveness,
+ playbackState,
+ position,
room: room,
sender: playback.infoEvent.sender,
toggle: playbackToggle,
- playbackState,
};
};
diff --git a/test/voice-broadcast/components/molecules/VoiceBroadcastPlaybackBody-test.tsx b/test/voice-broadcast/components/molecules/VoiceBroadcastPlaybackBody-test.tsx
index f7848e74c8..a2e95a856e 100644
--- a/test/voice-broadcast/components/molecules/VoiceBroadcastPlaybackBody-test.tsx
+++ b/test/voice-broadcast/components/molecules/VoiceBroadcastPlaybackBody-test.tsx
@@ -16,7 +16,7 @@ limitations under the License.
import React from "react";
import { MatrixClient, MatrixEvent } from "matrix-js-sdk/src/matrix";
-import { act, render, RenderResult } from "@testing-library/react";
+import { act, render, RenderResult, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { mocked } from "jest-mock";
@@ -54,7 +54,7 @@ describe("VoiceBroadcastPlaybackBody", () => {
infoEvent = mkVoiceBroadcastInfoStateEvent(
roomId,
- VoiceBroadcastInfoState.Started,
+ VoiceBroadcastInfoState.Stopped,
userId,
client.getDeviceId(),
);
@@ -65,6 +65,7 @@ describe("VoiceBroadcastPlaybackBody", () => {
jest.spyOn(playback, "toggle").mockImplementation(() => Promise.resolve());
jest.spyOn(playback, "getLiveness");
jest.spyOn(playback, "getState");
+ jest.spyOn(playback, "skipTo");
jest.spyOn(playback, "durationSeconds", "get").mockReturnValue(23 * 60 + 42); // 23:42
});
@@ -80,6 +81,50 @@ describe("VoiceBroadcastPlaybackBody", () => {
});
});
+ describe("when rendering a playing broadcast", () => {
+ beforeEach(() => {
+ mocked(playback.getState).mockReturnValue(VoiceBroadcastPlaybackState.Playing);
+ mocked(playback.getLiveness).mockReturnValue("not-live");
+ renderResult = render(
);
+ });
+
+ it("should render as expected", () => {
+ expect(renderResult.container).toMatchSnapshot();
+ });
+
+ describe("and being in the middle of the playback", () => {
+ beforeEach(() => {
+ act(() => {
+ playback.emit(VoiceBroadcastPlaybackEvent.PositionChanged, 10 * 60 * 1000); // 10:00
+ });
+ });
+
+ describe("and clicking 30s backward", () => {
+ beforeEach(async () => {
+ await act(async () => {
+ await userEvent.click(screen.getByLabelText("30s backward"));
+ });
+ });
+
+ it("should seek 30s backward", () => {
+ expect(playback.skipTo).toHaveBeenCalledWith(9 * 60 + 30);
+ });
+ });
+
+ describe("and clicking 30s forward", () => {
+ beforeEach(async () => {
+ await act(async () => {
+ await userEvent.click(screen.getByLabelText("30s forward"));
+ });
+ });
+
+ it("should seek 30s forward", () => {
+ expect(playback.skipTo).toHaveBeenCalledWith(10 * 60 + 30);
+ });
+ });
+ });
+ });
+
describe(`when rendering a stopped broadcast`, () => {
beforeEach(() => {
mocked(playback.getState).mockReturnValue(VoiceBroadcastPlaybackState.Stopped);
@@ -87,6 +132,10 @@ describe("VoiceBroadcastPlaybackBody", () => {
renderResult = render(
);
});
+ it("should render as expected", () => {
+ expect(renderResult.container).toMatchSnapshot();
+ });
+
describe("and clicking the play button", () => {
beforeEach(async () => {
await userEvent.click(renderResult.getByLabelText("play voice broadcast"));
@@ -104,8 +153,8 @@ describe("VoiceBroadcastPlaybackBody", () => {
});
});
- it("should render as expected", () => {
- expect(renderResult.container).toMatchSnapshot();
+ it("should render the new length", async () => {
+ expect(await screen.findByText("00:42")).toBeInTheDocument();
});
});
});
diff --git a/test/voice-broadcast/components/molecules/__snapshots__/VoiceBroadcastPlaybackBody-test.tsx.snap b/test/voice-broadcast/components/molecules/__snapshots__/VoiceBroadcastPlaybackBody-test.tsx.snap
index 5ec5ca56e3..71275fda51 100644
--- a/test/voice-broadcast/components/molecules/__snapshots__/VoiceBroadcastPlaybackBody-test.tsx.snap
+++ b/test/voice-broadcast/components/molecules/__snapshots__/VoiceBroadcastPlaybackBody-test.tsx.snap
@@ -45,6 +45,16 @@ exports[`VoiceBroadcastPlaybackBody when rendering a 0/not-live broadcast should
+