mirror of
https://github.com/vector-im/element-call.git
synced 2026-03-28 06:50:26 +00:00
Merge branch 'livekit' into toger5/test-with-new-membershipmanager
This commit is contained in:
17
.github/workflows/blocked.yaml
vendored
Normal file
17
.github/workflows/blocked.yaml
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
name: Prevent blocked
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, labeled, unlabeled]
|
||||
jobs:
|
||||
prevent-blocked:
|
||||
name: Prevent blocked
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: read
|
||||
steps:
|
||||
- name: Add notice
|
||||
uses: actions/github-script@v7
|
||||
if: contains(github.event.pull_request.labels.*.name, 'X-Blocked')
|
||||
with:
|
||||
script: |
|
||||
core.setFailed("PR has been labeled with X-Blocked; it cannot be merged.");
|
||||
@@ -8,26 +8,26 @@
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, maximum-scale=1.0"
|
||||
/>
|
||||
<title><%- title %></title>
|
||||
<title><%- brand %></title>
|
||||
<script>
|
||||
window.global = window;
|
||||
</script>
|
||||
|
||||
<!-- Open graph meta tags -->
|
||||
|
||||
<meta property="og:title" content="<%- title %>" />
|
||||
<meta property="og:title" content="<%- brand %>" />
|
||||
<meta
|
||||
property="og:description"
|
||||
content="You're invited to join a call on Element Call"
|
||||
content="You're invited to join a call on <%- brand %>"
|
||||
/>
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:image" content="favicon.png" />
|
||||
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:title" content="<%- title %>" />
|
||||
<meta name="twitter:title" content="<%- brand %>" />
|
||||
<meta
|
||||
name="twitter:description"
|
||||
content="You're invited to join a call on Element Call"
|
||||
content="You're invited to join a call on <%- brand %>"
|
||||
/>
|
||||
<meta name="twitter:image" content="favicon.png" />
|
||||
</head>
|
||||
|
||||
@@ -110,8 +110,8 @@ describe("UrlParams", () => {
|
||||
});
|
||||
|
||||
describe("returnToLobby", () => {
|
||||
it("is true in SPA mode", () => {
|
||||
expect(getUrlParams("?returnToLobby=false").returnToLobby).toBe(true);
|
||||
it("is false in SPA mode", () => {
|
||||
expect(getUrlParams("?returnToLobby=true").returnToLobby).toBe(false);
|
||||
});
|
||||
|
||||
it("defaults to false in widget mode", () => {
|
||||
|
||||
@@ -264,7 +264,9 @@ export const getUrlParams = (
|
||||
"skipLobby",
|
||||
isWidget && intent === UserIntent.StartNewCall,
|
||||
),
|
||||
returnToLobby: isWidget ? parser.getFlagParam("returnToLobby") : true,
|
||||
// In SPA mode the user should always exit to the home screen when hanging
|
||||
// up, rather than being sent back to the lobby
|
||||
returnToLobby: isWidget ? parser.getFlagParam("returnToLobby") : false,
|
||||
theme: parser.getParam("theme"),
|
||||
viaServers: !isWidget ? parser.getParam("viaServers") : null,
|
||||
homeserver: !isWidget ? parser.getParam("homeserver") : null,
|
||||
|
||||
@@ -539,9 +539,7 @@ export const GroupCallView: FC<Props> = ({
|
||||
}
|
||||
} else if (left && widget !== null) {
|
||||
// Left in widget mode:
|
||||
if (!returnToLobby) {
|
||||
body = null;
|
||||
}
|
||||
body = returnToLobby ? lobbyView : null;
|
||||
} else if (preload || skipLobby) {
|
||||
body = null;
|
||||
} else {
|
||||
|
||||
@@ -6,7 +6,7 @@ Please see LICENSE in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { type MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession";
|
||||
import { expect, test, vi } from "vitest";
|
||||
import { expect, onTestFinished, test, vi } from "vitest";
|
||||
import { AutoDiscovery } from "matrix-js-sdk/src/autodiscovery";
|
||||
import EventEmitter from "events";
|
||||
|
||||
@@ -15,11 +15,17 @@ import { mockConfig } from "./utils/test";
|
||||
import { ElementWidgetActions, widget } from "./widget";
|
||||
import { ErrorCode } from "./utils/errors.ts";
|
||||
|
||||
const getUrlParams = vi.hoisted(() => vi.fn(() => ({})));
|
||||
vi.mock("./UrlParams", () => ({ getUrlParams }));
|
||||
|
||||
const actualWidget = await vi.hoisted(async () => vi.importActual("./widget"));
|
||||
vi.mock("./widget", () => ({
|
||||
...actualWidget,
|
||||
widget: {
|
||||
api: { transport: { send: vi.fn(), reply: vi.fn(), stop: vi.fn() } },
|
||||
api: {
|
||||
setAlwaysOnScreen: (): void => {},
|
||||
transport: { send: vi.fn(), reply: vi.fn(), stop: vi.fn() },
|
||||
},
|
||||
lazyActions: new EventEmitter(),
|
||||
},
|
||||
}));
|
||||
@@ -110,34 +116,45 @@ test("It joins the correct Session", async () => {
|
||||
);
|
||||
});
|
||||
|
||||
test("leaveRTCSession closes the widget on a normal hangup", async () => {
|
||||
async function testLeaveRTCSession(
|
||||
cause: "user" | "error",
|
||||
expectClose: boolean,
|
||||
): Promise<void> {
|
||||
vi.clearAllMocks();
|
||||
const session = { leaveRoomSession: vi.fn() } as unknown as MatrixRTCSession;
|
||||
await leaveRTCSession(session, "user");
|
||||
await leaveRTCSession(session, cause);
|
||||
expect(session.leaveRoomSession).toHaveBeenCalled();
|
||||
expect(widget!.api.transport.send).toHaveBeenCalledWith(
|
||||
ElementWidgetActions.HangupCall,
|
||||
expect.anything(),
|
||||
);
|
||||
expect(widget!.api.transport.send).toHaveBeenCalledWith(
|
||||
ElementWidgetActions.Close,
|
||||
expect.anything(),
|
||||
);
|
||||
if (expectClose) {
|
||||
expect(widget!.api.transport.send).toHaveBeenCalledWith(
|
||||
ElementWidgetActions.Close,
|
||||
expect.anything(),
|
||||
);
|
||||
expect(widget!.api.transport.stop).toHaveBeenCalled();
|
||||
} else {
|
||||
expect(widget!.api.transport.send).not.toHaveBeenCalledWith(
|
||||
ElementWidgetActions.Close,
|
||||
expect.anything(),
|
||||
);
|
||||
expect(widget!.api.transport.stop).not.toHaveBeenCalled();
|
||||
}
|
||||
}
|
||||
|
||||
test("leaveRTCSession closes the widget on a normal hangup", async () => {
|
||||
await testLeaveRTCSession("user", true);
|
||||
});
|
||||
|
||||
test("leaveRTCSession doesn't close the widget on a fatal error", async () => {
|
||||
vi.clearAllMocks();
|
||||
const session = { leaveRoomSession: vi.fn() } as unknown as MatrixRTCSession;
|
||||
await leaveRTCSession(session, "error");
|
||||
expect(session.leaveRoomSession).toHaveBeenCalled();
|
||||
expect(widget!.api.transport.send).toHaveBeenCalledWith(
|
||||
ElementWidgetActions.HangupCall,
|
||||
expect.anything(),
|
||||
);
|
||||
expect(widget!.api.transport.send).not.toHaveBeenCalledWith(
|
||||
ElementWidgetActions.Close,
|
||||
expect.anything(),
|
||||
);
|
||||
await testLeaveRTCSession("error", false);
|
||||
});
|
||||
|
||||
test("leaveRTCSession doesn't close the widget when returning to lobby", async () => {
|
||||
getUrlParams.mockReturnValue({ returnToLobby: true });
|
||||
onTestFinished(() => void getUrlParams.mockReset());
|
||||
await testLeaveRTCSession("user", false);
|
||||
});
|
||||
|
||||
test("It fails with configuration error if no live kit url config is set in fallback", async () => {
|
||||
|
||||
@@ -19,6 +19,7 @@ import { PosthogAnalytics } from "./analytics/PosthogAnalytics";
|
||||
import { Config } from "./config/Config";
|
||||
import { ElementWidgetActions, widget, type WidgetHelpers } from "./widget";
|
||||
import { MatrixRTCFocusMissingError } from "./utils/errors.ts";
|
||||
import { getUrlParams } from "./UrlParams.ts";
|
||||
|
||||
const FOCI_WK_KEY = "org.matrix.msc4143.rtc_foci";
|
||||
|
||||
@@ -126,6 +127,13 @@ export async function enterRTCSession(
|
||||
makeKeyDelay: matrixRtcSessionConfig?.key_rotation_on_leave_delay,
|
||||
},
|
||||
);
|
||||
if (widget) {
|
||||
try {
|
||||
await widget.api.transport.send(ElementWidgetActions.JoinCall, {});
|
||||
} catch (e) {
|
||||
logger.error("Failed to send join action", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const widgetPostHangupProcedure = async (
|
||||
@@ -151,7 +159,7 @@ const widgetPostHangupProcedure = async (
|
||||
}
|
||||
// On a normal user hangup we can shut down and close the widget. But if an
|
||||
// error occurs we should keep the widget open until the user reads it.
|
||||
if (cause === "user") {
|
||||
if (cause === "user" && !getUrlParams().returnToLobby) {
|
||||
try {
|
||||
await widget.api.transport.send(ElementWidgetActions.Close, {});
|
||||
} catch (e) {
|
||||
|
||||
@@ -496,6 +496,10 @@ export class CallViewModel extends ViewModel {
|
||||
}
|
||||
return displaynameMap;
|
||||
}),
|
||||
// It turns out that doing the disambiguation above is rather expensive on Safari (10x slower
|
||||
// than on Chrome/Firefox). This means it is important that we share() the result so that we
|
||||
// don't do this work more times than we need to. This is achieve through the state() operator:
|
||||
this.scope.state(),
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,7 +29,7 @@ export default defineConfig(({ mode }) => {
|
||||
}),
|
||||
htmlTemplate.default({
|
||||
data: {
|
||||
title: env.VITE_PRODUCT_NAME || "Element Call",
|
||||
brand: env.VITE_PRODUCT_NAME || "Element Call",
|
||||
},
|
||||
}),
|
||||
|
||||
|
||||
Reference in New Issue
Block a user