Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 33 additions & 6 deletions playwright/e2e/voip/element-call.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ function assertCommonCallParameters(
expect(hash.get("deviceId")).toEqual(user.deviceId);
expect(hash.get("roomId")).toEqual(room.roomId);
expect(hash.get("preload")).toEqual("false");

expect(hash.get("returnToLobby")).toEqual("false");
}

async function sendRTCState(bot: Bot, roomId: string, notification?: "ring" | "notification") {
Expand Down Expand Up @@ -125,7 +123,7 @@ test.describe("Element Call", () => {
const hash = new URLSearchParams(url.hash.slice(1));
assertCommonCallParameters(url.searchParams, hash, user, room);
expect(hash.get("intent")).toEqual("start_call");
expect(hash.get("skipLobby")).toEqual("false");
expect(hash.get("skipLobby")).toEqual(null);
});

test("should be able to skip lobby by holding down shift", async ({ page, user, bot, room, app }) => {
Expand Down Expand Up @@ -165,7 +163,7 @@ test.describe("Element Call", () => {
assertCommonCallParameters(url.searchParams, hash, user, room);

expect(hash.get("intent")).toEqual("join_existing");
expect(hash.get("skipLobby")).toEqual("false");
expect(hash.get("skipLobby")).toEqual(null);
});

[true, false].forEach((skipLobbyToggle) => {
Expand Down Expand Up @@ -232,7 +230,7 @@ test.describe("Element Call", () => {
const hash = new URLSearchParams(url.hash.slice(1));
assertCommonCallParameters(url.searchParams, hash, user, room);
expect(hash.get("intent")).toEqual("start_call_dm");
expect(hash.get("skipLobby")).toEqual("false");
expect(hash.get("skipLobby")).toEqual(null);
});

test("should be able to skip lobby by holding down shift", async ({ page, user, room, app }) => {
Expand Down Expand Up @@ -271,7 +269,7 @@ test.describe("Element Call", () => {
assertCommonCallParameters(url.searchParams, hash, user, room);

expect(hash.get("intent")).toEqual("join_existing_dm");
expect(hash.get("skipLobby")).toEqual("false");
expect(hash.get("skipLobby")).toEqual(null);
});

[true, false].forEach((skipLobbyToggle) => {
Expand Down Expand Up @@ -309,4 +307,33 @@ test.describe("Element Call", () => {
);
});
});

test.describe("Video Rooms", () => {
test.use({
config: {
features: {
feature_video_rooms: true,
feature_element_call_video_rooms: true,
},
},
});
test("should be able to create and join a video room", async ({ page, user }) => {
await page.getByRole("navigation", { name: "Room list" }).getByRole("button", { name: "Add" }).click();
await page.getByRole("menuitem", { name: "New video room" }).click();
await page.getByRole("textbox", { name: "Name" }).fill("Test room");
await page.getByRole("button", { name: "Create video room" }).click();
await expect(page).toHaveURL(new RegExp(`/#/room/`));
const roomId = new URL(page.url()).hash.slice("#/room/".length);

const frameUrlStr = await page.locator("iframe").getAttribute("src");
await expect(frameUrlStr).toBeDefined();
// Ensure we set the correct parameters for ECall.
const url = new URL(frameUrlStr);
const hash = new URLSearchParams(url.hash.slice(1));
assertCommonCallParameters(url.searchParams, hash, user, { roomId });
expect(hash.get("intent")).toEqual("join_existing");
expect(hash.get("skipLobby")).toEqual("false");
expect(hash.get("returnToLobby")).toEqual("true");
});
});
});
1 change: 0 additions & 1 deletion src/components/structures/RoomView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2609,7 +2609,6 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
<CallView
room={this.state.room}
resizing={this.state.resizing}
skipLobby={this.context.roomViewStore.skipCallLobby() ?? false}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

skipLobby is now a parameter on ElementCall.start, so it doesn't need to appear in any of the views :- all entrypoints eventually call the same logic in RoomViewStore

role="main"
onClose={this.onCallClose}
/>
Expand Down
2 changes: 1 addition & 1 deletion src/components/views/beacon/RoomCallBanner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const RoomCallBannerInner: React.FC<RoomCallBannerProps> = ({ roomId, call }) =>
action: Action.ViewRoom,
room_id: roomId,
view_call: true,
skipLobby: "shiftKey" in ev ? ev.shiftKey : false,
skipLobby: ("shiftKey" in ev && ev.shiftKey) || undefined,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Critically this means we only skipLobby when shiftKey is held, otherwise we follow defaults.

metricsTrigger: undefined,
});
},
Expand Down
25 changes: 3 additions & 22 deletions src/components/views/voip/CallView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,11 @@ interface JoinCallViewProps {
room: Room;
resizing: boolean;
call: Call;
skipLobby?: boolean;
role?: AriaRole;
onClose: () => void;
}

const JoinCallView: FC<JoinCallViewProps> = ({ room, resizing, call, skipLobby, role, onClose }) => {
const JoinCallView: FC<JoinCallViewProps> = ({ room, resizing, call, role, onClose }) => {
const cli = useContext(MatrixClientContext);
useTypedEventEmitter(call, CallEvent.Close, onClose);

Expand All @@ -35,12 +34,6 @@ const JoinCallView: FC<JoinCallViewProps> = ({ room, resizing, call, skipLobby,
call.clean();
}, [call]);

useEffect(() => {
// Always update the widget data so that we don't ignore "skipLobby" accidentally.
call.widget.data ??= {};
call.widget.data.skipLobby = skipLobby;
}, [call.widget, skipLobby]);

const disconnectAllOtherCalls: () => Promise<void> = useCallback(async () => {
// The stickyPromise has to resolve before the widget actually becomes sticky.
// We only let the widget become sticky after disconnecting all other active calls.
Expand Down Expand Up @@ -69,27 +62,15 @@ const JoinCallView: FC<JoinCallViewProps> = ({ room, resizing, call, skipLobby,
interface CallViewProps {
room: Room;
resizing: boolean;
skipLobby?: boolean;
role?: AriaRole;
/**
* Callback for when the user closes the call.
*/
onClose: () => void;
}

export const CallView: FC<CallViewProps> = ({ room, resizing, skipLobby, role, onClose }) => {
export const CallView: FC<CallViewProps> = ({ room, resizing, role, onClose }) => {
const call = useCall(room.roomId);

return (
call && (
<JoinCallView
room={room}
resizing={resizing}
call={call}
skipLobby={skipLobby}
role={role}
onClose={onClose}
/>
)
);
return call && <JoinCallView room={room} resizing={resizing} call={call} role={role} onClose={onClose} />;
};
6 changes: 4 additions & 2 deletions src/hooks/room/useRoomCall.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ export const useRoomCall = (
if (widget && promptPinWidget) {
WidgetLayoutStore.instance.moveToContainer(room, widget, Container.Top);
} else {
placeCall(room, CallType.Voice, callPlatformType, evt?.shiftKey ?? false);
placeCall(room, CallType.Voice, callPlatformType, evt?.shiftKey || undefined);
}
},
[promptPinWidget, room, widget],
Expand All @@ -240,7 +240,9 @@ export const useRoomCall = (
if (widget && promptPinWidget) {
WidgetLayoutStore.instance.moveToContainer(room, widget, Container.Top);
} else {
placeCall(room, CallType.Video, callPlatformType, evt?.shiftKey ?? false);
// If we have pressed shift then always skip the lobby, otherwise `undefined` will defer
// to the defaults of the call implementation.
placeCall(room, CallType.Video, callPlatformType, evt?.shiftKey || undefined);
}
},
[widget, promptPinWidget, room],
Expand Down
Loading
Loading