diff --git a/e2e/page-objects/calls-page.po.ts b/e2e/page-objects/calls-page.po.ts
index d36df5c9..ef871bf9 100644
--- a/e2e/page-objects/calls-page.po.ts
+++ b/e2e/page-objects/calls-page.po.ts
@@ -13,7 +13,7 @@ export class CallsPagePO {
}
async gotoWithParams(productionId: string, lineId: string) {
- await this.page.goto(`/lines?lines=${productionId}:${lineId}`);
+ await this.page.goto(`/calls?lines=${productionId}:${lineId}`);
}
async gotoWithSettings(
@@ -30,6 +30,6 @@ export class CallsPagePO {
},
{ username }
);
- await this.page.goto(`/lines?lines=${productionId}:${lineId}`);
+ await this.page.goto(`/calls?lines=${productionId}:${lineId}`);
}
}
diff --git a/e2e/tests/calls-page.spec.ts b/e2e/tests/calls-page.spec.ts
index 63ef1fa4..e78373d3 100644
--- a/e2e/tests/calls-page.spec.ts
+++ b/e2e/tests/calls-page.spec.ts
@@ -7,7 +7,7 @@ test.describe("Calls Page", () => {
callsPage,
}) => {
await callsPage.gotoWithParams("1", "10");
- await expect(callsPage.page).toHaveURL(/\/lines\?lines=1:10/);
+ await expect(callsPage.page).toHaveURL(/\/calls\?lines=1:10/);
});
test("shows join form when no username is set", async ({ callsPage }) => {
@@ -17,11 +17,11 @@ test.describe("Calls Page", () => {
).toBeVisible();
});
- test("shows Lines header after joining with username", async ({
+ test("shows Calls header after joining with username", async ({
callsPage,
}) => {
await callsPage.gotoWithSettings("1", "10");
- await expect(callsPage.page.getByText("Lines").first()).toBeVisible();
+ await expect(callsPage.page.getByText("Calls").first()).toBeVisible();
});
test("shows Save as Configuration button when not on mobile", async ({
@@ -57,7 +57,7 @@ test.describe("Calls Page", () => {
test("invalid line in URL is removed silently", async ({ callsPage }) => {
// Line 99 does not exist; only line 10 should remain
- await callsPage.page.goto("/lines?lines=1:10,1:99");
+ await callsPage.page.goto("/calls?lines=1:10,1:99");
await expect(callsPage.page).toHaveURL(/lines=1:10/);
await expect(callsPage.page).not.toHaveURL(/1:99/);
});
diff --git a/e2e/tests/landing-page.spec.ts b/e2e/tests/landing-page.spec.ts
index 72039191..39e8d6c4 100644
--- a/e2e/tests/landing-page.spec.ts
+++ b/e2e/tests/landing-page.spec.ts
@@ -98,6 +98,6 @@ test.describe("Landing Page", () => {
.getByText("Quick Join Preset")
.locator("..");
await presetCard.getByRole("button", { name: /^join$/i }).click();
- await expect(landingPage.page).toHaveURL(/\/lines\?lines=1:10/);
+ await expect(landingPage.page).toHaveURL(/\/calls\?lines=1:10/);
});
});
diff --git a/e2e/tests/share-and-modals.spec.ts b/e2e/tests/share-and-modals.spec.ts
index f48d3192..d5ed9dd0 100644
--- a/e2e/tests/share-and-modals.spec.ts
+++ b/e2e/tests/share-and-modals.spec.ts
@@ -8,7 +8,7 @@ test.describe("Share Link Modal", () => {
await landingPage.page.getByTitle("Get share link").first().click();
// Share modal should appear
- await expect(landingPage.page.getByText("Share Lines")).toBeVisible();
+ await expect(landingPage.page.getByText("Share Calls")).toBeVisible();
});
test("share modal shows note about single use links", async ({
diff --git a/src/App.tsx b/src/App.tsx
index cb45cbff..264e07f1 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,6 +1,12 @@
import styled from "@emotion/styled";
import { useEffect, useState } from "react";
-import { BrowserRouter, Routes, Route } from "react-router";
+import {
+ BrowserRouter,
+ Routes,
+ Route,
+ Navigate,
+ useLocation,
+} from "react-router";
import { ErrorPage } from "./components/router-error.tsx";
import { useDevicePermissions } from "./hooks/use-device-permission.ts";
import { LandingPage } from "./components/landing-page/landing-page.tsx";
@@ -36,6 +42,11 @@ const ButtonWrapper = styled.div`
display: inline-block;
`;
+const LinesToCallsRedirect = () => {
+ const { search } = useLocation();
+ return ;
+};
+
const NotFound = () => {
return (
@@ -166,10 +177,11 @@ const AppContent = ({
errorElement={}
/>
}
errorElement={}
/>
+ } />
} />
>
diff --git a/src/components/calls-page/calls-page.tsx b/src/components/calls-page/calls-page.tsx
index a24d9685..fad32c05 100644
--- a/src/components/calls-page/calls-page.tsx
+++ b/src/components/calls-page/calls-page.tsx
@@ -450,7 +450,7 @@ export const CallsPage = () => {
setShowSettings(!showSettings)} />
)}
@@ -477,8 +477,8 @@ export const CallsPage = () => {
{confirmExitModalOpen && (
setConfirmExitModalOpen(false)}
onConfirm={runExitAllCalls}
/>
diff --git a/src/components/calls-page/header-actions.tsx b/src/components/calls-page/header-actions.tsx
index 7e71edc2..6bf31e9c 100644
--- a/src/components/calls-page/header-actions.tsx
+++ b/src/components/calls-page/header-actions.tsx
@@ -146,7 +146,7 @@ export const HeaderActions = ({
type="button"
onClick={() => setAddCallActive(!addCallActive)}
>
- Add Line
+ Add Call
)}
diff --git a/src/components/calls-page/use-calls-navigation.test.ts b/src/components/calls-page/use-calls-navigation.test.ts
index 38720304..590f596f 100644
--- a/src/components/calls-page/use-calls-navigation.test.ts
+++ b/src/components/calls-page/use-calls-navigation.test.ts
@@ -18,7 +18,7 @@ describe("useCallsNavigation", () => {
mockNavigate.mockReset();
mockSearchParams = new URLSearchParams();
Object.defineProperty(window, "location", {
- value: { pathname: "/lines", search: "" },
+ value: { pathname: "/calls", search: "" },
writable: true,
});
});
@@ -29,7 +29,7 @@ describe("useCallsNavigation", () => {
// a pending program card that has not yet appeared in the URL).
mockSearchParams = new URLSearchParams("lines=1:10");
Object.defineProperty(window, "location", {
- value: { pathname: "/lines", search: "?lines=1:10" },
+ value: { pathname: "/calls", search: "?lines=1:10" },
writable: true,
});
@@ -64,7 +64,7 @@ describe("useCallsNavigation", () => {
it("does not change the URL when a program line ref has joined and is no longer pending", async () => {
mockSearchParams = new URLSearchParams("lines=1:10,1:20");
Object.defineProperty(window, "location", {
- value: { pathname: "/lines", search: "?lines=1:10,1:20" },
+ value: { pathname: "/calls", search: "?lines=1:10,1:20" },
writable: true,
});
@@ -98,7 +98,7 @@ describe("useCallsNavigation", () => {
// Original URL only had line 10
mockSearchParams = new URLSearchParams("lines=1:10");
Object.defineProperty(window, "location", {
- value: { pathname: "/lines", search: "?lines=1:10" },
+ value: { pathname: "/calls", search: "?lines=1:10" },
writable: true,
});
@@ -140,7 +140,7 @@ describe("useCallsNavigation", () => {
// window.location already contains the companion param — the source of truth
Object.defineProperty(window, "location", {
value: {
- pathname: "/lines",
+ pathname: "/calls",
search: "?lines=1:10&companion=localhost:9000",
},
writable: true,
@@ -180,7 +180,7 @@ describe("useCallsNavigation", () => {
mockSearchParams = new URLSearchParams("lines=1:10"); // stale — no companion yet
Object.defineProperty(window, "location", {
value: {
- pathname: "/lines",
+ pathname: "/calls",
search: "?lines=1:10&companion=host:9000",
},
writable: true,
@@ -232,7 +232,7 @@ describe("useCallsNavigation", () => {
// Mock window.location so the hook's guard detects no change
Object.defineProperty(window, "location", {
- value: { pathname: "/lines", search: "?lines=1:10" },
+ value: { pathname: "/calls", search: "?lines=1:10" },
writable: true,
});
diff --git a/src/components/generate-urls/share-line-link/share-line-link-modal.tsx b/src/components/generate-urls/share-line-link/share-line-link-modal.tsx
index 822a516a..40dde9b1 100644
--- a/src/components/generate-urls/share-line-link/share-line-link-modal.tsx
+++ b/src/components/generate-urls/share-line-link/share-line-link-modal.tsx
@@ -204,12 +204,12 @@ export const ShareLineLinkModal = ({
return (
{isCopyProduction
- ? "Share these links to invite others to each line."
- : "Anyone with this link can join the line."}
+ ? "Share these links to invite others to each call."
+ : "Anyone with this link can join the call."}
Each link can only be used once. A fresh link is generated automatically
diff --git a/src/components/landing-page/join-production.tsx b/src/components/landing-page/join-production.tsx
index ef93a24c..2431b0d4 100644
--- a/src/components/landing-page/join-production.tsx
+++ b/src/components/landing-page/join-production.tsx
@@ -69,7 +69,7 @@ export const JoinProduction = ({
className={`${isMobile ? "" : "desktop"} ${className}`}
>
- Join Production
+ Join Call
{closeAddCallView && (
closeAddCallView()}>
diff --git a/src/components/production-line/exit-call-button.tsx b/src/components/production-line/exit-call-button.tsx
index bae1d581..e57ba39a 100644
--- a/src/components/production-line/exit-call-button.tsx
+++ b/src/components/production-line/exit-call-button.tsx
@@ -40,7 +40,7 @@ export const ExitCallButton = ({
title="Exit line"
onClick={() => resetOnExit()}
>
- Leave Line
+ Leave Call
);
diff --git a/src/components/production-line/settings-modal.tsx b/src/components/production-line/settings-modal.tsx
index a66505b2..6a8a9cc8 100644
--- a/src/components/production-line/settings-modal.tsx
+++ b/src/components/production-line/settings-modal.tsx
@@ -106,7 +106,7 @@ export const SettingsModal = ({
: false;
if (isGlobalStateDuplicate) {
- acc[field] = "This key is used in another connected line.";
+ acc[field] = "This key is used in another connected call.";
} else {
acc[field] = "";
}
@@ -224,7 +224,7 @@ export const SettingsModal = ({
return (
diff --git a/src/utils/call-url.test.ts b/src/utils/call-url.test.ts
index 94784c4e..04932d45 100644
--- a/src/utils/call-url.test.ts
+++ b/src/utils/call-url.test.ts
@@ -7,17 +7,17 @@ import {
} from "./call-url";
describe("buildCallsUrl", () => {
- it("returns /lines when given an empty list", () => {
- expect(buildCallsUrl([])).toBe("/lines");
+ it("returns /calls when given an empty list", () => {
+ expect(buildCallsUrl([])).toBe("/calls");
});
- it("produces the /lines?lines=prodId:lineId format for a single call", () => {
+ it("produces the /calls?lines=prodId:lineId format for a single call", () => {
// Regression: use-navigate-to-production previously navigated to the old
// /production-calls/production/:id/line/:id URL. This assertion locks in
// the correct target URL that buildCallsUrl must produce so that the landing
// page join lands directly on the right route without a flash redirect.
expect(buildCallsUrl([{ productionId: "prod-1", lineId: "line-2" }])).toBe(
- "/lines?lines=prod-1:line-2"
+ "/calls?lines=prod-1:line-2"
);
});
@@ -27,7 +27,7 @@ describe("buildCallsUrl", () => {
{ productionId: "p1", lineId: "l1" },
{ productionId: "p2", lineId: "l2" },
])
- ).toBe("/lines?lines=p1:l1,p2:l2");
+ ).toBe("/calls?lines=p1:l1,p2:l2");
});
});
@@ -94,7 +94,7 @@ describe("buildCallsUrl — companion URL", () => {
[{ productionId: "p1", lineId: "l1" }],
"ws://localhost:12345"
);
- expect(url).toBe("/lines?lines=p1:l1&companion=localhost:12345");
+ expect(url).toBe("/calls?lines=p1:l1&companion=localhost:12345");
});
it("strips wss:// prefix from companion URL", () => {
@@ -102,17 +102,17 @@ describe("buildCallsUrl — companion URL", () => {
[{ productionId: "p1", lineId: "l1" }],
"wss://example.com:9000"
);
- expect(url).toBe("/lines?lines=p1:l1&companion=example.com:9000");
+ expect(url).toBe("/calls?lines=p1:l1&companion=example.com:9000");
});
it("works with empty calls list and a companion URL", () => {
const url = buildCallsUrl([], "ws://localhost:12345");
- expect(url).toBe("/lines?companion=localhost:12345");
+ expect(url).toBe("/calls?companion=localhost:12345");
});
it("returns the base URL unchanged when companionUrl is undefined", () => {
expect(buildCallsUrl([{ productionId: "p1", lineId: "l1" }])).toBe(
- "/lines?lines=p1:l1"
+ "/calls?lines=p1:l1"
);
});
});
diff --git a/src/utils/call-url.ts b/src/utils/call-url.ts
index 592302cb..268087ff 100644
--- a/src/utils/call-url.ts
+++ b/src/utils/call-url.ts
@@ -32,7 +32,7 @@ export function decodeCallsParam(param: string | null): CallRef[] {
export function buildCallsUrl(calls: CallRef[], companionUrl?: string): string {
const base =
- calls.length === 0 ? "/lines" : `/lines?lines=${encodeCallsParam(calls)}`;
+ calls.length === 0 ? "/calls" : `/calls?lines=${encodeCallsParam(calls)}`;
let url = base;
if (companionUrl) {
const hostPort = companionUrl.replace(/^wss?:\/\//, "");