From 1f5ac411f6948745be21ecf24f2093a2ce8f75c6 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 9 Jun 2022 21:56:58 +0100 Subject: [PATCH 1/3] Add warning if incompatible versionsd are being used This will probably be overly sensitive until we start timing out member events (ie. https://github.com/matrix-org/matrix-js-sdk/pull/2446 lands) because lots of calls might have old member events from people who've joined previously. --- src/Header.jsx | 27 ++++++++++++++++- src/Header.module.css | 18 ++++++++++++ src/IncompatibleVersionModal.tsx | 48 +++++++++++++++++++++++++++++++ src/button/Button.jsx | 1 + src/button/Button.module.css | 7 +++++ src/icons/AlertTriangleFilled.svg | 4 +++ src/index.css | 1 + src/room/GroupCallView.jsx | 2 ++ src/room/InCallView.jsx | 13 ++++++++- src/room/useGroupCall.ts | 23 ++++++++++++++- 10 files changed, 141 insertions(+), 3 deletions(-) create mode 100644 src/IncompatibleVersionModal.tsx create mode 100644 src/icons/AlertTriangleFilled.svg diff --git a/src/Header.jsx b/src/Header.jsx index 85039de5..882dac32 100644 --- a/src/Header.jsx +++ b/src/Header.jsx @@ -1,5 +1,5 @@ import classNames from "classnames"; -import React, { useRef } from "react"; +import React, { useCallback, useRef } from "react"; import { Link } from "react-router-dom"; import styles from "./Header.module.css"; import { ReactComponent as Logo } from "./icons/Logo.svg"; @@ -8,6 +8,9 @@ import { ReactComponent as ArrowLeftIcon } from "./icons/ArrowLeft.svg"; import { useButton } from "@react-aria/button"; import { Subtitle } from "./typography/Typography"; import { Avatar } from "./Avatar"; +import { IncompatibleversionModal } from "./IncompatibleversionModal"; +import { useModalTriggerState } from "./Modal"; +import { Button } from "./button"; export function Header({ children, className, ...rest }) { return ( @@ -84,3 +87,25 @@ export function RoomSetupHeaderInfo({ roomName, avatarUrl, ...rest }) { ); } + +export function VersionMismatchWarning({ users, room }) { + const { modalState, modalProps } = useModalTriggerState(); + + const onDetailsClick = useCallback(() => { + modalState.open(); + }, [modalState]); + + if (users.size === 0) return null; + + return ( + + Incomaptible versions! + + {modalState.isOpen && ( + + )} + + ); +} diff --git a/src/Header.module.css b/src/Header.module.css index 04313d9d..cab276a0 100644 --- a/src/Header.module.css +++ b/src/Header.module.css @@ -104,6 +104,24 @@ flex-shrink: 0; } +.versionMismatchWarning { + padding-left: 15px; +} + +.versionMismatchWarning::before { + content: ""; + display: inline-block; + position: relative; + top: 2px; + width: 16px; + height: 16px; + mask-image: url("./icons/AlertTriangleFilled.svg"); + mask-repeat: no-repeat; + mask-size: contain; + background-color: var(--warning); + padding-right: 3px; +} + @media (min-width: 800px) { .headerLogo, .roomAvatar, diff --git a/src/IncompatibleVersionModal.tsx b/src/IncompatibleVersionModal.tsx new file mode 100644 index 00000000..5f8c9a83 --- /dev/null +++ b/src/IncompatibleVersionModal.tsx @@ -0,0 +1,48 @@ +/* +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 { Room } from "matrix-js-sdk"; +import React from "react"; + +import { Modal, ModalContent } from "./Modal"; +import { Body } from "./typography/Typography"; + +interface Props { + userIds: Set; + room: Room; +} + +export const IncompatibleversionModal: React.FC = ({ + userIds, + room, + ...rest +}) => { + const userLis = Array.from(userIds).map((u) => ( +
  • {room.getMember(u).name}
  • + )); + + return ( + + + + Other users are trying to join this call from incompatible versions. + These users should ensure that they have refreshed their browsers: +
      {userLis}
    + +
    +
    + ); +}; diff --git a/src/button/Button.jsx b/src/button/Button.jsx index 1244caf7..aabc3093 100644 --- a/src/button/Button.jsx +++ b/src/button/Button.jsx @@ -41,6 +41,7 @@ export const variantToClassName = { iconCopy: [styles.iconCopyButton], secondaryHangup: [styles.secondaryHangup], dropdown: [styles.dropdownButton], + link: [styles.linkButton], }; export const sizeToClassName = { diff --git a/src/button/Button.module.css b/src/button/Button.module.css index ad5c7e34..5be346ff 100644 --- a/src/button/Button.module.css +++ b/src/button/Button.module.css @@ -207,3 +207,10 @@ limitations under the License. .lg { height: 40px; } + +.linkButton { + background-color: transparent; + border: none; + text-decoration: underline; + cursor: pointer; +} diff --git a/src/icons/AlertTriangleFilled.svg b/src/icons/AlertTriangleFilled.svg new file mode 100644 index 00000000..59a5d518 --- /dev/null +++ b/src/icons/AlertTriangleFilled.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/index.css b/src/index.css index da77b1c5..d5d5fcba 100644 --- a/src/index.css +++ b/src/index.css @@ -29,6 +29,7 @@ limitations under the License. --accent-20: #0dbd8b33; --alert: #ff5b55; --alert-20: #ff5b5533; + --warning: #e8bf37; --links: #0086e6; --primary-content: #ffffff; --secondary-content: #a9b2bc; diff --git a/src/room/GroupCallView.jsx b/src/room/GroupCallView.jsx index 2809b82a..4b84926b 100644 --- a/src/room/GroupCallView.jsx +++ b/src/room/GroupCallView.jsx @@ -53,6 +53,7 @@ export function GroupCallView({ screenshareFeeds, hasLocalParticipant, participants, + unencryptedEventsFromUsers, } = useGroupCall(groupCall); const avatarUrl = useRoomAvatar(groupCall.room); @@ -112,6 +113,7 @@ export function GroupCallView({ localScreenshareFeed={localScreenshareFeed} screenshareFeeds={screenshareFeeds} roomId={roomId} + unencryptedEventsFromUsers={unencryptedEventsFromUsers} /> ); } diff --git a/src/room/InCallView.jsx b/src/room/InCallView.jsx index 2c6240e6..de9f5bc1 100644 --- a/src/room/InCallView.jsx +++ b/src/room/InCallView.jsx @@ -22,7 +22,13 @@ import { VideoButton, ScreenshareButton, } from "../button"; -import { Header, LeftNav, RightNav, RoomHeaderInfo } from "../Header"; +import { + Header, + LeftNav, + RightNav, + RoomHeaderInfo, + VersionMismatchWarning, +} from "../Header"; import { VideoGrid, useVideoGridLayout } from "../video-grid/VideoGrid"; import { VideoTileContainer } from "../video-grid/VideoTileContainer"; import { GroupCallInspector } from "./GroupCallInspector"; @@ -59,6 +65,7 @@ export function InCallView({ isScreensharing, screenshareFeeds, roomId, + unencryptedEventsFromUsers, }) { usePreventScroll(); const [layout, setLayout] = useVideoGridLayout(screenshareFeeds.length > 0); @@ -135,6 +142,10 @@ export function InCallView({
    + diff --git a/src/room/useGroupCall.ts b/src/room/useGroupCall.ts index 6816bcfc..b3697ccf 100644 --- a/src/room/useGroupCall.ts +++ b/src/room/useGroupCall.ts @@ -14,11 +14,14 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { useCallback, useEffect, useState } from "react"; +import { useCallback, useEffect, useReducer, useState } from "react"; import { GroupCallEvent, GroupCallState, GroupCall, + GroupCallErrorCode, + GroupCallUnknownDeviceError, + GroupCallError, } from "matrix-js-sdk/src/webrtc/groupCall"; import { MatrixCall } from "matrix-js-sdk/src/webrtc/call"; import { CallFeed } from "matrix-js-sdk/src/webrtc/callFeed"; @@ -48,6 +51,7 @@ export interface UseGroupCallType { localDesktopCapturerSourceId: string; participants: RoomMember[]; hasLocalParticipant: boolean; + unencryptedEventsFromUsers: Set; } interface State { @@ -106,6 +110,13 @@ export function useGroupCall(groupCall: GroupCall): UseGroupCallType { hasLocalParticipant: false, }); + const [unencryptedEventsFromUsers, addUnencryptedEventUser] = useReducer( + (state: Set, newVal: string) => { + return new Set(state).add(newVal); + }, + new Set() + ); + const updateState = (state: Partial) => setState((prevState) => ({ ...prevState, ...state })); @@ -180,6 +191,13 @@ export function useGroupCall(groupCall: GroupCall): UseGroupCallType { }); } + function onError(e: GroupCallError): void { + if (e.code === GroupCallErrorCode.UnknownDevice) { + const unknownDeviceError = e as GroupCallUnknownDeviceError; + addUnencryptedEventUser(unknownDeviceError.userId); + } + } + groupCall.on(GroupCallEvent.GroupCallStateChanged, onGroupCallStateChanged); groupCall.on(GroupCallEvent.UserMediaFeedsChanged, onUserMediaFeedsChanged); groupCall.on( @@ -194,6 +212,7 @@ export function useGroupCall(groupCall: GroupCall): UseGroupCallType { ); groupCall.on(GroupCallEvent.CallsChanged, onCallsChanged); groupCall.on(GroupCallEvent.ParticipantsChanged, onParticipantsChanged); + groupCall.on(GroupCallEvent.Error, onError); updateState({ error: null, @@ -242,6 +261,7 @@ export function useGroupCall(groupCall: GroupCall): UseGroupCallType { GroupCallEvent.ParticipantsChanged, onParticipantsChanged ); + groupCall.removeListener(GroupCallEvent.Error, onError); groupCall.leave(); }; }, [groupCall]); @@ -319,5 +339,6 @@ export function useGroupCall(groupCall: GroupCall): UseGroupCallType { localDesktopCapturerSourceId, participants, hasLocalParticipant, + unencryptedEventsFromUsers, }; } From 9fc4fbc3e72230df93b21be70dece49ab78fb302 Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 10 Jun 2022 12:06:06 +0100 Subject: [PATCH 2/3] Icon / styling fixes + typo * Use icon from compound * Use warning colour * Fix capitalisation --- src/Header.jsx | 4 ++-- src/Header.module.css | 6 +++--- src/IncompatibleVersionModal.tsx | 2 +- src/button/Button.module.css | 2 +- src/icons/AlertTriangleFilled.svg | 5 ++--- src/index.css | 1 - 6 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/Header.jsx b/src/Header.jsx index 882dac32..d4f83e55 100644 --- a/src/Header.jsx +++ b/src/Header.jsx @@ -8,7 +8,7 @@ import { ReactComponent as ArrowLeftIcon } from "./icons/ArrowLeft.svg"; import { useButton } from "@react-aria/button"; import { Subtitle } from "./typography/Typography"; import { Avatar } from "./Avatar"; -import { IncompatibleversionModal } from "./IncompatibleversionModal"; +import { IncompatibleVersionModal } from "./IncompatibleVersionModal"; import { useModalTriggerState } from "./Modal"; import { Button } from "./button"; @@ -104,7 +104,7 @@ export function VersionMismatchWarning({ users, room }) { Details {modalState.isOpen && ( - + )} ); diff --git a/src/Header.module.css b/src/Header.module.css index cab276a0..7f945819 100644 --- a/src/Header.module.css +++ b/src/Header.module.css @@ -112,14 +112,14 @@ content: ""; display: inline-block; position: relative; - top: 2px; + top: 1px; width: 16px; height: 16px; mask-image: url("./icons/AlertTriangleFilled.svg"); mask-repeat: no-repeat; mask-size: contain; - background-color: var(--warning); - padding-right: 3px; + background-color: var(--alert); + padding-right: 5px; } @media (min-width: 800px) { diff --git a/src/IncompatibleVersionModal.tsx b/src/IncompatibleVersionModal.tsx index 5f8c9a83..6cc5615a 100644 --- a/src/IncompatibleVersionModal.tsx +++ b/src/IncompatibleVersionModal.tsx @@ -25,7 +25,7 @@ interface Props { room: Room; } -export const IncompatibleversionModal: React.FC = ({ +export const IncompatibleVersionModal: React.FC = ({ userIds, room, ...rest diff --git a/src/button/Button.module.css b/src/button/Button.module.css index 5be346ff..53e3b2d5 100644 --- a/src/button/Button.module.css +++ b/src/button/Button.module.css @@ -211,6 +211,6 @@ limitations under the License. .linkButton { background-color: transparent; border: none; - text-decoration: underline; + color: var(--accent); cursor: pointer; } diff --git a/src/icons/AlertTriangleFilled.svg b/src/icons/AlertTriangleFilled.svg index 59a5d518..cbdd429d 100644 --- a/src/icons/AlertTriangleFilled.svg +++ b/src/icons/AlertTriangleFilled.svg @@ -1,4 +1,3 @@ - - - + + diff --git a/src/index.css b/src/index.css index d5d5fcba..da77b1c5 100644 --- a/src/index.css +++ b/src/index.css @@ -29,7 +29,6 @@ limitations under the License. --accent-20: #0dbd8b33; --alert: #ff5b55; --alert-20: #ff5b5533; - --warning: #e8bf37; --links: #0086e6; --primary-content: #ffffff; --secondary-content: #a9b2bc; From d4b211e67894ab07a5bf57e7326b8dfa3a50887b Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 10 Jun 2022 12:07:14 +0100 Subject: [PATCH 3/3] Update js-sdk version --- package.json | 2 +- yarn.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 50a00506..e2331248 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "classnames": "^2.3.1", "color-hash": "^2.0.1", "events": "^3.3.0", - "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#34ef7bc64aa52d1aa78f2e779150922892e287de", + "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#b97b862fb66bafee542e3c0baac35d6576b3a75d", "mermaid": "^8.13.8", "normalize.css": "^8.0.1", "pako": "^2.0.4", diff --git a/yarn.lock b/yarn.lock index b708cd3e..25be29f4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8597,9 +8597,9 @@ matrix-events-sdk@^0.0.1-beta.7: resolved "https://registry.yarnpkg.com/matrix-events-sdk/-/matrix-events-sdk-0.0.1-beta.7.tgz#5ffe45eba1f67cc8d7c2377736c728b322524934" integrity sha512-9jl4wtWanUFSy2sr2lCjErN/oC8KTAtaeaozJtrgot1JiQcEI4Rda9OLgQ7nLKaqb4Z/QUx/fR3XpDzm5Jy1JA== -"matrix-js-sdk@github:matrix-org/matrix-js-sdk#34ef7bc64aa52d1aa78f2e779150922892e287de": +"matrix-js-sdk@github:matrix-org/matrix-js-sdk#b97b862fb66bafee542e3c0baac35d6576b3a75d": version "17.2.0" - resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/34ef7bc64aa52d1aa78f2e779150922892e287de" + resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/b97b862fb66bafee542e3c0baac35d6576b3a75d" dependencies: "@babel/runtime" "^7.12.5" another-json "^0.2.0"