From 1a5898eb30fe3266d9e753ab035f6d732a0a70a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 4 Aug 2023 13:39:59 +0200 Subject: [PATCH 01/29] Get E2EE password from the URL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/UrlParams.ts | 18 +++++++++++++++++- src/room/LobbyView.tsx | 5 ++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/UrlParams.ts b/src/UrlParams.ts index 700c8154..80f91de0 100644 --- a/src/UrlParams.ts +++ b/src/UrlParams.ts @@ -19,6 +19,8 @@ import { useLocation } from "react-router-dom"; import { Config } from "./config/Config"; +const PASSWORD_STRING = "?password="; + interface UrlParams { roomAlias: string | null; roomId: string | null; @@ -86,6 +88,10 @@ interface UrlParams { * user's homeserver doesn't provide any. */ allowIceFallback: boolean; + /** + * E2EE password + */ + password: string | null; } /** @@ -103,8 +109,17 @@ export const getUrlParams = ( hash = window.location.hash ): UrlParams => { let roomAlias: string | null = null; + let password: string | null = null; + + const passwordIndex = hash.indexOf(PASSWORD_STRING); + const passwordStart = + passwordIndex === -1 ? null : passwordIndex + PASSWORD_STRING.length; + if (passwordStart) { + password = hash.substring(passwordStart); + } + if (!ignoreRoomAlias) { - if (hash === "") { + if (hash === "" || hash.startsWith("#" + PASSWORD_STRING)) { roomAlias = pathname.substring(1); // Strip the "/" // Delete "/room/", if present @@ -164,6 +179,7 @@ export const getUrlParams = ( return { roomAlias, roomId, + password, viaServers: getAllParams("via"), isEmbedded: hasParam("embed"), preload: hasParam("preload"), diff --git a/src/room/LobbyView.tsx b/src/room/LobbyView.tsx index e1edadd5..53bc170b 100644 --- a/src/room/LobbyView.tsx +++ b/src/room/LobbyView.tsx @@ -36,6 +36,7 @@ import { E2EEConfig } from "../livekit/useLiveKit"; import { InputField } from "../input/Input"; import { useEnableE2EE } from "../settings/useSetting"; import { MuteStates } from "./MuteStates"; +import { useUrlParams } from "../UrlParams"; interface Props { matrixInfo: MatrixInfo; @@ -52,6 +53,8 @@ export const LobbyView: FC = ({ isEmbedded, hideHeader, }) => { + const { password } = useUrlParams(); + const { t } = useTranslation(); useLocationNavigation(); @@ -65,7 +68,7 @@ export const LobbyView: FC = ({ }, [joinCallButtonRef]); const [e2eeSharedKey, setE2EESharedKey] = useState( - undefined + password ?? undefined ); const onE2EESharedKeyChanged = useCallback( From 59653fea07858296f3a4fed9d7a2917e61e9f2c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 4 Aug 2023 14:01:13 +0200 Subject: [PATCH 02/29] Update the URL the lobby view when the password changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/room/LobbyView.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/room/LobbyView.tsx b/src/room/LobbyView.tsx index 53bc170b..5880c362 100644 --- a/src/room/LobbyView.tsx +++ b/src/room/LobbyView.tsx @@ -79,6 +79,17 @@ export const LobbyView: FC = ({ [setE2EESharedKey] ); + useEffect(() => { + const originalHash = location.hash; + let hash = originalHash === "" ? "#" : originalHash; + hash = hash.split("?password=")[0]; + hash += `?password=${e2eeSharedKey ?? ""}`; + + if (originalHash !== hash) { + location.replace(hash); + } + }, [e2eeSharedKey]); + return (
{!hideHeader && ( From 8fdc1e3684a0a2bb713e4c12bb7fc32febf1d49a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 8 Aug 2023 13:46:51 +0200 Subject: [PATCH 03/29] Store shared keys in local storage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/e2ee/sharedKeyManagement.ts | 20 ++++++++++++ src/room/GroupCallView.tsx | 37 +++++++++++++++++---- src/room/LobbyView.tsx | 57 ++------------------------------- src/settings/useSetting.ts | 2 +- 4 files changed, 54 insertions(+), 62 deletions(-) create mode 100644 src/e2ee/sharedKeyManagement.ts diff --git a/src/e2ee/sharedKeyManagement.ts b/src/e2ee/sharedKeyManagement.ts new file mode 100644 index 00000000..0a819066 --- /dev/null +++ b/src/e2ee/sharedKeyManagement.ts @@ -0,0 +1,20 @@ +/* +Copyright 2023 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 { useSetting } from "../settings/useSetting"; + +export const useRoomSharedKey = (roomId: string, initialValue?: string) => + useSetting(`room-shared-key-${roomId}`, initialValue); diff --git a/src/room/GroupCallView.tsx b/src/room/GroupCallView.tsx index d8e2fd6b..45bcac3b 100644 --- a/src/room/GroupCallView.tsx +++ b/src/room/GroupCallView.tsx @@ -32,13 +32,14 @@ import { CallEndedView } from "./CallEndedView"; import { useSentryGroupCallHandler } from "./useSentryGroupCallHandler"; import { PosthogAnalytics } from "../analytics/PosthogAnalytics"; import { useProfile } from "../profile/useProfile"; -import { E2EEConfig } from "../livekit/useLiveKit"; import { findDeviceByName } from "../media-utils"; import { OpenIDLoader } from "../livekit/OpenIDLoader"; import { ActiveCall } from "./InCallView"; import { Config } from "../config/Config"; import { MuteStates, useMuteStates } from "./MuteStates"; import { useMediaDevices, MediaDevices } from "../livekit/MediaDevicesContext"; +import { useRoomSharedKey } from "../e2ee/sharedKeyManagement"; +import { useUrlParams } from "../UrlParams"; declare global { interface Window { @@ -73,6 +74,8 @@ export function GroupCallView({ otelGroupCallMembership, } = useGroupCall(groupCall, client); + const { password } = useUrlParams(); + const { t } = useTranslation(); useEffect(() => { @@ -241,8 +244,31 @@ export function GroupCallView({ } }, [groupCall, state, leave]); - const [e2eeConfig, setE2EEConfig] = useState( - undefined + const [e2eeSharedKey, setE2EESharedKey] = useRoomSharedKey( + groupCall.room.roomId, + password ?? undefined + ); + + useEffect(() => { + if (!password || password === e2eeSharedKey) return; + + setE2EESharedKey(password); + }, [password, e2eeSharedKey, setE2EESharedKey]); + + useEffect(() => { + const originalHash = location.hash; + let hash = originalHash === "" ? "#" : originalHash; + hash = hash.split("?password=")[0]; + hash += `?password=${e2eeSharedKey ?? ""}`; + + if (originalHash !== hash) { + location.replace(hash); + } + }, [e2eeSharedKey]); + + const e2eeConfig = useMemo( + () => (e2eeSharedKey ? { sharedKey: e2eeSharedKey } : undefined), + [e2eeSharedKey] ); const onReconnect = useCallback(() => { @@ -319,10 +345,7 @@ export function GroupCallView({ { - setE2EEConfig(e2eeConfig); - enter(); - }} + onEnter={() => enter()} isEmbedded={isEmbedded} hideHeader={hideHeader} /> diff --git a/src/room/LobbyView.tsx b/src/room/LobbyView.tsx index 5880c362..d77f4d1d 100644 --- a/src/room/LobbyView.tsx +++ b/src/room/LobbyView.tsx @@ -14,14 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { - useRef, - useEffect, - useState, - useCallback, - ChangeEvent, - FC, -} from "react"; +import { useRef, useEffect, FC } from "react"; import { Trans, useTranslation } from "react-i18next"; import styles from "./LobbyView.module.css"; @@ -32,16 +25,12 @@ import { UserMenuContainer } from "../UserMenuContainer"; import { Body, Link } from "../typography/Typography"; import { useLocationNavigation } from "../useLocationNavigation"; import { MatrixInfo, VideoPreview } from "./VideoPreview"; -import { E2EEConfig } from "../livekit/useLiveKit"; -import { InputField } from "../input/Input"; -import { useEnableE2EE } from "../settings/useSetting"; import { MuteStates } from "./MuteStates"; -import { useUrlParams } from "../UrlParams"; interface Props { matrixInfo: MatrixInfo; muteStates: MuteStates; - onEnter: (e2eeConfig?: E2EEConfig) => void; + onEnter: () => void; isEmbedded: boolean; hideHeader: boolean; } @@ -53,13 +42,9 @@ export const LobbyView: FC = ({ isEmbedded, hideHeader, }) => { - const { password } = useUrlParams(); - const { t } = useTranslation(); useLocationNavigation(); - const [enableE2EE] = useEnableE2EE(); - const joinCallButtonRef = useRef(null); useEffect(() => { if (joinCallButtonRef.current) { @@ -67,29 +52,6 @@ export const LobbyView: FC = ({ } }, [joinCallButtonRef]); - const [e2eeSharedKey, setE2EESharedKey] = useState( - password ?? undefined - ); - - const onE2EESharedKeyChanged = useCallback( - (event: ChangeEvent) => { - const value = event.target.value; - setE2EESharedKey(value === "" ? undefined : value); - }, - [setE2EESharedKey] - ); - - useEffect(() => { - const originalHash = location.hash; - let hash = originalHash === "" ? "#" : originalHash; - hash = hash.split("?password=")[0]; - hash += `?password=${e2eeSharedKey ?? ""}`; - - if (originalHash !== hash) { - location.replace(hash); - } - }, [e2eeSharedKey]); - return (
{!hideHeader && ( @@ -105,25 +67,12 @@ export const LobbyView: FC = ({
- {enableE2EE && ( - - )} - + {e2eeEnabled ? ( + + ) : ( + <> + + + + )} From 819734e2dd703433e97c40d7a671e4c9223c4516 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 9 Aug 2023 14:00:25 +0200 Subject: [PATCH 12/29] i18n MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- public/locales/en-GB/app.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/public/locales/en-GB/app.json b/public/locales/en-GB/app.json index e9d995a3..62462c6a 100644 --- a/public/locales/en-GB/app.json +++ b/public/locales/en-GB/app.json @@ -73,6 +73,7 @@ "No": "No", "Not now, return to home screen": "Not now, return to home screen", "Not registered yet? <2>Create an account": "Not registered yet? <2>Create an account", + "Ok": "Ok", "Other users are trying to join this call from incompatible versions. These users should ensure that they have refreshed their browsers:<1>{userLis}": "Other users are trying to join this call from incompatible versions. These users should ensure that they have refreshed their browsers:<1>{userLis}", "Password": "Password", "Passwords must match": "Passwords must match", @@ -104,6 +105,8 @@ "Take me Home": "Take me Home", "Thanks, we received your feedback!": "Thanks, we received your feedback!", "Thanks!": "Thanks!", + "This call already exists": "This call already exists", + "This call already exists, please join using a URL retrieved using the in-app copy link button": "This call already exists, please join using a URL retrieved using the in-app copy link button", "This call already exists, would you like to join?": "This call already exists, would you like to join?", "This site is protected by ReCAPTCHA and the Google <2>Privacy Policy and <6>Terms of Service apply.<9>By clicking \"Register\", you agree to our <12>End User Licensing Agreement (EULA)": "This site is protected by ReCAPTCHA and the Google <2>Privacy Policy and <6>Terms of Service apply.<9>By clicking \"Register\", you agree to our <12>End User Licensing Agreement (EULA)", "Turn off camera": "Turn off camera", From 6a3c02f7f7713b2336fcf5be11816055a1b6d3d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 9 Aug 2023 14:01:19 +0200 Subject: [PATCH 13/29] Delint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/room/InviteModal.tsx | 2 +- src/room/LobbyView.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/room/InviteModal.tsx b/src/room/InviteModal.tsx index b807d26f..1986374b 100644 --- a/src/room/InviteModal.tsx +++ b/src/room/InviteModal.tsx @@ -43,7 +43,7 @@ export const InviteModal: FC = ({ roomAlias, roomId, ...rest }) => {

{t("Copy and share this call link")}

diff --git a/src/room/LobbyView.tsx b/src/room/LobbyView.tsx index 3f985d79..e3f80d43 100644 --- a/src/room/LobbyView.tsx +++ b/src/room/LobbyView.tsx @@ -84,7 +84,7 @@ export const LobbyView: FC = ({ variant="secondaryCopy" value={getRoomUrl( matrixInfo.roomAlias ?? matrixInfo.roomId, - roomSharedKey + roomSharedKey ?? undefined )} className={styles.copyButton} copiedMessage={t("Call link copied")} From 923043a58c46ab90d022ff39de38b9c89eb1c585 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 9 Aug 2023 14:08:23 +0200 Subject: [PATCH 14/29] Fix tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- test/home/CallList-test.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/home/CallList-test.tsx b/test/home/CallList-test.tsx index a161960f..b2a1e5ec 100644 --- a/test/home/CallList-test.tsx +++ b/test/home/CallList-test.tsx @@ -34,7 +34,13 @@ describe("CallList", () => { it("should show room", async () => { const rooms = [ - { roomName: "Room #1", roomAlias: "#room-name:server.org" }, + { + roomName: "Room #1", + roomAlias: "#room-name:server.org", + room: { + roomId: "!roomId", + }, + }, ] as GroupCallRoom[]; const result = renderComponent(rooms); From 5c3d8efebf36adc96a4ea12e8204e3154b1e9f4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 10 Aug 2023 15:19:43 +0200 Subject: [PATCH 15/29] Improve URL handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/UrlParams.ts | 15 +++------------ src/matrix-utils.ts | 2 +- src/room/GroupCallView.tsx | 10 ++++++---- 3 files changed, 10 insertions(+), 17 deletions(-) diff --git a/src/UrlParams.ts b/src/UrlParams.ts index 82a08801..85071eb6 100644 --- a/src/UrlParams.ts +++ b/src/UrlParams.ts @@ -19,7 +19,7 @@ import { useLocation } from "react-router-dom"; import { Config } from "./config/Config"; -export const PASSWORD_STRING = "?password="; +export const PASSWORD_STRING = "password="; interface UrlParams { roomAlias: string | null; @@ -109,17 +109,8 @@ export const getUrlParams = ( hash = window.location.hash ): UrlParams => { let roomAlias: string | null = null; - let password: string | null = null; - - const passwordIndex = hash.indexOf(PASSWORD_STRING); - const passwordStart = - passwordIndex === -1 ? null : passwordIndex + PASSWORD_STRING.length; - if (passwordStart) { - password = hash.substring(passwordStart); - } - if (!ignoreRoomAlias) { - if (hash === "" || hash.startsWith("#" + PASSWORD_STRING)) { + if (hash === "" || hash.startsWith("#?")) { roomAlias = pathname.substring(1); // Strip the "/" // Delete "/room/", if present @@ -179,7 +170,7 @@ export const getUrlParams = ( return { roomAlias, roomId, - password, + password: getParam("password"), viaServers: getAllParams("via"), isEmbedded: hasParam("embed"), preload: hasParam("preload"), diff --git a/src/matrix-utils.ts b/src/matrix-utils.ts index e60f5345..ba76b665 100644 --- a/src/matrix-utils.ts +++ b/src/matrix-utils.ts @@ -347,7 +347,7 @@ export function getRoomUrl( roomIdOrAlias: string, password: string = "" ): string { - password = password === "" ? "" : "#" + PASSWORD_STRING + password; + password = password === "" ? "" : "#?" + PASSWORD_STRING + password; if (roomIdOrAlias.startsWith("#")) { return `${window.location.protocol}//${window.location.host}/${ diff --git a/src/room/GroupCallView.tsx b/src/room/GroupCallView.tsx index cf3aa341..b528d9ce 100644 --- a/src/room/GroupCallView.tsx +++ b/src/room/GroupCallView.tsx @@ -257,13 +257,15 @@ export function GroupCallView({ }, [password, e2eeSharedKey, setE2EESharedKey]); useEffect(() => { - const originalHash = location.hash; - const hash = originalHash === "" ? "#" : originalHash; - const [hashStart, password] = hash.split(PASSWORD_STRING); + const hash = location.hash; + if (!hash.includes("?")) return; + + const [hashStart, passwordStart] = hash.split(PASSWORD_STRING); + const [password, hashEnd] = passwordStart ? passwordStart.split("&") : []; if (password !== e2eeSharedKey) return; - location.replace(hashStart); + location.replace((hashStart ?? "") + (hashEnd ?? "")); }, [password, e2eeSharedKey]); const e2eeConfig = useMemo( From 96f264db87cb211f69e2b7274937bf7845b36d01 Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 11 Aug 2023 09:24:11 +0100 Subject: [PATCH 16/29] Put the 'v' back on the docker tag for release versions --- .github/workflows/publish.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 5d1bf6a9..b5cf8765 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -67,7 +67,7 @@ jobs: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | type=sha,format=short,event=branch - type=semver,pattern={{version}} + type=semver,pattern=v{{version}} type=raw,value=latest-ci,enable={{is_default_branch}} type=raw,value=latest-ci_${{steps.current-time.outputs.unix_time}},enable={{is_default_branch}} From 506b363f381d5a2d345617ffee1baee60a59d2e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 11 Aug 2023 13:14:50 +0200 Subject: [PATCH 17/29] Update E2EE texts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/E2EEBanner.tsx | 4 ++++ src/E2EELock.tsx | 5 +---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/E2EEBanner.tsx b/src/E2EEBanner.tsx index 957813e3..774f3582 100644 --- a/src/E2EEBanner.tsx +++ b/src/E2EEBanner.tsx @@ -19,8 +19,12 @@ import { Trans } from "react-i18next"; import { Banner } from "./Banner"; import styles from "./E2EEBanner.module.css"; import { ReactComponent as LockOffIcon } from "./icons/LockOff.svg"; +import { useEnableE2EE } from "./settings/useSetting"; export const E2EEBanner = () => { + const [e2eeEnabled] = useEnableE2EE(); + if (e2eeEnabled) return null; + return (
diff --git a/src/E2EELock.tsx b/src/E2EELock.tsx index d032b036..9a9a55e9 100644 --- a/src/E2EELock.tsx +++ b/src/E2EELock.tsx @@ -26,10 +26,7 @@ import { TooltipTrigger } from "./Tooltip"; export const E2EELock = () => { const { t } = useTranslation(); const tooltip = useCallback( - () => - t( - "Element Call is temporarily not end-to-end encrypted while we test scalability." - ), + () => t("This call is not end-to-end encrypted."), [t] ); From b2f5f90f37abae98879bc8bc69ba8bd66fb178ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 11 Aug 2023 13:16:35 +0200 Subject: [PATCH 18/29] More URL handling adjustements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/UrlParams.ts | 15 +++++++++------ src/matrix-utils.ts | 29 +++++++++++++---------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/UrlParams.ts b/src/UrlParams.ts index 85071eb6..e6f0cd05 100644 --- a/src/UrlParams.ts +++ b/src/UrlParams.ts @@ -108,8 +108,11 @@ export const getUrlParams = ( pathname = window.location.pathname, hash = window.location.hash ): UrlParams => { + // This is legacy code - we're moving away from using aliases let roomAlias: string | null = null; if (!ignoreRoomAlias) { + // Here we handle the beginning of the alias and make sure it starts with a + // "#" if (hash === "" || hash.startsWith("#?")) { roomAlias = pathname.substring(1); // Strip the "/" @@ -125,17 +128,17 @@ export const getUrlParams = ( roomAlias = hash; } - // Add server part, if not present - if (!roomAlias.includes(":")) { - roomAlias = `${roomAlias}:${Config.defaultServerName()}`; - } - // Delete "?" and what comes afterwards roomAlias = roomAlias.split("?")[0]; - // Make roomAlias undefined, if empty if (roomAlias.length <= 1) { + // Make roomAlias is null, if it only is a "#" roomAlias = null; + } else { + // Add server part, if not present + if (!roomAlias.includes(":")) { + roomAlias = `${roomAlias}:${Config.defaultServerName()}`; + } } } diff --git a/src/matrix-utils.ts b/src/matrix-utils.ts index ba76b665..d074fa3f 100644 --- a/src/matrix-utils.ts +++ b/src/matrix-utils.ts @@ -273,14 +273,15 @@ export function isLocalRoomId(roomId: string, client: MatrixClient): boolean { export async function createRoom( client: MatrixClient, name: string, - ptt: boolean + ptt: boolean, + e2ee: boolean ): Promise<[string, string]> { logger.log(`Creating room for group call`); const createPromise = client.createRoom({ visibility: Visibility.Private, preset: Preset.PublicChat, name, - room_alias_name: roomAliasLocalpartFromRoomName(name), + room_alias_name: e2ee ? undefined : roomAliasLocalpartFromRoomName(name), power_level_content_override: { invite: 100, kick: 100, @@ -342,20 +343,16 @@ export async function createRoom( return [fullAliasFromRoomName(name, client), result.room_id]; } -// Returns a URL to that will load Element Call with the given room -export function getRoomUrl( - roomIdOrAlias: string, - password: string = "" -): string { - password = password === "" ? "" : "#?" + PASSWORD_STRING + password; - - if (roomIdOrAlias.startsWith("#")) { - return `${window.location.protocol}//${window.location.host}/${ - roomIdOrAlias.substring(1).split(":")[0] - }${password}`; - } else { - return `${window.location.protocol}//${window.location.host}/room?roomId=${roomIdOrAlias}${password}`; - } +/** + * Returns a URL to that will load Element Call with the given room + * @param roomId of the room + * @param password + * @returns + */ +export function getRoomUrl(roomId: string, password?: string): string { + return `${window.location.protocol}//${ + window.location.host + }/room/#?roomId=${roomId}${password ? "&" + PASSWORD_STRING + password : ""}`; } export function getAvatarUrl( From c86ef4016284b75bdf639a7ef82d21124cc13f20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 11 Aug 2023 13:25:09 +0200 Subject: [PATCH 19/29] Goodbye, aliases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/home/CallList.tsx | 13 +++---------- src/home/RegisteredView.tsx | 4 ++-- src/home/UnauthenticatedView.tsx | 2 +- src/home/useGroupCallRooms.ts | 3 +-- src/room/InCallView.tsx | 6 +----- src/room/InviteModal.tsx | 5 ++--- src/room/LobbyView.tsx | 5 +---- 7 files changed, 11 insertions(+), 27 deletions(-) diff --git a/src/home/CallList.tsx b/src/home/CallList.tsx index 99296c5d..8e17c013 100644 --- a/src/home/CallList.tsx +++ b/src/home/CallList.tsx @@ -23,7 +23,7 @@ import { Facepile } from "../Facepile"; import { Avatar, Size } from "../Avatar"; import styles from "./CallList.module.css"; import { getRoomUrl } from "../matrix-utils"; -import { Body, Caption } from "../typography/Typography"; +import { Body } from "../typography/Typography"; import { GroupCallRoom } from "./useGroupCallRooms"; import { useRoomSharedKey } from "../e2ee/sharedKeyManagement"; @@ -42,7 +42,6 @@ export function CallList({ rooms, client, disableFacepile }: CallListProps) { client={client} name={roomName} avatarUrl={avatarUrl} - roomAlias={roomAlias} roomId={room.roomId} participants={participants} disableFacepile={disableFacepile} @@ -61,7 +60,6 @@ export function CallList({ rooms, client, disableFacepile }: CallListProps) { interface CallTileProps { name: string; avatarUrl: string; - roomAlias: string; roomId: string; participants: RoomMember[]; client: MatrixClient; @@ -70,7 +68,6 @@ interface CallTileProps { function CallTile({ name, avatarUrl, - roomAlias, roomId, participants, client, @@ -80,10 +77,7 @@ function CallTile({ return (
- + {name} - {getRoomUrl(roomAlias)} {participants && !disableFacepile && (
); diff --git a/src/home/RegisteredView.tsx b/src/home/RegisteredView.tsx index 8fbea9c1..5de21a3e 100644 --- a/src/home/RegisteredView.tsx +++ b/src/home/RegisteredView.tsx @@ -80,7 +80,7 @@ export function RegisteredView({ client, isPasswordlessUser }: Props) { randomString(32) ); - history.push(`/${roomAlias.substring(1).split(":")[0]}`); + history.push(`/room/#?roomId=${roomId}`); } submit().catch((error) => { @@ -103,7 +103,7 @@ export function RegisteredView({ client, isPasswordlessUser }: Props) { const [existingRoomId, setExistingRoomId] = useState(); const onJoinExistingRoom = useCallback(() => { - history.push(`/${existingRoomId}`); + history.push(`/room/#?roomId=${existingRoomId}`); }, [history, existingRoomId]); const callNameLabel = diff --git a/src/home/UnauthenticatedView.tsx b/src/home/UnauthenticatedView.tsx index f479901f..a9c840df 100644 --- a/src/home/UnauthenticatedView.tsx +++ b/src/home/UnauthenticatedView.tsx @@ -110,7 +110,7 @@ export const UnauthenticatedView: FC = () => { } setClient({ client, session }); - history.push(`/${roomAlias.substring(1).split(":")[0]}`); + history.push(`/room/#?roomId=${roomId}`); } submit().catch((error) => { diff --git a/src/home/useGroupCallRooms.ts b/src/home/useGroupCallRooms.ts index 0f5d8ef9..58135b04 100644 --- a/src/home/useGroupCallRooms.ts +++ b/src/home/useGroupCallRooms.ts @@ -89,8 +89,7 @@ export function useGroupCallRooms(client: MatrixClient): GroupCallRoom[] { const groupCalls = client.groupCallEventHandler.groupCalls.values(); const rooms = Array.from(groupCalls).map((groupCall) => groupCall.room); - const filteredRooms = rooms.filter((r) => r.getCanonicalAlias()); // We don't display rooms without an alias - const sortedRooms = sortRooms(client, filteredRooms); + const sortedRooms = sortRooms(client, rooms); const items = sortedRooms.map((room) => { const groupCall = client.getGroupCallForRoom(room.roomId)!; diff --git a/src/room/InCallView.tsx b/src/room/InCallView.tsx index fa1c1754..fd3964c6 100644 --- a/src/room/InCallView.tsx +++ b/src/room/InCallView.tsx @@ -461,11 +461,7 @@ export function InCallView({ /> )} {inviteModalState.isOpen && ( - + )}
); diff --git a/src/room/InviteModal.tsx b/src/room/InviteModal.tsx index 1986374b..e52e7f3a 100644 --- a/src/room/InviteModal.tsx +++ b/src/room/InviteModal.tsx @@ -24,11 +24,10 @@ import styles from "./InviteModal.module.css"; import { useRoomSharedKey } from "../e2ee/sharedKeyManagement"; interface Props extends Omit { - roomAlias?: string; roomId: string; } -export const InviteModal: FC = ({ roomAlias, roomId, ...rest }) => { +export const InviteModal: FC = ({ roomId, ...rest }) => { const { t } = useTranslation(); const [roomSharedKey] = useRoomSharedKey(roomId); @@ -43,7 +42,7 @@ export const InviteModal: FC = ({ roomAlias, roomId, ...rest }) => {

{t("Copy and share this call link")}

diff --git a/src/room/LobbyView.tsx b/src/room/LobbyView.tsx index e3f80d43..ad5f999c 100644 --- a/src/room/LobbyView.tsx +++ b/src/room/LobbyView.tsx @@ -82,10 +82,7 @@ export const LobbyView: FC = ({ Or Date: Fri, 11 Aug 2023 16:57:55 +0200 Subject: [PATCH 20/29] Improve loading of passwords MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/e2ee/sharedKeyManagement.ts | 40 +++++++++++++++++++++++++++++++-- src/home/CallList.tsx | 2 +- src/room/GroupCallView.tsx | 31 +++++-------------------- src/room/InviteModal.tsx | 2 +- src/room/LobbyView.tsx | 2 +- 5 files changed, 47 insertions(+), 30 deletions(-) diff --git a/src/e2ee/sharedKeyManagement.ts b/src/e2ee/sharedKeyManagement.ts index 11b436ea..ed7ba2f5 100644 --- a/src/e2ee/sharedKeyManagement.ts +++ b/src/e2ee/sharedKeyManagement.ts @@ -14,20 +14,56 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { useMemo } from "react"; +import { useEffect, useMemo } from "react"; import { useEnableE2EE } from "../settings/useSetting"; import { useLocalStorage } from "../useLocalStorage"; +import { PASSWORD_STRING, useUrlParams } from "../UrlParams"; export const getRoomSharedKeyLocalStorageKey = (roomId: string): string => `room-shared-key-${roomId}`; -export const useRoomSharedKey = ( +export const useInternalRoomSharedKey = ( roomId: string ): [string | null, ((value: string) => void) | null] => { const key = useMemo(() => getRoomSharedKeyLocalStorageKey(roomId), [roomId]); const [e2eeEnabled] = useEnableE2EE(); const [roomSharedKey, setRoomSharedKey] = useLocalStorage(key); + console.log("LOG useRoomSharedKey return:", key, roomSharedKey); return e2eeEnabled ? [roomSharedKey, setRoomSharedKey] : [null, null]; }; + +export const useRoomSharedKey = (roomId: string): string | null => { + return useInternalRoomSharedKey(roomId)[0]; +}; + +export const useManageRoomSharedKey = (roomId: string): string | null => { + const { password } = useUrlParams(); + const [e2eeSharedKey, setE2EESharedKey] = useInternalRoomSharedKey(roomId); + + useEffect(() => { + if (!password) return; + if (password === "") return; + if (password === e2eeSharedKey) return; + + setE2EESharedKey?.(password); + }, [password, e2eeSharedKey, setE2EESharedKey]); + + useEffect(() => { + const hash = location.hash; + + if (!hash.includes("?")) return; + if (!hash.includes(PASSWORD_STRING)) return; + if (password !== e2eeSharedKey) return; + + const [hashStart, passwordStart] = hash.split(PASSWORD_STRING); + const hashEnd = passwordStart.split("&")[1]; + + location.replace((hashStart ?? "") + (hashEnd ?? "")); + }, [password, e2eeSharedKey]); + + return e2eeSharedKey; +}; + +}; diff --git a/src/home/CallList.tsx b/src/home/CallList.tsx index 8e17c013..1e36360e 100644 --- a/src/home/CallList.tsx +++ b/src/home/CallList.tsx @@ -73,7 +73,7 @@ function CallTile({ client, disableFacepile, }: CallTileProps) { - const [roomSharedKey] = useRoomSharedKey(roomId); + const roomSharedKey = useRoomSharedKey(roomId); return (
diff --git a/src/room/GroupCallView.tsx b/src/room/GroupCallView.tsx index b528d9ce..5b4068c4 100644 --- a/src/room/GroupCallView.tsx +++ b/src/room/GroupCallView.tsx @@ -38,8 +38,10 @@ import { ActiveCall } from "./InCallView"; import { Config } from "../config/Config"; import { MuteStates, useMuteStates } from "./MuteStates"; import { useMediaDevices, MediaDevices } from "../livekit/MediaDevicesContext"; -import { useRoomSharedKey } from "../e2ee/sharedKeyManagement"; -import { PASSWORD_STRING, useUrlParams } from "../UrlParams"; +import { + useManageRoomSharedKey, + useRoomSharedKey, +} from "../e2ee/sharedKeyManagement"; import { useEnableE2EE } from "../settings/useSetting"; declare global { @@ -75,7 +77,7 @@ export function GroupCallView({ otelGroupCallMembership, } = useGroupCall(groupCall, client); - const { password } = useUrlParams(); + const e2eeSharedKey = useManageRoomSharedKey(groupCall.room.roomId); const { t } = useTranslation(); @@ -246,27 +248,6 @@ export function GroupCallView({ }, [groupCall, state, leave]); const [e2eeEnabled] = useEnableE2EE(); - const [e2eeSharedKey, setE2EESharedKey] = useRoomSharedKey( - groupCall.room.roomId - ); - - useEffect(() => { - if (!password || password === "" || password === e2eeSharedKey) return; - - setE2EESharedKey?.(password); - }, [password, e2eeSharedKey, setE2EESharedKey]); - - useEffect(() => { - const hash = location.hash; - if (!hash.includes("?")) return; - - const [hashStart, passwordStart] = hash.split(PASSWORD_STRING); - const [password, hashEnd] = passwordStart ? passwordStart.split("&") : []; - - if (password !== e2eeSharedKey) return; - - location.replace((hashStart ?? "") + (hashEnd ?? "")); - }, [password, e2eeSharedKey]); const e2eeConfig = useMemo( () => (e2eeSharedKey ? { sharedKey: e2eeSharedKey } : undefined), @@ -279,7 +260,7 @@ export function GroupCallView({ groupCall.enter(); }, [groupCall]); - if (!password && !e2eeSharedKey && e2eeEnabled) { + if (e2eeEnabled && isRoomE2EE && !e2eeSharedKey) { return ( { export const InviteModal: FC = ({ roomId, ...rest }) => { const { t } = useTranslation(); - const [roomSharedKey] = useRoomSharedKey(roomId); + const roomSharedKey = useRoomSharedKey(roomId); return ( = ({ hideHeader, }) => { const { t } = useTranslation(); - const [roomSharedKey] = useRoomSharedKey(matrixInfo.roomId); + const roomSharedKey = useRoomSharedKey(matrixInfo.roomId); useLocationNavigation(); const joinCallButtonRef = useRef(null); From edfae0138c59f7d9fc2790a30f771bd95efde64c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 11 Aug 2023 16:59:26 +0200 Subject: [PATCH 21/29] Add `useIsRoomE2EE()` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/e2ee/sharedKeyManagement.ts | 13 +++++++++++++ src/room/GroupCallView.tsx | 7 ++++++- src/room/InCallView.tsx | 5 ++++- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/e2ee/sharedKeyManagement.ts b/src/e2ee/sharedKeyManagement.ts index ed7ba2f5..0e373ce1 100644 --- a/src/e2ee/sharedKeyManagement.ts +++ b/src/e2ee/sharedKeyManagement.ts @@ -18,6 +18,7 @@ import { useEffect, useMemo } from "react"; import { useEnableE2EE } from "../settings/useSetting"; import { useLocalStorage } from "../useLocalStorage"; +import { useClient } from "../ClientContext"; import { PASSWORD_STRING, useUrlParams } from "../UrlParams"; export const getRoomSharedKeyLocalStorageKey = (roomId: string): string => @@ -66,4 +67,16 @@ export const useManageRoomSharedKey = (roomId: string): string | null => { return e2eeSharedKey; }; +export const useIsRoomE2EE = (roomId: string): boolean | null => { + const client = useClient(); + const room = useMemo( + () => client.client?.getRoom(roomId) ?? null, + [roomId, client.client] + ); + const isE2EE = useMemo( + () => (room ? !room?.getCanonicalAlias() : null), + [room] + ); + + return isE2EE; }; diff --git a/src/room/GroupCallView.tsx b/src/room/GroupCallView.tsx index 5b4068c4..c6c73815 100644 --- a/src/room/GroupCallView.tsx +++ b/src/room/GroupCallView.tsx @@ -40,7 +40,7 @@ import { MuteStates, useMuteStates } from "./MuteStates"; import { useMediaDevices, MediaDevices } from "../livekit/MediaDevicesContext"; import { useManageRoomSharedKey, - useRoomSharedKey, + useIsRoomE2EE, } from "../e2ee/sharedKeyManagement"; import { useEnableE2EE } from "../settings/useSetting"; @@ -78,6 +78,7 @@ export function GroupCallView({ } = useGroupCall(groupCall, client); const e2eeSharedKey = useManageRoomSharedKey(groupCall.room.roomId); + const isRoomE2EE = useIsRoomE2EE(groupCall.room.roomId); const { t } = useTranslation(); @@ -272,6 +273,10 @@ export function GroupCallView({ ); } + if (!e2eeEnabled && isRoomE2EE) { + return ; + } + const livekitServiceURL = groupCall.livekitServiceURL ?? Config.get().livekit?.livekit_service_url; if (!livekitServiceURL) { diff --git a/src/room/InCallView.tsx b/src/room/InCallView.tsx index fd3964c6..fa99a5c9 100644 --- a/src/room/InCallView.tsx +++ b/src/room/InCallView.tsx @@ -88,6 +88,7 @@ import { useEventEmitterThree } from "../useEvents"; import { useWakeLock } from "../useWakeLock"; import { useMergedRefs } from "../useMergedRefs"; import { MuteStates } from "./MuteStates"; +import { useIsRoomE2EE } from "../e2ee/sharedKeyManagement"; const canScreenshare = "getDisplayMedia" in (navigator.mediaDevices ?? {}); // There is currently a bug in Safari our our code with cloning and sending MediaStreams @@ -145,6 +146,8 @@ export function InCallView({ usePreventScroll(); useWakeLock(); + const isRoomE2EE = useIsRoomE2EE(groupCall.room.roomId); + const containerRef1 = useRef(null); const [containerRef2, bounds] = useMeasure({ polyfill: ResizeObserver }); const boundsValid = bounds.height > 0; @@ -424,7 +427,7 @@ export function InCallView({ users={unencryptedEventsFromUsers} room={groupCall.room} /> - + {!isRoomE2EE && } From 22690c4a0b0cf653f3c984c0985c6ca42a1a3d37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 11 Aug 2023 17:00:05 +0200 Subject: [PATCH 22/29] Differentiate between E2EE and non-E2EE rooms by alias presence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/home/RegisteredView.tsx | 19 ++++++++++++------- src/home/UnauthenticatedView.tsx | 30 ++++++++++++++++++++++++++---- src/room/useLoadGroupCall.ts | 19 +++++++++++++++++-- 3 files changed, 55 insertions(+), 13 deletions(-) diff --git a/src/home/RegisteredView.tsx b/src/home/RegisteredView.tsx index 5de21a3e..8a5115a6 100644 --- a/src/home/RegisteredView.tsx +++ b/src/home/RegisteredView.tsx @@ -38,7 +38,7 @@ import { JoinExistingCallModal } from "./JoinExistingCallModal"; import { Caption, Title } from "../typography/Typography"; import { Form } from "../form/Form"; import { CallType, CallTypeDropdown } from "./CallTypeDropdown"; -import { useOptInAnalytics } from "../settings/useSetting"; +import { useEnableE2EE, useOptInAnalytics } from "../settings/useSetting"; import { AnalyticsNotice } from "../analytics/AnalyticsNotice"; import { E2EEBanner } from "../E2EEBanner"; import { setLocalStorageItem } from "../useLocalStorage"; @@ -57,6 +57,7 @@ export function RegisteredView({ client, isPasswordlessUser }: Props) { const history = useHistory(); const { t } = useTranslation(); const { modalState, modalProps } = useModalTriggerState(); + const [e2eeEnabled] = useEnableE2EE(); const onSubmit: FormEventHandler = useCallback( (e: FormEvent) => { @@ -73,12 +74,16 @@ export function RegisteredView({ client, isPasswordlessUser }: Props) { setError(undefined); setLoading(true); - const [roomAlias, roomId] = await createRoom(client, roomName, ptt); + const roomId = ( + await createRoom(client, roomName, ptt, e2eeEnabled ?? false) + )[1]; - setLocalStorageItem( - getRoomSharedKeyLocalStorageKey(roomId), - randomString(32) - ); + if (e2eeEnabled) { + setLocalStorageItem( + getRoomSharedKeyLocalStorageKey(roomId), + randomString(32) + ); + } history.push(`/room/#?roomId=${roomId}`); } @@ -96,7 +101,7 @@ export function RegisteredView({ client, isPasswordlessUser }: Props) { } }); }, - [client, history, modalState, callType] + [client, history, modalState, callType, e2eeEnabled] ); const recentRooms = useGroupCallRooms(client); diff --git a/src/home/UnauthenticatedView.tsx b/src/home/UnauthenticatedView.tsx index a9c840df..721c56d1 100644 --- a/src/home/UnauthenticatedView.tsx +++ b/src/home/UnauthenticatedView.tsx @@ -40,9 +40,11 @@ import styles from "./UnauthenticatedView.module.css"; import commonStyles from "./common.module.css"; import { generateRandomName } from "../auth/generateRandomName"; import { AnalyticsNotice } from "../analytics/AnalyticsNotice"; -import { useOptInAnalytics } from "../settings/useSetting"; +import { useEnableE2EE, useOptInAnalytics } from "../settings/useSetting"; import { Config } from "../config/Config"; import { E2EEBanner } from "../E2EEBanner"; +import { getRoomSharedKeyLocalStorageKey } from "../e2ee/sharedKeyManagement"; +import { setLocalStorageItem } from "../useLocalStorage"; export const UnauthenticatedView: FC = () => { const { setClient } = useClient(); @@ -58,6 +60,8 @@ export const UnauthenticatedView: FC = () => { const history = useHistory(); const { t } = useTranslation(); + const [e2eeEnabled] = useEnableE2EE(); + const onSubmit: FormEventHandler = useCallback( (e) => { e.preventDefault(); @@ -79,9 +83,18 @@ export const UnauthenticatedView: FC = () => { true ); - let roomAlias: string; + let roomId: string; try { - [roomAlias] = await createRoom(client, roomName, ptt); + roomId = ( + await createRoom(client, roomName, ptt, e2eeEnabled ?? false) + )[1]; + + if (e2eeEnabled) { + setLocalStorageItem( + getRoomSharedKeyLocalStorageKey(roomId), + randomString(32) + ); + } } catch (error) { if (!setClient) { throw error; @@ -120,7 +133,16 @@ export const UnauthenticatedView: FC = () => { reset(); }); }, - [register, reset, execute, history, callType, modalState, setClient] + [ + register, + reset, + execute, + history, + callType, + modalState, + setClient, + e2eeEnabled, + ] ); const callNameLabel = diff --git a/src/room/useLoadGroupCall.ts b/src/room/useLoadGroupCall.ts index 4aa82f11..3436360c 100644 --- a/src/room/useLoadGroupCall.ts +++ b/src/room/useLoadGroupCall.ts @@ -25,12 +25,16 @@ import { logger } from "matrix-js-sdk/src/logger"; import { ClientEvent, MatrixClient } from "matrix-js-sdk/src/client"; import { SyncState } from "matrix-js-sdk/src/sync"; import { useTranslation } from "react-i18next"; +import { randomString } from "matrix-js-sdk/src/randomstring"; import type { Room } from "matrix-js-sdk/src/models/room"; import type { GroupCall } from "matrix-js-sdk/src/webrtc/groupCall"; +import { setLocalStorageItem } from "../useLocalStorage"; import { isLocalRoomId, createRoom, roomNameFromRoomId } from "../matrix-utils"; import { translatedError } from "../TranslatedError"; import { widget } from "../widget"; +import { useEnableE2EE } from "../settings/useSetting"; +import { getRoomSharedKeyLocalStorageKey } from "../e2ee/sharedKeyManagement"; const STATS_COLLECT_INTERVAL_TIME_MS = 10000; @@ -67,6 +71,8 @@ export const useLoadGroupCall = ( const { t } = useTranslation(); const [state, setState] = useState({ kind: "loading" }); + const [e2eeEnabled] = useEnableE2EE(); + useEffect(() => { const fetchOrCreateRoom = async (): Promise => { try { @@ -104,8 +110,17 @@ export const useLoadGroupCall = ( const [, roomId] = await createRoom( client, roomNameFromRoomId(roomIdOrAlias), - createPtt + createPtt, + e2eeEnabled ?? false ); + + if (e2eeEnabled) { + setLocalStorageItem( + getRoomSharedKeyLocalStorageKey(roomId), + randomString(32) + ); + } + // likewise, wait for the room await client.waitUntilRoomReadyForGroupCalls(roomId); return client.getRoom(roomId)!; @@ -194,7 +209,7 @@ export const useLoadGroupCall = ( .then(fetchOrCreateGroupCall) .then((groupCall) => setState({ kind: "loaded", groupCall })) .catch((error) => setState({ kind: "failed", error })); - }, [client, roomIdOrAlias, viaServers, createPtt, t]); + }, [client, roomIdOrAlias, viaServers, createPtt, t, e2eeEnabled]); return state; }; From 54157611eb5a90e7c0c27bc62e573ace92e4bf15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 16 Aug 2023 13:56:31 +0200 Subject: [PATCH 23/29] Remove log line MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/e2ee/sharedKeyManagement.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/e2ee/sharedKeyManagement.ts b/src/e2ee/sharedKeyManagement.ts index 0e373ce1..819c16d9 100644 --- a/src/e2ee/sharedKeyManagement.ts +++ b/src/e2ee/sharedKeyManagement.ts @@ -31,7 +31,6 @@ export const useInternalRoomSharedKey = ( const [e2eeEnabled] = useEnableE2EE(); const [roomSharedKey, setRoomSharedKey] = useLocalStorage(key); - console.log("LOG useRoomSharedKey return:", key, roomSharedKey); return e2eeEnabled ? [roomSharedKey, setRoomSharedKey] : [null, null]; }; From 5cd8c0538e860317d88ddb8028e82a8fe8c2d14f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 16 Aug 2023 13:59:41 +0200 Subject: [PATCH 24/29] Revert changes to `JoinExistingCallModal` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/home/JoinExistingCallModal.tsx | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/src/home/JoinExistingCallModal.tsx b/src/home/JoinExistingCallModal.tsx index 26b3bf10..dfa6b095 100644 --- a/src/home/JoinExistingCallModal.tsx +++ b/src/home/JoinExistingCallModal.tsx @@ -21,7 +21,6 @@ import { Modal, ModalContent } from "../Modal"; import { Button } from "../button"; import { FieldRow } from "../input/Input"; import styles from "./JoinExistingCallModal.module.css"; -import { useEnableE2EE } from "../settings/useSetting"; interface Props { onJoin: (e: PressEvent) => void; @@ -31,36 +30,21 @@ interface Props { } export function JoinExistingCallModal({ onJoin, onClose, ...rest }: Props) { const { t } = useTranslation(); - const [e2eeEnabled] = useEnableE2EE(); return ( -

- {e2eeEnabled - ? t( - "This call already exists, please join using a URL retrieved using the in-app copy link button" - ) - : t("This call already exists, would you like to join?")} -

+

{t("This call already exists, would you like to join?")}

- {e2eeEnabled ? ( - - ) : ( - <> - - - - )} + +
From 11b5f537dee72125ca407b554320636213f5fb85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 16 Aug 2023 14:01:36 +0200 Subject: [PATCH 25/29] i18n MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- public/locales/en-GB/app.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/public/locales/en-GB/app.json b/public/locales/en-GB/app.json index 62462c6a..076c65b8 100644 --- a/public/locales/en-GB/app.json +++ b/public/locales/en-GB/app.json @@ -73,7 +73,6 @@ "No": "No", "Not now, return to home screen": "Not now, return to home screen", "Not registered yet? <2>Create an account": "Not registered yet? <2>Create an account", - "Ok": "Ok", "Other users are trying to join this call from incompatible versions. These users should ensure that they have refreshed their browsers:<1>{userLis}": "Other users are trying to join this call from incompatible versions. These users should ensure that they have refreshed their browsers:<1>{userLis}", "Password": "Password", "Passwords must match": "Passwords must match", @@ -105,9 +104,8 @@ "Take me Home": "Take me Home", "Thanks, we received your feedback!": "Thanks, we received your feedback!", "Thanks!": "Thanks!", - "This call already exists": "This call already exists", - "This call already exists, please join using a URL retrieved using the in-app copy link button": "This call already exists, please join using a URL retrieved using the in-app copy link button", "This call already exists, would you like to join?": "This call already exists, would you like to join?", + "This call is not end-to-end encrypted.": "This call is not end-to-end encrypted.", "This site is protected by ReCAPTCHA and the Google <2>Privacy Policy and <6>Terms of Service apply.<9>By clicking \"Register\", you agree to our <12>End User Licensing Agreement (EULA)": "This site is protected by ReCAPTCHA and the Google <2>Privacy Policy and <6>Terms of Service apply.<9>By clicking \"Register\", you agree to our <12>End User Licensing Agreement (EULA)", "Turn off camera": "Turn off camera", "Turn on camera": "Turn on camera", From b4b33563bed5d9d8a74d666555471f1edcd11b4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 16 Aug 2023 15:13:28 +0200 Subject: [PATCH 26/29] Fix joining an existing room MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/home/RegisteredView.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/home/RegisteredView.tsx b/src/home/RegisteredView.tsx index 8a5115a6..42aba9e8 100644 --- a/src/home/RegisteredView.tsx +++ b/src/home/RegisteredView.tsx @@ -90,7 +90,7 @@ export function RegisteredView({ client, isPasswordlessUser }: Props) { submit().catch((error) => { if (error.errcode === "M_ROOM_IN_USE") { - setExistingRoomId(roomAliasLocalpartFromRoomName(roomName)); + setExistingAlias(roomAliasLocalpartFromRoomName(roomName)); setLoading(false); setError(undefined); modalState.open(); @@ -106,10 +106,10 @@ export function RegisteredView({ client, isPasswordlessUser }: Props) { const recentRooms = useGroupCallRooms(client); - const [existingRoomId, setExistingRoomId] = useState(); + const [existingAlias, setExistingAlias] = useState(); const onJoinExistingRoom = useCallback(() => { - history.push(`/room/#?roomId=${existingRoomId}`); - }, [history, existingRoomId]); + history.push(`/${existingAlias}`); + }, [history, existingAlias]); const callNameLabel = callType === CallType.Video From 74c70627dcbb5ef6cd266727acaae9e7eff567a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 16 Aug 2023 15:35:49 +0200 Subject: [PATCH 27/29] Remove optional call MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/e2ee/sharedKeyManagement.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/e2ee/sharedKeyManagement.ts b/src/e2ee/sharedKeyManagement.ts index 819c16d9..07060419 100644 --- a/src/e2ee/sharedKeyManagement.ts +++ b/src/e2ee/sharedKeyManagement.ts @@ -47,7 +47,7 @@ export const useManageRoomSharedKey = (roomId: string): string | null => { if (password === "") return; if (password === e2eeSharedKey) return; - setE2EESharedKey?.(password); + setE2EESharedKey(password); }, [password, e2eeSharedKey, setE2EESharedKey]); useEffect(() => { From 3ea908c59f0df40088bbec7486aae9cdec1daf0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 16 Aug 2023 15:38:23 +0200 Subject: [PATCH 28/29] Revert "Remove optional call" This reverts commit 74c70627dcbb5ef6cd266727acaae9e7eff567a3. --- src/e2ee/sharedKeyManagement.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/e2ee/sharedKeyManagement.ts b/src/e2ee/sharedKeyManagement.ts index 07060419..819c16d9 100644 --- a/src/e2ee/sharedKeyManagement.ts +++ b/src/e2ee/sharedKeyManagement.ts @@ -47,7 +47,7 @@ export const useManageRoomSharedKey = (roomId: string): string | null => { if (password === "") return; if (password === e2eeSharedKey) return; - setE2EESharedKey(password); + setE2EESharedKey?.(password); }, [password, e2eeSharedKey, setE2EESharedKey]); useEffect(() => { From d0fe055af6b7081e46c1d97674a04e23857c74cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 16 Aug 2023 15:39:55 +0200 Subject: [PATCH 29/29] Always allow setting a password MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/e2ee/sharedKeyManagement.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/e2ee/sharedKeyManagement.ts b/src/e2ee/sharedKeyManagement.ts index 819c16d9..3af56d6f 100644 --- a/src/e2ee/sharedKeyManagement.ts +++ b/src/e2ee/sharedKeyManagement.ts @@ -26,12 +26,12 @@ export const getRoomSharedKeyLocalStorageKey = (roomId: string): string => export const useInternalRoomSharedKey = ( roomId: string -): [string | null, ((value: string) => void) | null] => { +): [string | null, (value: string) => void] => { const key = useMemo(() => getRoomSharedKeyLocalStorageKey(roomId), [roomId]); const [e2eeEnabled] = useEnableE2EE(); const [roomSharedKey, setRoomSharedKey] = useLocalStorage(key); - return e2eeEnabled ? [roomSharedKey, setRoomSharedKey] : [null, null]; + return [e2eeEnabled ? roomSharedKey : null, setRoomSharedKey]; }; export const useRoomSharedKey = (roomId: string): string | null => { @@ -47,7 +47,7 @@ export const useManageRoomSharedKey = (roomId: string): string | null => { if (password === "") return; if (password === e2eeSharedKey) return; - setE2EESharedKey?.(password); + setE2EESharedKey(password); }, [password, e2eeSharedKey, setE2EESharedKey]); useEffect(() => {