Merge branch 'main' of github.com:vector-im/matrix-video-chat
This commit is contained in:
		
				commit
				
					
						0067212512
					
				
			
		
					 12 changed files with 198 additions and 28 deletions
				
			
		
							
								
								
									
										8
									
								
								.env
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								.env
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,8 @@
 | 
			
		|||
####
 | 
			
		||||
# App Config
 | 
			
		||||
# Environment files are documented here:
 | 
			
		||||
# https://vitejs.dev/guide/env-and-mode.html#env-files
 | 
			
		||||
####
 | 
			
		||||
 | 
			
		||||
# The room id for the space to use for listing public group call rooms
 | 
			
		||||
# VITE_PUBLIC_SPACE_ROOM_ID=!hjdfshkdskjdsk:myhomeserver.com
 | 
			
		||||
							
								
								
									
										34
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										34
									
								
								README.md
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -4,10 +4,42 @@ Testbed for full mesh video chat.
 | 
			
		|||
 | 
			
		||||
## Getting Started
 | 
			
		||||
 | 
			
		||||
You must first run a local Synapse server on port 8008
 | 
			
		||||
`matrix-video-chat` is built against the `robertlong/group-call` branch of both [matrix-js-sdk](https://github.com/matrix-org/matrix-js-sdk/pull/1902) and [matrix-react-sdk](https://github.com/matrix-org/matrix-react-sdk/pull/6848). Because of how these packages are configured and Vite's requirements, you will need to clone them locally and use `yarn link` to stich things together.
 | 
			
		||||
 | 
			
		||||
First clone, install, and link `matrix-js-sdk`
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
git clone https://github.com/matrix-org/matrix-js-sdk.git
 | 
			
		||||
cd matrix-js-sdk
 | 
			
		||||
git checkout robertlong/group-call
 | 
			
		||||
yarn
 | 
			
		||||
yarn link
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Then clone, install, link `matrix-js-sdk` into `matrix-react-sdk`, and link `matrix-react-sdk`
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
git clone https://github.com/matrix-org/matrix-react-sdk.git
 | 
			
		||||
cd matrix-react-sdk
 | 
			
		||||
git checkout robertlong/group-call
 | 
			
		||||
yarn
 | 
			
		||||
yarn link matrix-js-sdk
 | 
			
		||||
yarn link
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Next you'll also need [Synapse](https://matrix-org.github.io/synapse/latest/setup/installation.html) installed locally and running on port 8008.
 | 
			
		||||
 | 
			
		||||
Finally we can set up this project.
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
git clone https://github.com/vector-im/matrix-video-chat.git
 | 
			
		||||
cd matrix-video-chat
 | 
			
		||||
yarn
 | 
			
		||||
yarn link matrix-js-sdk
 | 
			
		||||
yarn link matrix-react-sdk
 | 
			
		||||
yarn dev
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Config
 | 
			
		||||
 | 
			
		||||
Configuration options are documented in the `.env` file.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,19 +6,15 @@
 | 
			
		|||
    "serve": "vite preview"
 | 
			
		||||
  },
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@react-spring/web": "^9.2.4",
 | 
			
		||||
    "classnames": "^2.3.1",
 | 
			
		||||
    "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-react-sdk": "github:matrix-org/matrix-react-sdk#robertlong/group-call",
 | 
			
		||||
    "re-resizable": "^6.9.0",
 | 
			
		||||
    "react": "^17.0.0",
 | 
			
		||||
    "react-dom": "^17.0.0",
 | 
			
		||||
    "react-router-dom": "^5.2.0",
 | 
			
		||||
    "react-use-gesture": "^9.1.3",
 | 
			
		||||
    "react-use-measure": "^2.0.4"
 | 
			
		||||
    "react-router-dom": "^5.2.0"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "sass": "^1.42.1",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -277,24 +277,56 @@ function sortRooms(client, rooms) {
 | 
			
		|||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function useRooms(client) {
 | 
			
		||||
export function useGroupCallRooms(client) {
 | 
			
		||||
  const [rooms, setRooms] = useState([]);
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    function updateRooms() {
 | 
			
		||||
      const visibleRooms = client.getVisibleRooms();
 | 
			
		||||
      const sortedRooms = sortRooms(client, visibleRooms);
 | 
			
		||||
      setRooms(sortedRooms);
 | 
			
		||||
      const groupCalls = client.groupCallEventHandler.groupCalls.values();
 | 
			
		||||
      const rooms = Array.from(groupCalls).map((groupCall) => groupCall.room);
 | 
			
		||||
      const sortedRooms = sortRooms(client, rooms);
 | 
			
		||||
      const items = sortedRooms.map((room) => {
 | 
			
		||||
        const groupCall = client.getGroupCallForRoom(room.roomId);
 | 
			
		||||
 | 
			
		||||
        return {
 | 
			
		||||
          room,
 | 
			
		||||
          groupCall,
 | 
			
		||||
          participants: [...groupCall.participants],
 | 
			
		||||
        };
 | 
			
		||||
      });
 | 
			
		||||
      setRooms(items);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    updateRooms();
 | 
			
		||||
 | 
			
		||||
    client.on("Room", updateRooms);
 | 
			
		||||
    client.on("GroupCall.incoming", updateRooms);
 | 
			
		||||
    client.on("GroupCall.participants", updateRooms);
 | 
			
		||||
 | 
			
		||||
    return () => {
 | 
			
		||||
      client.removeListener("Room", updateRooms);
 | 
			
		||||
      client.removeListener("GroupCall.incoming", updateRooms);
 | 
			
		||||
      client.removeListener("GroupCall.participants", updateRooms);
 | 
			
		||||
    };
 | 
			
		||||
  }, []);
 | 
			
		||||
 | 
			
		||||
  return rooms;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function usePublicRooms(client, publicSpaceRoomId, maxRooms = 50) {
 | 
			
		||||
  const [rooms, setRooms] = useState([]);
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    if (publicSpaceRoomId) {
 | 
			
		||||
      client.getRoomHierarchy(publicSpaceRoomId, maxRooms).then(({ rooms }) => {
 | 
			
		||||
        const filteredRooms = rooms.filter(
 | 
			
		||||
          (room) => room.room_type !== "m.space"
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        setRooms(filteredRooms);
 | 
			
		||||
      });
 | 
			
		||||
    } else {
 | 
			
		||||
      setRooms([]);
 | 
			
		||||
    }
 | 
			
		||||
  }, [publicSpaceRoomId]);
 | 
			
		||||
 | 
			
		||||
  return rooms;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										23
									
								
								src/Facepile.jsx
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/Facepile.jsx
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
import React from "react";
 | 
			
		||||
import styles from "./Facepile.module.css";
 | 
			
		||||
import ColorHash from "color-hash";
 | 
			
		||||
 | 
			
		||||
const colorHash = new ColorHash({ lightness: 0.3 });
 | 
			
		||||
 | 
			
		||||
export function Facepile({ participants }) {
 | 
			
		||||
  return (
 | 
			
		||||
    <div
 | 
			
		||||
      className={styles.facepile}
 | 
			
		||||
      title={participants.map((member) => member.name).join(", ")}
 | 
			
		||||
    >
 | 
			
		||||
      {participants.map((member) => (
 | 
			
		||||
        <div
 | 
			
		||||
          className={styles.avatar}
 | 
			
		||||
          style={{ backgroundColor: colorHash.hex(member.name) }}
 | 
			
		||||
        >
 | 
			
		||||
          <span>{member.name.slice(0, 1).toUpperCase()}</span>
 | 
			
		||||
        </div>
 | 
			
		||||
      ))}
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								src/Facepile.module.css
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/Facepile.module.css
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
.facepile {
 | 
			
		||||
  margin: 0 16px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.facepile .avatar {
 | 
			
		||||
  position: relative;
 | 
			
		||||
  width: 20px;
 | 
			
		||||
  height: 20px;
 | 
			
		||||
  border-radius: 20px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.facepile .avatar > * {
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  left: 0;
 | 
			
		||||
  color: #fff;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
  pointer-events: none;
 | 
			
		||||
  font-weight: 600;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.facepile .avatar span {
 | 
			
		||||
  font-size: 14px;
 | 
			
		||||
  width: 20px;
 | 
			
		||||
  line-height: 20px;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										43
									
								
								src/Home.jsx
									
										
									
									
									
								
							
							
						
						
									
										43
									
								
								src/Home.jsx
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -16,7 +16,10 @@ limitations under the License.
 | 
			
		|||
 | 
			
		||||
import React, { useCallback, useRef, useState } from "react";
 | 
			
		||||
import { useHistory, Link } from "react-router-dom";
 | 
			
		||||
import { useRooms } from "./ConferenceCallManagerHooks";
 | 
			
		||||
import {
 | 
			
		||||
  useGroupCallRooms,
 | 
			
		||||
  usePublicRooms,
 | 
			
		||||
} from "./ConferenceCallManagerHooks";
 | 
			
		||||
import { Header, LeftNav, UserNav } from "./Header";
 | 
			
		||||
import ColorHash from "color-hash";
 | 
			
		||||
import styles from "./Home.module.css";
 | 
			
		||||
| 
						 | 
				
			
			@ -26,6 +29,7 @@ import {
 | 
			
		|||
  GroupCallIntent,
 | 
			
		||||
  GroupCallType,
 | 
			
		||||
} from "matrix-js-sdk/src/browser-index";
 | 
			
		||||
import { Facepile } from "./Facepile";
 | 
			
		||||
 | 
			
		||||
const colorHash = new ColorHash({ lightness: 0.3 });
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -34,7 +38,11 @@ export function Home({ client, onLogout }) {
 | 
			
		|||
  const roomNameRef = useRef();
 | 
			
		||||
  const guestAccessRef = useRef();
 | 
			
		||||
  const [createRoomError, setCreateRoomError] = useState();
 | 
			
		||||
  const rooms = useRooms(client);
 | 
			
		||||
  const rooms = useGroupCallRooms(client);
 | 
			
		||||
  const publicRooms = usePublicRooms(
 | 
			
		||||
    client,
 | 
			
		||||
    import.meta.env.VITE_PUBLIC_SPACE_ROOM_ID
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  const onCreateRoom = useCallback(
 | 
			
		||||
    (e) => {
 | 
			
		||||
| 
						 | 
				
			
			@ -139,14 +147,15 @@ export function Home({ client, onLogout }) {
 | 
			
		|||
                </FieldRow>
 | 
			
		||||
              </form>
 | 
			
		||||
            </section>
 | 
			
		||||
            {publicRooms.length > 0 && (
 | 
			
		||||
              <section>
 | 
			
		||||
              <h3>Recent Rooms</h3>
 | 
			
		||||
                <h3>Public Rooms</h3>
 | 
			
		||||
                <div className={styles.roomList}>
 | 
			
		||||
                {rooms.map((room) => (
 | 
			
		||||
                  {publicRooms.map((room) => (
 | 
			
		||||
                    <Link
 | 
			
		||||
                      className={styles.roomListItem}
 | 
			
		||||
                    key={room.roomId}
 | 
			
		||||
                    to={`/room/${room.roomId}`}
 | 
			
		||||
                      key={room.room_id}
 | 
			
		||||
                      to={`/room/${room.room_id}`}
 | 
			
		||||
                    >
 | 
			
		||||
                      <div
 | 
			
		||||
                        className={styles.roomAvatar}
 | 
			
		||||
| 
						 | 
				
			
			@ -159,6 +168,28 @@ export function Home({ client, onLogout }) {
 | 
			
		|||
                  ))}
 | 
			
		||||
                </div>
 | 
			
		||||
              </section>
 | 
			
		||||
            )}
 | 
			
		||||
            <section>
 | 
			
		||||
              <h3>Recent Rooms</h3>
 | 
			
		||||
              <div className={styles.roomList}>
 | 
			
		||||
                {rooms.map(({ room, participants }) => (
 | 
			
		||||
                  <Link
 | 
			
		||||
                    className={styles.roomListItem}
 | 
			
		||||
                    key={room.roomId}
 | 
			
		||||
                    to={`/room/${room.roomId}`}
 | 
			
		||||
                  >
 | 
			
		||||
                    <div
 | 
			
		||||
                      className={styles.roomAvatar}
 | 
			
		||||
                      style={{ backgroundColor: colorHash.hex(room.name) }}
 | 
			
		||||
                    >
 | 
			
		||||
                      <span>{room.name.slice(0, 1)}</span>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div className={styles.roomName}>{room.name}</div>
 | 
			
		||||
                    <Facepile participants={participants} />
 | 
			
		||||
                  </Link>
 | 
			
		||||
                ))}
 | 
			
		||||
              </div>
 | 
			
		||||
            </section>
 | 
			
		||||
          </Modal>
 | 
			
		||||
        </Center>
 | 
			
		||||
      </Content>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,6 +22,7 @@ import {
 | 
			
		|||
  MicButton,
 | 
			
		||||
  VideoButton,
 | 
			
		||||
  LayoutToggleButton,
 | 
			
		||||
  ScreenshareButton,
 | 
			
		||||
} from "./RoomButton";
 | 
			
		||||
import { Header, LeftNav, RightNav, CenterNav } from "./Header";
 | 
			
		||||
import { Button, ErrorMessage } from "./Input";
 | 
			
		||||
| 
						 | 
				
			
			@ -270,8 +271,6 @@ function InRoomView({
 | 
			
		|||
      });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    console.log("items changed", participants);
 | 
			
		||||
 | 
			
		||||
    return participants;
 | 
			
		||||
  }, [userMediaFeeds, activeSpeaker, screenshareFeeds]);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -303,7 +302,10 @@ function InRoomView({
 | 
			
		|||
          enabled={localVideoMuted}
 | 
			
		||||
          onClick={toggleLocalVideoMuted}
 | 
			
		||||
        />
 | 
			
		||||
        <VideoButton enabled={isScreensharing} onClick={toggleScreensharing} />
 | 
			
		||||
        <ScreenshareButton
 | 
			
		||||
          enabled={isScreensharing}
 | 
			
		||||
          onClick={toggleScreensharing}
 | 
			
		||||
        />
 | 
			
		||||
        <HangupButton onClick={onLeave} />
 | 
			
		||||
      </div>
 | 
			
		||||
    </>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,7 @@ import { ReactComponent as HangupIcon } from "./icons/Hangup.svg";
 | 
			
		|||
import { ReactComponent as SettingsIcon } from "./icons/Settings.svg";
 | 
			
		||||
import { ReactComponent as GridIcon } from "./icons/Grid.svg";
 | 
			
		||||
import { ReactComponent as SpeakerIcon } from "./icons/Speaker.svg";
 | 
			
		||||
import { ReactComponent as ScreenshareIcon } from "./icons/Screenshare.svg";
 | 
			
		||||
 | 
			
		||||
export function RoomButton({ on, className, children, ...rest }) {
 | 
			
		||||
  return (
 | 
			
		||||
| 
						 | 
				
			
			@ -37,6 +38,18 @@ export function VideoButton({ enabled, ...rest }) {
 | 
			
		|||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function ScreenshareButton({ enabled, className, ...rest }) {
 | 
			
		||||
  return (
 | 
			
		||||
    <RoomButton
 | 
			
		||||
      className={classNames(styles.screenshareButton, className)}
 | 
			
		||||
      {...rest}
 | 
			
		||||
      on={enabled}
 | 
			
		||||
    >
 | 
			
		||||
      <ScreenshareIcon />
 | 
			
		||||
    </RoomButton>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function HangupButton({ className, ...rest }) {
 | 
			
		||||
  return (
 | 
			
		||||
    <RoomButton
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,7 +14,8 @@ See the License for the specific language governing permissions and
 | 
			
		|||
limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
.roomButton, .headerButton {
 | 
			
		||||
.roomButton,
 | 
			
		||||
.headerButton {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: center;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
| 
						 | 
				
			
			@ -32,11 +33,10 @@ limitations under the License.
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
.roomButton:hover {
 | 
			
		||||
  background-color: #8D97A5;
 | 
			
		||||
  background-color: #8d97a5;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.roomButton:active {
 | 
			
		||||
  
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.roomButton.on {
 | 
			
		||||
| 
						 | 
				
			
			@ -50,11 +50,11 @@ limitations under the License.
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
.headerButton svg * {
 | 
			
		||||
  fill: #8E99A4;
 | 
			
		||||
  fill: #8e99a4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.headerButton:hover {
 | 
			
		||||
  background-color: #8D97A5;
 | 
			
		||||
  background-color: #8d97a5;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.headerButton:hover svg * {
 | 
			
		||||
| 
						 | 
				
			
			@ -62,9 +62,14 @@ limitations under the License.
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
.headerButton.on svg * {
 | 
			
		||||
  fill: #0DBD8B
 | 
			
		||||
  fill: #0dbd8b;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hangupButton, .hangupButton:hover {
 | 
			
		||||
  background-color: #FF5B55;
 | 
			
		||||
.hangupButton,
 | 
			
		||||
.hangupButton:hover {
 | 
			
		||||
  background-color: #ff5b55;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.screenshareButton.on svg * {
 | 
			
		||||
  fill: #0dbd8b;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										3
									
								
								src/icons/Screenshare.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/icons/Screenshare.svg
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
<svg width="24" height="17" viewBox="0 0 24 17" fill="none" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.75 0.5C2.09315 0.5 0.75 1.84314 0.75 3.5V13.5713C0.75 15.2282 2.09315 16.5713 3.75 16.5713H20.2499C21.9067 16.5713 23.2499 15.2282 23.2499 13.5713V3.5C23.2499 1.84315 21.9067 0.5 20.2499 0.5H3.75ZM12.7998 11.9106C12.7998 12.3524 12.4416 12.7106 11.9998 12.7106C11.558 12.7106 11.1998 12.3524 11.1998 11.9106L11.1998 7.09206L9.43158 8.86029C9.11916 9.17271 8.61263 9.17271 8.30021 8.86029C7.98779 8.54787 7.98779 8.04134 8.30021 7.72892L11.4341 4.59501C11.7465 4.28259 12.2531 4.28259 12.5655 4.59501L15.6994 7.72892C16.0118 8.04134 16.0118 8.54787 15.6994 8.86029C15.387 9.17271 14.8805 9.17271 14.568 8.86029L12.7998 7.09206L12.7998 11.9106Z" fill="white"/>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 814 B  | 
| 
						 | 
				
			
			@ -1602,7 +1602,7 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3
 | 
			
		|||
 | 
			
		||||
"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/326aec9f9ea7b29c6c07bbcc84dc5288300abc58"
 | 
			
		||||
  resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/ba57736bf6d6d99342c64cca5eb6156ee7b9e178"
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@babel/runtime" "^7.12.5"
 | 
			
		||||
    another-json "^0.2.0"
 | 
			
		||||
| 
						 | 
				
			
			@ -1617,7 +1617,7 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3
 | 
			
		|||
 | 
			
		||||
"matrix-react-sdk@github:matrix-org/matrix-react-sdk#robertlong/group-call":
 | 
			
		||||
  version "3.31.0"
 | 
			
		||||
  resolved "https://codeload.github.com/matrix-org/matrix-react-sdk/tar.gz/7775ac9956bc8fba437fbb15f5cf56b2ee554903"
 | 
			
		||||
  resolved "https://codeload.github.com/matrix-org/matrix-react-sdk/tar.gz/fc43d1d2f742f92a1ffd113ec557565d74e98167"
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@babel/runtime" "^7.12.5"
 | 
			
		||||
    "@react-spring/web" "^9.2.4"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue