From fc1aaf02bf0266471753474cad210ffc744be62f Mon Sep 17 00:00:00 2001 From: Robert Long Date: Fri, 22 Apr 2022 11:15:39 -0700 Subject: [PATCH 01/20] Use dbkr/ptt matrix-js-sdk package --- package.json | 2 +- yarn.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 9471442e..e5c26a84 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "color-hash": "^2.0.1", "events": "^3.3.0", "lodash-move": "^1.1.1", - "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#robertlong/group-call", + "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#dbkr/ptt", "mermaid": "^8.13.8", "normalize.css": "^8.0.1", "pako": "^2.0.4", diff --git a/yarn.lock b/yarn.lock index 4c921087..7f5dc081 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8012,9 +8012,9 @@ markdown-to-jsx@^7.1.3: resolved "https://registry.yarnpkg.com/markdown-to-jsx/-/markdown-to-jsx-7.1.6.tgz#421487df2a66fe4231d94db653a34da033691e62" integrity sha512-1wrIGZYwIG2gR3yfRmbr4FlQmhaAKoKTpRo4wur4fp9p0njU1Hi7vR8fj0AUKKIcPduiJmPprzmCB5B/GvlC7g== -"matrix-js-sdk@github:matrix-org/matrix-js-sdk#robertlong/group-call": - version "13.0.0" - resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/ba57736bf6d6d99342c64cca5eb6156ee7b9e178" +"matrix-js-sdk@github:matrix-org/matrix-js-sdk#dbkr/ptt": + version "15.1.0" + resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/cc60492376f2622533b0523d87ed4626a2608e30" dependencies: "@babel/runtime" "^7.12.5" another-json "^0.2.0" From 38f9a79bd3d79fad83822b0e49314f00c0270fa0 Mon Sep 17 00:00:00 2001 From: Robert Long Date: Fri, 22 Apr 2022 18:05:48 -0700 Subject: [PATCH 02/20] Initial PTT designs --- src/button/Button.jsx | 1 + src/button/Button.module.css | 9 +++ src/home/RegisteredView.jsx | 12 +++- src/home/RegisteredView.module.css | 4 ++ src/home/UnauthenticatedView.jsx | 11 +++- src/matrix-utils.js | 5 +- src/room/GroupCallView.jsx | 63 ++++++++++++++------- src/room/PTTButton.jsx | 44 +++++++++++++++ src/room/PTTButton.module.css | 11 ++++ src/room/PTTCallView.jsx | 88 ++++++++++++++++++++++++++++++ src/room/PTTCallView.module.css | 40 ++++++++++++++ src/room/PTTFeed.jsx | 10 ++++ src/room/PTTFeed.module.css | 3 + 13 files changed, 277 insertions(+), 24 deletions(-) create mode 100644 src/room/PTTButton.jsx create mode 100644 src/room/PTTButton.module.css create mode 100644 src/room/PTTCallView.jsx create mode 100644 src/room/PTTCallView.module.css create mode 100644 src/room/PTTFeed.jsx create mode 100644 src/room/PTTFeed.module.css diff --git a/src/button/Button.jsx b/src/button/Button.jsx index b6c3df98..ab6ed776 100644 --- a/src/button/Button.jsx +++ b/src/button/Button.jsx @@ -20,6 +20,7 @@ export const variantToClassName = { copy: [styles.copyButton], iconCopy: [styles.iconCopyButton], secondaryCopy: [styles.copyButton], + secondaryHangup: [styles.secondaryHangup], }; export const sizeToClassName = { diff --git a/src/button/Button.module.css b/src/button/Button.module.css index 72450d51..5c3ec300 100644 --- a/src/button/Button.module.css +++ b/src/button/Button.module.css @@ -20,6 +20,7 @@ limitations under the License. .iconButton, .iconCopyButton, .secondary, +.secondaryHangup, .copyButton { position: relative; display: flex; @@ -34,6 +35,7 @@ limitations under the License. } .secondary, +.secondaryHangup, .button, .copyButton { padding: 7px 15px; @@ -53,6 +55,7 @@ limitations under the License. .iconButton:focus, .iconCopyButton:focus, .secondary:focus, +.secondaryHangup:focus, .copyButton:focus { outline: auto; } @@ -119,6 +122,12 @@ limitations under the License. background-color: transparent; } +.secondaryHangup { + color: #ff5b55; + border: 2px solid #ff5b55; + background-color: transparent; +} + .copyButton.secondaryCopy { color: var(--textColor1); border-color: var(--textColor1); diff --git a/src/home/RegisteredView.jsx b/src/home/RegisteredView.jsx index 6e43f205..6849d9f6 100644 --- a/src/home/RegisteredView.jsx +++ b/src/home/RegisteredView.jsx @@ -23,12 +23,13 @@ export function RegisteredView({ client }) { e.preventDefault(); const data = new FormData(e.target); const roomName = data.get("callName"); + const ptt = data.get("ptt") !== null; async function submit() { setError(undefined); setLoading(true); - const roomIdOrAlias = await createRoom(client, roomName); + const roomIdOrAlias = await createRoom(client, roomName, ptt); if (roomIdOrAlias) { history.push(`/room/${roomIdOrAlias}`); @@ -87,6 +88,7 @@ export function RegisteredView({ client }) { required autoComplete="off" /> + + ); +} diff --git a/src/room/PTTButton.module.css b/src/room/PTTButton.module.css new file mode 100644 index 00000000..6bfc1a10 --- /dev/null +++ b/src/room/PTTButton.module.css @@ -0,0 +1,11 @@ +.pttButton { + width: 100vw; + height: 100vh; + max-height: 232px; + max-width: 232px; + border-radius: 116px; + + color: ##fff; + border: 6px solid #0dbd8b; + background-color: #21262C; +} \ No newline at end of file diff --git a/src/room/PTTCallView.jsx b/src/room/PTTCallView.jsx new file mode 100644 index 00000000..29d90da9 --- /dev/null +++ b/src/room/PTTCallView.jsx @@ -0,0 +1,88 @@ +import React from "react"; +import { useModalTriggerState } from "../Modal"; +import { SettingsModal } from "../settings/SettingsModal"; +import { InviteModal } from "./InviteModal"; +import { Button } from "../button"; +import { Header, LeftNav, RightNav, RoomSetupHeaderInfo } from "../Header"; +import { ReactComponent as AddUserIcon } from "../icons/AddUser.svg"; +import { ReactComponent as SettingsIcon } from "../icons/Settings.svg"; +import styles from "./PTTCallView.module.css"; +import { Facepile } from "../Facepile"; +import { PTTButton } from "./PTTButton"; +import { PTTFeed } from "./PTTFeed"; +import { useMediaHandler } from "../settings/useMediaHandler"; + +export function PTTCallView({ + groupCall, + participants, + client, + roomName, + microphoneMuted, + toggleMicrophoneMuted, + userMediaFeeds, + activeSpeaker, + onLeave, + setShowInspector, + showInspector, + roomId, +}) { + const { modalState: inviteModalState, modalProps: inviteModalProps } = + useModalTriggerState(); + const { modalState: settingsModalState, modalProps: settingsModalProps } = + useModalTriggerState(); + const { audioOutput } = useMediaHandler(); + + return ( +
+
+ + + + + + + + +
+
+
+

{`${participants.length} user${ + participants.length > 1 ? "s" : "" + } connected`}

+ +
+
+ +

Press and hold spacebar to talk

+ {userMediaFeeds.map((callFeed) => ( + + ))} +
+ + {settingsModalState.isOpen && ( + + )} + {inviteModalState.isOpen && ( + + )} +
+ ); +} diff --git a/src/room/PTTCallView.module.css b/src/room/PTTCallView.module.css new file mode 100644 index 00000000..f513b798 --- /dev/null +++ b/src/room/PTTCallView.module.css @@ -0,0 +1,40 @@ +.pttCallView { + position: relative; + display: flex; + flex-direction: column; + overflow: hidden; + min-height: 100%; + position: fixed; + height: 100%; + width: 100%; +} + +.headerSeparator { + width: calc(100% - 40px); + height: 1px; + margin: 0 20px; + background-color: #21262C; +} + +.center { + width: 100%; + display: flex; + flex: 1; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.actionTip { + margin-top: 42px; + font-size: 17px; +} + +.participants { + margin: 24px 20px 0 20px; +} + +.participants > p { + color: #A9B2BC; + margin-bottom: 8px; +} \ No newline at end of file diff --git a/src/room/PTTFeed.jsx b/src/room/PTTFeed.jsx new file mode 100644 index 00000000..cc655c76 --- /dev/null +++ b/src/room/PTTFeed.jsx @@ -0,0 +1,10 @@ +import React from "react"; +import { useCallFeed } from "../video-grid/useCallFeed"; +import { useMediaStream } from "../video-grid/useMediaStream"; +import styles from "./PTTFeed.module.css"; + +export function PTTFeed({ callFeed, audioOutputDevice }) { + const { isLocal, stream } = useCallFeed(callFeed); + const mediaRef = useMediaStream(stream, audioOutputDevice, isLocal); + return