Fully remove walkie-talkie mode

This commit is contained in:
Robin
2023-09-18 11:06:06 -04:00
parent d1e5a3043f
commit 1e9e096356
11 changed files with 29 additions and 184 deletions

View File

@@ -43,10 +43,6 @@ interface UrlParams {
* Whether to hide the screen-sharing button.
*/
hideScreensharing: boolean;
/**
* Whether to start a walkie-talkie call instead of a video call.
*/
isPtt: boolean;
/**
* Whether to use end-to-end encryption.
*/
@@ -179,7 +175,6 @@ export const getUrlParams = (
preload: hasParam("preload"),
hideHeader: hasParam("hideHeader"),
hideScreensharing: hasParam("hideScreensharing"),
isPtt: hasParam("ptt"),
e2eEnabled: getParam("enableE2e") !== "false", // Defaults to true
userId: getParam("userId"),
displayName: getParam("displayName"),

View File

@@ -1,19 +0,0 @@
/*
Copyright 2022 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
.label {
margin-bottom: 0;
}

View File

@@ -1,85 +0,0 @@
/*
Copyright 2022 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import { FC } from "react";
import { Item } from "@react-stately/collections";
import { useTranslation } from "react-i18next";
import { Headline } from "../typography/Typography";
import { Button } from "../button";
import { PopoverMenuTrigger } from "../popover/PopoverMenu";
import { ReactComponent as VideoIcon } from "../icons/Video.svg";
import { ReactComponent as MicIcon } from "../icons/Mic.svg";
import { ReactComponent as CheckIcon } from "../icons/Check.svg";
import styles from "./CallTypeDropdown.module.css";
import commonStyles from "./common.module.css";
import menuStyles from "../Menu.module.css";
import { Menu } from "../Menu";
export enum CallType {
Video = "video",
Radio = "radio",
}
interface Props {
callType: CallType;
setCallType: (value: CallType) => void;
}
export const CallTypeDropdown: FC<Props> = ({ callType, setCallType }) => {
const { t } = useTranslation();
const onAction = (key: React.Key) => {
setCallType(key.toString() as CallType);
};
const onClose = () => {};
return (
<PopoverMenuTrigger placement="bottom">
<Button variant="dropdown" className={commonStyles.headline}>
<Headline className={styles.label}>
{callType === CallType.Video
? t("Video call")
: t("Walkie-talkie call")}
</Headline>
</Button>
{(props: JSX.IntrinsicAttributes) => (
<Menu
{...props}
label={t("Call type menu")}
onAction={onAction}
onClose={onClose}
>
<Item key={CallType.Video} textValue={t("Video call")}>
<VideoIcon />
<span>{t("Video call")}</span>
{callType === CallType.Video && (
<CheckIcon className={menuStyles.checkIcon} />
)}
</Item>
<Item key={CallType.Radio} textValue={t("Walkie-talkie call")}>
<MicIcon />
<span>{t("Walkie-talkie call")}</span>
{callType === CallType.Radio && (
<CheckIcon className={menuStyles.checkIcon} />
)}
</Item>
</Menu>
)}
</PopoverMenuTrigger>
);
};

View File

@@ -34,10 +34,7 @@ export function HomePage() {
return <ErrorView error={clientState.error} />;
} else {
return clientState.authenticated ? (
<RegisteredView
isPasswordlessUser={clientState.authenticated.isPasswordlessUser}
client={clientState.authenticated.client}
/>
<RegisteredView client={clientState.authenticated.client} />
) : (
<UnauthenticatedView />
);

View File

@@ -19,6 +19,7 @@ import { useHistory } from "react-router-dom";
import { MatrixClient } from "matrix-js-sdk/src/client";
import { randomString } from "matrix-js-sdk/src/randomstring";
import { useTranslation } from "react-i18next";
import { Heading } from "@vector-im/compound-web";
import {
createRoom,
@@ -35,9 +36,8 @@ import { CallList } from "./CallList";
import { UserMenuContainer } from "../UserMenuContainer";
import { useModalTriggerState } from "../Modal";
import { JoinExistingCallModal } from "./JoinExistingCallModal";
import { Caption, Title } from "../typography/Typography";
import { Caption } from "../typography/Typography";
import { Form } from "../form/Form";
import { CallType, CallTypeDropdown } from "./CallTypeDropdown";
import { useEnableE2EE, useOptInAnalytics } from "../settings/useSetting";
import { AnalyticsNotice } from "../analytics/AnalyticsNotice";
import { E2EEBanner } from "../E2EEBanner";
@@ -46,11 +46,9 @@ import { getRoomSharedKeyLocalStorageKey } from "../e2ee/sharedKeyManagement";
interface Props {
client: MatrixClient;
isPasswordlessUser: boolean;
}
export function RegisteredView({ client, isPasswordlessUser }: Props) {
const [callType, setCallType] = useState(CallType.Video);
export function RegisteredView({ client }: Props) {
const [loading, setLoading] = useState(false);
const [error, setError] = useState<Error>();
const [optInAnalytics] = useOptInAnalytics();
@@ -68,14 +66,13 @@ export function RegisteredView({ client, isPasswordlessUser }: Props) {
typeof roomNameData === "string"
? sanitiseRoomNameInput(roomNameData)
: "";
const ptt = callType === CallType.Radio;
async function submit() {
setError(undefined);
setLoading(true);
const roomId = (
await createRoom(client, roomName, ptt, e2eeEnabled ?? false)
await createRoom(client, roomName, e2eeEnabled ?? false)
)[1];
if (e2eeEnabled) {
@@ -101,7 +98,7 @@ export function RegisteredView({ client, isPasswordlessUser }: Props) {
}
});
},
[client, history, modalState, callType, e2eeEnabled]
[client, history, modalState, e2eeEnabled]
);
const recentRooms = useGroupCallRooms(client);
@@ -111,11 +108,6 @@ export function RegisteredView({ client, isPasswordlessUser }: Props) {
history.push(`/${existingAlias}`);
}, [history, existingAlias]);
const callNameLabel =
callType === CallType.Video
? t("Video call name")
: t("Walkie-talkie call name");
return (
<>
<Header>
@@ -129,14 +121,16 @@ export function RegisteredView({ client, isPasswordlessUser }: Props) {
<div className={commonStyles.container}>
<main className={commonStyles.main}>
<HeaderLogo className={commonStyles.logo} />
<CallTypeDropdown callType={callType} setCallType={setCallType} />
<Heading size="lg" weight="semibold">
{t("Start new call")}
</Heading>
<Form className={styles.form} onSubmit={onSubmit}>
<FieldRow className={styles.fieldRow}>
<InputField
id="callName"
name="callName"
label={callNameLabel}
placeholder={callNameLabel}
label={t("Name of call")}
placeholder={t("Name of call")}
type="text"
required
autoComplete="off"
@@ -166,12 +160,7 @@ export function RegisteredView({ client, isPasswordlessUser }: Props) {
)}
</Form>
{recentRooms.length > 0 && (
<>
<Title className={styles.recentCallsTitle}>
{t("Your recent calls")}
</Title>
<CallList rooms={recentRooms} client={client} />
</>
<CallList rooms={recentRooms} client={client} />
)}
</main>
</div>

View File

@@ -18,6 +18,7 @@ import { FC, useCallback, useState, FormEventHandler } from "react";
import { useHistory } from "react-router-dom";
import { randomString } from "matrix-js-sdk/src/randomstring";
import { Trans, useTranslation } from "react-i18next";
import { Heading } from "@vector-im/compound-web";
import { useClient } from "../ClientContext";
import { Header, HeaderLogo, LeftNav, RightNav } from "../Header";
@@ -35,7 +36,6 @@ import { JoinExistingCallModal } from "./JoinExistingCallModal";
import { useRecaptcha } from "../auth/useRecaptcha";
import { Body, Caption, Link } from "../typography/Typography";
import { Form } from "../form/Form";
import { CallType, CallTypeDropdown } from "./CallTypeDropdown";
import styles from "./UnauthenticatedView.module.css";
import commonStyles from "./common.module.css";
import { generateRandomName } from "../auth/generateRandomName";
@@ -48,7 +48,6 @@ import { setLocalStorageItem } from "../useLocalStorage";
export const UnauthenticatedView: FC = () => {
const { setClient } = useClient();
const [callType, setCallType] = useState(CallType.Video);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<Error>();
const [optInAnalytics] = useOptInAnalytics();
@@ -68,7 +67,6 @@ export const UnauthenticatedView: FC = () => {
const data = new FormData(e.target as HTMLFormElement);
const roomName = sanitiseRoomNameInput(data.get("callName") as string);
const displayName = data.get("displayName") as string;
const ptt = callType === CallType.Radio;
async function submit() {
setError(undefined);
@@ -86,7 +84,7 @@ export const UnauthenticatedView: FC = () => {
let roomId: string;
try {
roomId = (
await createRoom(client, roomName, ptt, e2eeEnabled ?? false)
await createRoom(client, roomName, e2eeEnabled ?? false)
)[1];
if (e2eeEnabled) {
@@ -133,23 +131,9 @@ export const UnauthenticatedView: FC = () => {
reset();
});
},
[
register,
reset,
execute,
history,
callType,
modalState,
setClient,
e2eeEnabled,
]
[register, reset, execute, history, modalState, setClient, e2eeEnabled]
);
const callNameLabel =
callType === CallType.Video
? t("Video call name")
: t("Walkie-talkie call name");
return (
<>
<Header>
@@ -163,14 +147,16 @@ export const UnauthenticatedView: FC = () => {
<div className={commonStyles.container}>
<main className={commonStyles.main}>
<HeaderLogo className={commonStyles.logo} />
<CallTypeDropdown callType={callType} setCallType={setCallType} />
<Heading size="lg" weight="semibold">
{t("Start new call")}
</Heading>
<Form className={styles.form} onSubmit={onSubmit}>
<FieldRow>
<InputField
id="callName"
name="callName"
label={callNameLabel}
placeholder={callNameLabel}
label={t("Name of call")}
placeholder={t("Name of call")}
type="text"
required
autoComplete="off"

View File

@@ -272,7 +272,6 @@ export function isLocalRoomId(roomId: string, client: MatrixClient): boolean {
export async function createRoom(
client: MatrixClient,
name: string,
ptt: boolean,
e2ee: boolean
): Promise<[string, string]> {
logger.log(`Creating room for group call`);
@@ -327,14 +326,12 @@ export async function createRoom(
const result = await createPromise;
logger.log(
`Creating ${ptt ? "PTT" : "video"} group call in ${result.room_id}`
);
logger.log(`Creating group call in ${result.room_id}`);
await client.createGroupCall(
result.room_id,
ptt ? GroupCallType.Voice : GroupCallType.Video,
ptt,
GroupCallType.Video,
false,
GroupCallIntent.Room,
true
);

View File

@@ -27,7 +27,6 @@ interface Props {
roomIdOrAlias: string;
viaServers: string[];
children: (rtcSession: MatrixRTCSession) => ReactNode;
createPtt: boolean;
}
export function GroupCallLoader({
@@ -35,15 +34,9 @@ export function GroupCallLoader({
roomIdOrAlias,
viaServers,
children,
createPtt,
}: Props): JSX.Element {
const { t } = useTranslation();
const groupCallState = useLoadGroupCall(
client,
roomIdOrAlias,
viaServers,
createPtt
);
const groupCallState = useLoadGroupCall(client, roomIdOrAlias, viaServers);
switch (groupCallState.kind) {
case "loading":

View File

@@ -35,7 +35,6 @@ export const RoomPage: FC = () => {
isEmbedded,
preload,
hideHeader,
isPtt,
displayName,
} = useUrlParams();
const roomIdOrAlias = roomId ?? roomAlias;
@@ -107,7 +106,6 @@ export const RoomPage: FC = () => {
client={client}
roomIdOrAlias={roomIdOrAlias}
viaServers={viaServers}
createPtt={isPtt}
>
{groupCallView}
</GroupCallLoader>

View File

@@ -56,8 +56,7 @@ export interface GroupCallLoadState {
export const useLoadGroupCall = (
client: MatrixClient,
roomIdOrAlias: string,
viaServers: string[],
createPtt: boolean
viaServers: string[]
): GroupCallStatus => {
const { t } = useTranslation();
const [state, setState] = useState<GroupCallStatus>({ kind: "loading" });
@@ -101,7 +100,6 @@ export const useLoadGroupCall = (
const [, roomId] = await createRoom(
client,
roomNameFromRoomId(roomIdOrAlias),
createPtt,
e2eeEnabled ?? false
);
@@ -151,7 +149,7 @@ export const useLoadGroupCall = (
.then(fetchOrCreateGroupCall)
.then((rtcSession) => setState({ kind: "loaded", rtcSession }))
.catch((error) => setState({ kind: "failed", error }));
}, [client, roomIdOrAlias, viaServers, createPtt, t, e2eeEnabled]);
}, [client, roomIdOrAlias, viaServers, t, e2eeEnabled]);
return state;
};