diff --git a/.gitignore b/.gitignore index 2eb9aa0f6..1d4900b27 100644 --- a/.gitignore +++ b/.gitignore @@ -288,3 +288,4 @@ buck-out/ packages/restapi/yarn.lock yarn.lock *.env +**/.next diff --git a/packages/demoreact/src/app/SpaceTest/AddSpeakersToSpaceTest.tsx b/packages/demoreact/src/app/SpaceTest/AddSpeakersToSpaceTest.tsx index ab4b31b42..2b95f9c6b 100644 --- a/packages/demoreact/src/app/SpaceTest/AddSpeakersToSpaceTest.tsx +++ b/packages/demoreact/src/app/SpaceTest/AddSpeakersToSpaceTest.tsx @@ -39,7 +39,6 @@ const AddSpeakersToSpaceTest = () => { spaceId: spaceId, speakers: speakerAddress ? speakerAddress.split(',') : [], env, - account: account, signer: librarySigner, }); setSendResponse(response); diff --git a/packages/demoreact/src/app/SpaceTest/CreateSpaceTest.tsx b/packages/demoreact/src/app/SpaceTest/CreateSpaceTest.tsx index 9e1e543be..ab4bcf2f3 100644 --- a/packages/demoreact/src/app/SpaceTest/CreateSpaceTest.tsx +++ b/packages/demoreact/src/app/SpaceTest/CreateSpaceTest.tsx @@ -105,7 +105,6 @@ const CreateSpaceTest = () => { numberOfNFTs: numberOfNFTs != null ? Number(numberOfNFTs) : undefined, contractAddressERC20, numberOfERC20: numberOfERC20 != null ? Number(numberOfERC20) : undefined, - account: isCAIP ? walletToPCAIP10(account) : account, signer: librarySigner, env, meta: meta, diff --git a/packages/demoreact/src/app/SpaceTest/RemoveSpeakersFromSpaceTest.tsx b/packages/demoreact/src/app/SpaceTest/RemoveSpeakersFromSpaceTest.tsx index 117f13135..411a0f398 100644 --- a/packages/demoreact/src/app/SpaceTest/RemoveSpeakersFromSpaceTest.tsx +++ b/packages/demoreact/src/app/SpaceTest/RemoveSpeakersFromSpaceTest.tsx @@ -39,7 +39,6 @@ const RemoveSpeakersFromSpaceTest = () => { spaceId: spaceId, speakers: speakerAddress ? speakerAddress.split(',') : [], env, - account: account, signer: librarySigner, }); setSendResponse(response); diff --git a/packages/demoreact/src/app/SpaceTest/StartSpaceTest.tsx b/packages/demoreact/src/app/SpaceTest/StartSpaceTest.tsx index d27c48455..90364c22d 100644 --- a/packages/demoreact/src/app/SpaceTest/StartSpaceTest.tsx +++ b/packages/demoreact/src/app/SpaceTest/StartSpaceTest.tsx @@ -31,12 +31,12 @@ const StartSpaceTest = () => { setLoading(true); const librarySigner = await library.getSigner(); - const response = await PushAPI.space.start({ - spaceId: spaceId, - signer: librarySigner, - env: env, - }); - setSendResponse(response); + // const response = await PushAPI.space.start({ + // spaceId: spaceId, + // signer: librarySigner, + // env: env, + // }); + // setSendResponse(response); } catch (e) { console.error(e); diff --git a/packages/demoreact/src/app/SpaceTest/StopSpaceTest.tsx b/packages/demoreact/src/app/SpaceTest/StopSpaceTest.tsx index fe361f17c..a2182ee3d 100644 --- a/packages/demoreact/src/app/SpaceTest/StopSpaceTest.tsx +++ b/packages/demoreact/src/app/SpaceTest/StopSpaceTest.tsx @@ -31,12 +31,12 @@ const StopSpaceTest = () => { setLoading(true); const librarySigner = await library.getSigner(); - const response = await PushAPI.space.stop({ - spaceId: spaceId, - signer: librarySigner, - env: env, - }); - setSendResponse(response); + // const response = await PushAPI.space.stop({ + // spaceId: spaceId, + // signer: librarySigner, + // env: env, + // }); + // setSendResponse(response); } catch (e) { console.error(e); diff --git a/packages/demoreact/src/app/SpaceTest/UpdateSpaceTest.tsx b/packages/demoreact/src/app/SpaceTest/UpdateSpaceTest.tsx index 7e56f3ce4..6a893f472 100644 --- a/packages/demoreact/src/app/SpaceTest/UpdateSpaceTest.tsx +++ b/packages/demoreact/src/app/SpaceTest/UpdateSpaceTest.tsx @@ -48,7 +48,7 @@ const UpdateSpaceTest = () => { setMembers((e.target as HTMLInputElement).value); }; - + const updateAdmins= (e: React.SyntheticEvent) => { setAdmins((e.target as HTMLInputElement).value); }; @@ -81,7 +81,6 @@ const UpdateSpaceTest = () => { spaceDescription, members: members.split(','), admins: admins.split(','), - account: isCAIP ? walletToPCAIP10(account) : account, signer: librarySigner, env, scheduleAt: new Date(scheduleAt) , @@ -148,7 +147,7 @@ const UpdateSpaceTest = () => { style={{ width: 400, height: 30 }} /> - + { + const { CreateSpaceComponent } = useSpaceComponents(); + + return +} diff --git a/packages/demoreact/src/app/SpaceUITest/SpaceBanner.tsx b/packages/demoreact/src/app/SpaceUITest/SpaceBanner.tsx new file mode 100644 index 000000000..44c50caee --- /dev/null +++ b/packages/demoreact/src/app/SpaceUITest/SpaceBanner.tsx @@ -0,0 +1,63 @@ +import React, { useState } from 'react'; + +import { useSpaceComponents } from './useSpaceComponents'; +import { Section, SectionItem } from '../components/StyledComponents'; +import Dropdown from '../components/Dropdown'; + +export const SpaceBanner = () => { + const { SpaceBannerComponent } = useSpaceComponents(); + + const [spaceId, setSpaceId] = useState(''); + const [orientation, setOrientation] = useState('maximized'); + + const updateSpaceId = (e: React.SyntheticEvent) => { + setSpaceId((e.target as HTMLInputElement).value); + }; + + const updateOrientation = (e: any) => { + setOrientation(e.target.value); + }; + + const onClickHandler = (arg: string) => { + console.log(arg); + } + + return ( +
+
+ + + + + +
+ +
+ ); +}; diff --git a/packages/demoreact/src/app/SpaceUITest/SpaceFeed.tsx b/packages/demoreact/src/app/SpaceUITest/SpaceFeed.tsx new file mode 100644 index 000000000..5b204b591 --- /dev/null +++ b/packages/demoreact/src/app/SpaceUITest/SpaceFeed.tsx @@ -0,0 +1,85 @@ +import React, { useState } from 'react'; +import { useSpaceComponents } from './useSpaceComponents'; +import { Checkbox } from '../components/Checkbox'; + +export const SpaceFeed = () => { + const { SpaceFeedComponent } = useSpaceComponents(); + const [address, setAddress] = useState(); + const [showTab, setShowTab] = useState(true); + const [horizontal, setHorizontal] = useState(false); + const [width, setWidth] = useState(); + const [height, setHeight] = useState(500); + const [sortingOrder, setSortingOrder] = useState([]); + + const handleShowTab = () => { + setShowTab(!showTab); + }; + + const handleHorizontal = () => { + setHorizontal(!horizontal); + }; + + const handleAddressChange = (e: React.SyntheticEvent) => { + setAddress((e.target as HTMLInputElement).value); + }; + + const handleWidthChange = (e: React.SyntheticEvent) => { + setWidth((e.target as HTMLInputElement).value as unknown as number); + }; + + const handleHeightChange = (e: React.SyntheticEvent) => { + setHeight((e.target as HTMLInputElement).value as unknown as number); + }; + + return ( + <> + + + +
+ +
+ +
+ +
+ +
+ + { + console.log('spaceId: ', spaceId); + }} + /> + + ); +}; diff --git a/packages/demoreact/src/app/SpaceUITest/SpaceInvites.tsx b/packages/demoreact/src/app/SpaceUITest/SpaceInvites.tsx new file mode 100644 index 000000000..8b1493262 --- /dev/null +++ b/packages/demoreact/src/app/SpaceUITest/SpaceInvites.tsx @@ -0,0 +1,9 @@ +import { useSpaceComponents } from "./useSpaceComponents" + +export const SpaceInvitesComponent = () => { + const { SpaceInvitesComponent } = useSpaceComponents(); + + return ( + + ) +} diff --git a/packages/demoreact/src/app/SpaceUITest/SpaceUITest.tsx b/packages/demoreact/src/app/SpaceUITest/SpaceUITest.tsx new file mode 100644 index 000000000..ce3f9c8bf --- /dev/null +++ b/packages/demoreact/src/app/SpaceUITest/SpaceUITest.tsx @@ -0,0 +1,52 @@ +import { useState } from 'react'; +import styled from 'styled-components'; +import { Link } from 'react-router-dom'; +import { + Section, +} from '../components/StyledComponents'; +import Loader from '../components/Loader'; + +const SpaceUITest = () => { + const [isLoading, setIsLoading] = useState(false); + + const NavMenu = styled.div` + display: flex; + flex-wrap: wrap; + gap: 30px; + justify-content: center; + + @media only screen and (max-width: 900px) { + flex-direction: column; + } + `; + + return ( +
+

Space UI Test page

+ + + +
+ + + SPACES WIDGET + + + SPACES FEED + + + SPACES BANNER + + + CREATE SPACE + + + SPACES INVITES + + +
+
+ ); +}; + +export default SpaceUITest; diff --git a/packages/demoreact/src/app/SpaceUITest/SpaceWidget.tsx b/packages/demoreact/src/app/SpaceUITest/SpaceWidget.tsx new file mode 100644 index 000000000..1bb487857 --- /dev/null +++ b/packages/demoreact/src/app/SpaceUITest/SpaceWidget.tsx @@ -0,0 +1,155 @@ +import { useState } from "react"; +import { Section, SectionItem } from "../components/StyledComponents"; +import SpaceUITest from "./SpaceUITest"; +import { useSpaceComponents } from "./useSpaceComponents" + +export const SpaceWidget = () => { + const { SpaceWidgetComponent } = useSpaceComponents(); + const [spaceId, setSpaceId] = useState(''); + const [width, setWidth] = useState(''); + const [zIndex, setZIndex] = useState('1000'); + const [shareUrl, setShareUrl] = useState(''); + const [isHost, setisHost] = useState(false); + const [isLive, setisLive] = useState(false); + const [isMember, setisMember] = useState(false); + const [isJoined, setisJoined] = useState(false); + const [isTimeToStartSpace, setisTimeToStartSpace] = useState(false); + + const updateSpaceId = (e: React.SyntheticEvent) => { + setSpaceId((e.target as HTMLInputElement).value); + }; + + const updateWidgetWidth = (e: React.SyntheticEvent) => { + setWidth((e.target as HTMLInputElement).value); + }; + + const updateZIndex = (e: React.SyntheticEvent) => { + setZIndex((e.target as HTMLInputElement).value); + }; + + const updateShareUrl = (e: React.SyntheticEvent) => { + setShareUrl((e.target as HTMLInputElement).value); + }; + + const updateIsHost = (e: React.SyntheticEvent) => { + setisHost((e.target as HTMLInputElement).checked); + }; + + const updateIsLive = (e: React.SyntheticEvent) => { + setisLive((e.target as HTMLInputElement).checked); + }; + + const updateIsMember = (e: React.SyntheticEvent) => { + setisMember((e.target as HTMLInputElement).checked); + }; + + const updateIsJoined = (e: React.SyntheticEvent) => { + setisJoined((e.target as HTMLInputElement).checked); + }; + + const updateIsTimeToStartSpace = (e: React.SyntheticEvent) => { + setisTimeToStartSpace((e.target as HTMLInputElement).checked); + }; + + return ( +
+ +

Space Widget Test page

+
+ + + + + + + + + + + + + + + + +
Temp Props
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ ); +} diff --git a/packages/demoreact/src/app/SpaceUITest/index.tsx b/packages/demoreact/src/app/SpaceUITest/index.tsx new file mode 100644 index 000000000..5e3c4137f --- /dev/null +++ b/packages/demoreact/src/app/SpaceUITest/index.tsx @@ -0,0 +1,29 @@ +import { SpacesUIProvider } from '@pushprotocol/uiweb'; +import { useSpaceComponents } from './useSpaceComponents'; + +export * from './SpaceUITest'; +export * from './SpaceWidget'; +export * from './SpaceFeed'; +export * from "./SpaceBanner"; +export * from "./CreateSpaceComponent"; +export * from "./SpaceInvites"; + +export interface ISpacesComponentProps { + children: React.ReactNode; +} + +export const SpacesComponentProvider = ({ + children, +}: ISpacesComponentProps) => { + const { spaceUI } = useSpaceComponents(); + + const customtheme = { + statusColorError: 'red', + } + + return ( + + {children} + + ); +}; diff --git a/packages/demoreact/src/app/SpaceUITest/useSpaceComponents.tsx b/packages/demoreact/src/app/SpaceUITest/useSpaceComponents.tsx new file mode 100644 index 000000000..5c0ee9ffc --- /dev/null +++ b/packages/demoreact/src/app/SpaceUITest/useSpaceComponents.tsx @@ -0,0 +1,64 @@ +import { + ISpaceFeedProps, + ISpaceBannerProps, + ISpaceWidgetProps, + ISpaceCreateWidgetProps, + SpacesUI, + ISpaceInvitesProps, +} from '@pushprotocol/uiweb'; +import React, { useContext, useEffect, useState } from 'react'; +import { EnvContext, Web3Context } from '../context'; +import * as PushAPI from '@pushprotocol/restapi'; + +export interface IUseSpaceReturnValues { + spaceUI: SpacesUI; + SpaceInvitesComponent: React.FC; + SpaceWidgetComponent: React.FC; + SpaceFeedComponent: React.FC; + SpaceBannerComponent: React.FC; + CreateSpaceComponent: React.FC; +} + +export const useSpaceComponents = (): IUseSpaceReturnValues => { + const { account, library } = useContext(Web3Context); + const { env } = useContext(EnvContext); + const librarySigner = library?.getSigner(); + + const [pgpPrivateKey, setPgpPrivateKey] = useState(''); + + const spaceUI = new SpacesUI({ + account: account, + signer: librarySigner, + pgpPrivateKey: pgpPrivateKey, + env: env, + }); + + useEffect(() => { + (async () => { + if (!account || !env || !library) return; + + const user = await PushAPI.user.get({ account, env }); + let pgpPrivateKey; + const librarySigner = await library.getSigner(account); + if (user?.encryptedPrivateKey) { + pgpPrivateKey = await PushAPI.chat.decryptPGPKey({ + encryptedPGPPrivateKey: user.encryptedPrivateKey, + account, + signer: librarySigner, + env, + }); + } + + setPgpPrivateKey(pgpPrivateKey); + })(); + }, [account, env, library]); + + return { + spaceUI, + SpaceInvitesComponent: spaceUI.SpaceInvites, + SpaceWidgetComponent: spaceUI.SpaceWidget, + SpaceBannerComponent: spaceUI.SpaceBanner, + SpaceFeedComponent: spaceUI.SpaceFeed, + CreateSpaceComponent: spaceUI.SpaceCreationButtonWidget, + }; +}; diff --git a/packages/demoreact/src/app/app.tsx b/packages/demoreact/src/app/app.tsx index fb971e471..69d9c8f35 100644 --- a/packages/demoreact/src/app/app.tsx +++ b/packages/demoreact/src/app/app.tsx @@ -53,6 +53,16 @@ import RemoveSpeakersFromSpaceTest from './SpaceTest/RemoveSpeakersFromSpaceTest import GetSpacesTest from './SpaceTest/GetSpacesTest'; import GetSpacesRequestsTest from './SpaceTest/GetSpacesRequestsTest'; import GetSpacesTrendingTest from './SpaceTest/GetSpacesTrendingTest'; +import SpaceUITest from './SpaceUITest/SpaceUITest'; +import { + SpacesComponentProvider, + SpaceWidget, + SpaceBanner, + SpaceFeed, + CreateSpaceComponent, + SpaceInvitesComponent +} from './SpaceUITest'; +import { useSpaceComponents } from './SpaceUITest/useSpaceComponents'; window.Buffer = window.Buffer || Buffer; @@ -74,7 +84,7 @@ const StyledApp = styled.div` justify-content: center; text-decoration: none; - &: hover { + &:hover { text-decoration: underline; } } @@ -127,6 +137,7 @@ const StyledApp = styled.div` const NavMenu = styled.div` display: flex; + flex-flow: wrap; gap: 30px; justify-content: center; @@ -150,6 +161,9 @@ export function App() { const [env, setEnv] = useState(ENV.PROD); const [isCAIP, setIsCAIP] = useState(false); + const { SpaceWidgetComponent } = useSpaceComponents(); + const [spaceId, setSpaceId] = useState(''); + const socketData = useSDKSocket({ account: web3Data.account, chainId: web3Data.chainId, @@ -199,101 +213,159 @@ export function App() { {checkForWeb3Data(web3Data) ? ( - - - - NOTIFICATIONS - - - SECRET NOTIFICATION - - - CHANNELS - - - ALIAS - - - DELEGATIONS - - - PAYLOADS - - - SOCKET - - - EMBED - - - CHAT - - - SPACE - - - } - /> - } /> - } /> - - } /> - - } /> - - } /> - - } /> - - } /> - - } /> - - } /> - } /> - - {/* chat method routes */} - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - - {/* spaces method routes */} - - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - - - + + + + + NOTIFICATIONS + + + SECRET NOTIFICATION + + + CHANNELS + + + ALIAS + + + DELEGATIONS + + + PAYLOADS + + + SOCKET + + + EMBED + + + CHAT + + + SPACE + + + SPACE UI + + + } + /> + } + /> + } /> + + } /> + + } /> + + } /> + + } /> + + } /> + + } /> + + } /> + } /> + + } /> + + {/* chat method routes */} + } /> + } + /> + } /> + } + /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } + /> + } + /> + } + /> + } + /> + } /> + + {/* spaces method routes */} + } /> + } /> + } /> + } /> + } + /> + } /> + } /> + } + /> + } + /> + } + /> + } + /> + } /> + } + /> + } + /> + + {/* spaces ui components routes */} + } /> + } /> + } /> + } /> + } + /> + + + + ) : null} diff --git a/packages/examples/sdk-frontend/video/README.md b/packages/examples/sdk-frontend/README.md similarity index 100% rename from packages/examples/sdk-frontend/video/README.md rename to packages/examples/sdk-frontend/README.md diff --git a/packages/examples/sdk-frontend/components/Spaces/Checkbox.tsx b/packages/examples/sdk-frontend/components/Spaces/Checkbox.tsx new file mode 100644 index 000000000..58e759c59 --- /dev/null +++ b/packages/examples/sdk-frontend/components/Spaces/Checkbox.tsx @@ -0,0 +1,15 @@ +import React from 'react'; + +export const Checkbox = (props: { id: string, label: string, value?: boolean, onChange: () => void }) => { + return ( +
+ + +
+ ); + }; \ No newline at end of file diff --git a/packages/examples/sdk-frontend/components/Spaces/Dropdown.tsx b/packages/examples/sdk-frontend/components/Spaces/Dropdown.tsx new file mode 100644 index 000000000..b97e8e9ee --- /dev/null +++ b/packages/examples/sdk-frontend/components/Spaces/Dropdown.tsx @@ -0,0 +1,35 @@ +import React from 'react'; + +type DropdownOptionsType = { + value: string, + label: string +}; + +const Dropdown = ({ + style, + label, + value, + width, + options, + onChange +}: { + style?: any, + label: string, + value?: string, + width?: string | number, + options: DropdownOptionsType[], + onChange: (arg0: any) => void +}) => { + return ( + + ); +}; + +export default Dropdown; \ No newline at end of file diff --git a/packages/examples/sdk-frontend/components/Spaces/StyledComponents.tsx b/packages/examples/sdk-frontend/components/Spaces/StyledComponents.tsx new file mode 100644 index 000000000..cb13603e4 --- /dev/null +++ b/packages/examples/sdk-frontend/components/Spaces/StyledComponents.tsx @@ -0,0 +1,61 @@ +import styled from 'styled-components'; + +export const Section = styled.section` + border: 2px solid #ccc; + padding: 25px; + margin: 10px 0; + display: flex; + flex-direction: column; + background-color: ${(props) => props.theme === 'dark' ? '#000' : '#fff'}; + + & .headerText { + color: ${(props) => props.theme === 'dark' ? '#fff' : '#000'}; + font-size: 2rem; + } + + & .subHeaderText { + color: ${(props) => props.theme === 'dark' ? '#fff' : '#000'}; + font-size: 1.2rem; + } +` + +export const SectionItem = styled.div` + display: flex; + gap: 15px; + align-items: center; + + & label.consoleLabel { + color: green; + } +`; + +export const SectionItemCustom = styled(SectionItem)` + justify-content: flex-end; + align-items: center; + margin: 20px 0px; +`; + +export const CodeFormatter = styled.pre` + background: #eeebeb; + padding: 15px; + border-radius: 7px; +`; + +export const SectionButton = styled.button` + font-family: "Source Sans Pro",Arial,sans-serif; + font-size: 16px; + display: flex; + margin-right: 15px; + padding: 15px 20px; + background: #674C9F; + border: 0; + border-radius: 7px; + box-shadow: rgb(0 0 0 / 52%) 0px 0px 5px; + color: #fff; + justify-content: center; + + &:hover { + cursor: pointer; + background: rgb(226, 8, 128); + } +`; diff --git a/packages/examples/sdk-frontend/components/Spaces/index.ts b/packages/examples/sdk-frontend/components/Spaces/index.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/examples/sdk-frontend/components/Spaces/useSpaceComponent.tsx b/packages/examples/sdk-frontend/components/Spaces/useSpaceComponent.tsx new file mode 100644 index 000000000..ccad60268 --- /dev/null +++ b/packages/examples/sdk-frontend/components/Spaces/useSpaceComponent.tsx @@ -0,0 +1,72 @@ +import { + ISpaceFeedProps, + ISpaceBannerProps, + ISpaceWidgetProps, + ISpaceCreateWidgetProps, + SpacesUI, + ISpaceInvitesProps, +} from '@pushprotocol/uiweb'; +import { useAccount, useNetwork, useSigner } from 'wagmi'; +import React, { useContext, useEffect, useState } from 'react'; +import { ENV } from '@pushprotocol/restapi/src/lib/constants'; +import * as PushAPI from '@pushprotocol/restapi'; +import { is } from 'date-fns/locale'; + +export interface IUseSpaceReturnValues { + spaceUI: SpacesUI; + SpaceInvitesComponent: React.FC; + SpaceWidgetComponent: React.FC; + SpaceFeedComponent: React.FC; + SpaceBannerComponent: React.FC; + CreateSpaceComponent: React.FC; +} + +export const useSpaceComponents = (): IUseSpaceReturnValues => { + const env = ENV.DEV; + + const { address, isConnected } = useAccount(); + const { chain } = useNetwork(); + const { data: signer } = useSigner(); + + const [pgpPrivateKey, setPgpPrivateKey] = useState(''); + + console.log('address: ', address, isConnected); + + const spaceUI = new SpacesUI({ + account: address as string, + signer: signer as PushAPI.SignerType, + pgpPrivateKey: pgpPrivateKey, + env: env, + }); + + useEffect(() => { + (async () => { + if (!signer || !address || !chain?.id) return; + + const user = await PushAPI.user.get({ + account: address, + env, + }); + let pgpPrivateKey = null; + if (user?.encryptedPrivateKey) { + pgpPrivateKey = await PushAPI.chat.decryptPGPKey({ + encryptedPGPPrivateKey: user.encryptedPrivateKey, + account: address, + signer, + env, + }); + } + + setPgpPrivateKey(pgpPrivateKey); + })(); + }, [address, env, signer, chain]); + + return { + spaceUI, + SpaceInvitesComponent: spaceUI.SpaceInvites, + SpaceWidgetComponent: spaceUI.SpaceWidget, + SpaceBannerComponent: spaceUI.SpaceBanner, + SpaceFeedComponent: spaceUI.SpaceFeed, + CreateSpaceComponent: spaceUI.SpaceCreationButtonWidget, + }; +}; diff --git a/packages/examples/sdk-frontend/video/components/VideoPlayer.tsx b/packages/examples/sdk-frontend/components/VideoPlayer.tsx similarity index 100% rename from packages/examples/sdk-frontend/video/components/VideoPlayer.tsx rename to packages/examples/sdk-frontend/components/VideoPlayer.tsx diff --git a/packages/examples/sdk-frontend/video/helpers/getCAIPAddress.ts b/packages/examples/sdk-frontend/helpers/getCAIPAddress.ts similarity index 100% rename from packages/examples/sdk-frontend/video/helpers/getCAIPAddress.ts rename to packages/examples/sdk-frontend/helpers/getCAIPAddress.ts diff --git a/packages/examples/sdk-frontend/video/hooks/usePushSocket.ts b/packages/examples/sdk-frontend/hooks/usePushSocket.ts similarity index 100% rename from packages/examples/sdk-frontend/video/hooks/usePushSocket.ts rename to packages/examples/sdk-frontend/hooks/usePushSocket.ts diff --git a/packages/examples/sdk-frontend/video/next-env.d.ts b/packages/examples/sdk-frontend/next-env.d.ts similarity index 100% rename from packages/examples/sdk-frontend/video/next-env.d.ts rename to packages/examples/sdk-frontend/next-env.d.ts diff --git a/packages/examples/sdk-frontend/video/next.config.js b/packages/examples/sdk-frontend/next.config.js similarity index 100% rename from packages/examples/sdk-frontend/video/next.config.js rename to packages/examples/sdk-frontend/next.config.js diff --git a/packages/examples/sdk-frontend/video/package.json b/packages/examples/sdk-frontend/package.json similarity index 85% rename from packages/examples/sdk-frontend/video/package.json rename to packages/examples/sdk-frontend/package.json index e4f26153e..c5791072e 100644 --- a/packages/examples/sdk-frontend/video/package.json +++ b/packages/examples/sdk-frontend/package.json @@ -9,7 +9,8 @@ "lint": "next lint" }, "dependencies": { - "@pushprotocol/restapi": "^1.3.3", + "@pushprotocol/restapi": "../../../dist/packages/restapi", + "@pushprotocol/uiweb": "../../../dist/packages/uiweb", "@pushprotocol/socket": "^0.5.1", "@rainbow-me/rainbowkit": "0.12.14", "ethers": "^5", diff --git a/packages/examples/sdk-frontend/video/pages/_app.tsx b/packages/examples/sdk-frontend/pages/_app.tsx similarity index 56% rename from packages/examples/sdk-frontend/video/pages/_app.tsx rename to packages/examples/sdk-frontend/pages/_app.tsx index 5237f95e3..6013004e0 100644 --- a/packages/examples/sdk-frontend/video/pages/_app.tsx +++ b/packages/examples/sdk-frontend/pages/_app.tsx @@ -1,23 +1,24 @@ -import type { AppProps } from "next/app"; +import type { AppProps } from 'next/app'; import { getDefaultWallets, RainbowKitProvider, darkTheme, -} from "@rainbow-me/rainbowkit"; -import { configureChains, createClient, WagmiConfig } from "wagmi"; -import { goerli } from "wagmi/chains"; -import { publicProvider } from "wagmi/providers/public"; +} from '@rainbow-me/rainbowkit'; +import { configureChains, createClient, WagmiConfig } from 'wagmi'; +import { goerli } from 'wagmi/chains'; +import { publicProvider } from 'wagmi/providers/public'; -import "@rainbow-me/rainbowkit/styles.css"; -import "../styles/globals.css"; -import { useEffect, useState } from "react"; +import '@rainbow-me/rainbowkit/styles.css'; +import '../styles/globals.css'; +import { useEffect, useState } from 'react'; +import { SpacesComponentProvider } from './spaces'; const { chains, provider } = configureChains([goerli], [publicProvider()]); const { connectors } = getDefaultWallets({ - appName: "Connect", - projectId: "connect", + appName: 'Connect', + projectId: 'connect', chains, }); @@ -40,7 +41,9 @@ function MyApp({ Component, pageProps }: AppProps) { {loadWagmi ? ( - + + + ) : null} diff --git a/packages/examples/sdk-frontend/pages/index.tsx b/packages/examples/sdk-frontend/pages/index.tsx new file mode 100644 index 000000000..aff02dff0 --- /dev/null +++ b/packages/examples/sdk-frontend/pages/index.tsx @@ -0,0 +1,43 @@ +import { ConnectButton } from '@rainbow-me/rainbowkit'; +import { NextPage } from 'next'; +import Link from 'next/link'; +import styled from 'styled-components'; + +const Index: NextPage = () => { + return ( + +

Hello Next.js 👋

+ + + +
+ ); +}; + +export default Index; + +export const Container = styled.div` + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 20px; +}`; + +export const Button = styled.button` + background: #000; + color: #fff; + border: none; + border-radius: 10px; + padding: 10px 20px; + font-size: 1.2rem; + cursor: pointer; + transition: 0.3s; + &:hover { + opacity: 0.7; + } +}`; diff --git a/packages/examples/sdk-frontend/pages/spaces/banner.tsx b/packages/examples/sdk-frontend/pages/spaces/banner.tsx new file mode 100644 index 000000000..bc0a6a01c --- /dev/null +++ b/packages/examples/sdk-frontend/pages/spaces/banner.tsx @@ -0,0 +1,71 @@ +import React, { useState } from 'react'; + +import { useSpaceComponents } from './../../components/Spaces/useSpaceComponent'; +import { + Section, + SectionItem, +} from './../../components/Spaces/StyledComponents'; +import Dropdown from './../../components/Spaces/Dropdown'; +import { NextPage } from 'next'; +import Spaces from '.'; + +const SpaceBanner: NextPage = () => { + const { SpaceBannerComponent } = useSpaceComponents(); + + const [spaceId, setSpaceId] = useState(''); + const [orientation, setOrientation] = useState('maximized'); + + const updateSpaceId = (e: React.SyntheticEvent) => { + setSpaceId((e.target as HTMLInputElement).value); + }; + + const updateOrientation = (e: any) => { + setOrientation(e.target.value); + }; + + const onClickHandler = (arg: string) => { + console.log(arg); + }; + + return ( +
+ +
+ + + + + +
+ +
+ ); +}; + +export default SpaceBanner; diff --git a/packages/examples/sdk-frontend/pages/spaces/create.tsx b/packages/examples/sdk-frontend/pages/spaces/create.tsx new file mode 100644 index 000000000..c45a327ba --- /dev/null +++ b/packages/examples/sdk-frontend/pages/spaces/create.tsx @@ -0,0 +1,16 @@ +import { NextPage } from 'next'; +import { useSpaceComponents } from './../../components/Spaces/useSpaceComponent'; +import Spaces from '.'; + +const CreateSpaceComponent: NextPage = () => { + const { CreateSpaceComponent } = useSpaceComponents(); + + return ( + <> + + + + ); +}; + +export default CreateSpaceComponent; diff --git a/packages/examples/sdk-frontend/pages/spaces/feed.tsx b/packages/examples/sdk-frontend/pages/spaces/feed.tsx new file mode 100644 index 000000000..b15b4faa5 --- /dev/null +++ b/packages/examples/sdk-frontend/pages/spaces/feed.tsx @@ -0,0 +1,90 @@ +import React, { useState } from 'react'; +import { useSpaceComponents } from './../../components/Spaces/useSpaceComponent'; +import { Checkbox } from './../../components/Spaces/Checkbox'; +import { NextPage } from 'next'; +import Spaces from '.'; + +const SpaceFeed: NextPage = () => { + const { SpaceFeedComponent } = useSpaceComponents(); + const [address, setAddress] = useState(); + const [showTab, setShowTab] = useState(true); + const [horizontal, setHorizontal] = useState(false); + const [width, setWidth] = useState(); + const [height, setHeight] = useState(500); + const [sortingOrder, setSortingOrder] = useState([]); + + const handleShowTab = () => { + setShowTab(!showTab); + }; + + const handleHorizontal = () => { + setHorizontal(!horizontal); + }; + + const handleAddressChange = (e: React.SyntheticEvent) => { + setAddress((e.target as HTMLInputElement).value); + }; + + const handleWidthChange = (e: React.SyntheticEvent) => { + setWidth((e.target as HTMLInputElement).value as unknown as number); + }; + + const handleHeightChange = (e: React.SyntheticEvent) => { + setHeight((e.target as HTMLInputElement).value as unknown as number); + }; + + return ( + <> + + + + +
+ +
+ +
+ +
+ +
+ + { + console.log('spaceId: ', spaceId); + }} + /> + + ); +}; + +export default SpaceFeed; diff --git a/packages/examples/sdk-frontend/pages/spaces/index.tsx b/packages/examples/sdk-frontend/pages/spaces/index.tsx new file mode 100644 index 000000000..2441d1181 --- /dev/null +++ b/packages/examples/sdk-frontend/pages/spaces/index.tsx @@ -0,0 +1,66 @@ +import { NextPage } from 'next'; +import styled from 'styled-components'; +import { Button, Container } from '..'; +import Link from 'next/link'; + +import { SpacesUIProvider } from '@pushprotocol/uiweb'; +import { useSpaceComponents } from './../../components/Spaces/useSpaceComponent'; + + +export interface ISpacesComponentProps { + children: React.ReactNode; +} + +export const SpacesComponentProvider = ({ + children, +}: ISpacesComponentProps) => { + const { spaceUI } = useSpaceComponents(); + + const customtheme = { + statusColorError: 'red', + }; + + return ( + + {children} + + ); +}; + +const Spaces: NextPage = () => { + return ( + + +

Spaces UI Test

+
+ + + + + +
+
+
+ ); +}; + +export default Spaces; + +const Section = styled.div` + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + gap: 20px; + wrap: wrap; +}`; diff --git a/packages/examples/sdk-frontend/pages/spaces/invites.tsx b/packages/examples/sdk-frontend/pages/spaces/invites.tsx new file mode 100644 index 000000000..0cf3aeca0 --- /dev/null +++ b/packages/examples/sdk-frontend/pages/spaces/invites.tsx @@ -0,0 +1,16 @@ +import { NextPage } from 'next'; +import { useSpaceComponents } from './../../components/Spaces/useSpaceComponent'; +import Spaces from '.'; + +const SpaceInvitesComponent: NextPage = () => { + const { SpaceInvitesComponent } = useSpaceComponents(); + + return ( + <> + + + + ); +}; + +export default SpaceInvitesComponent; diff --git a/packages/examples/sdk-frontend/pages/spaces/widget.tsx b/packages/examples/sdk-frontend/pages/spaces/widget.tsx new file mode 100644 index 000000000..3283285ca --- /dev/null +++ b/packages/examples/sdk-frontend/pages/spaces/widget.tsx @@ -0,0 +1,163 @@ +import { useState } from 'react'; +import { + Section, + SectionItem, +} from './../../components/Spaces/StyledComponents'; +import { useSpaceComponents } from './../../components/Spaces/useSpaceComponent'; +import Spaces from '.'; +import { NextPage } from 'next'; + +const SpaceWidget: NextPage = () => { + const { SpaceWidgetComponent } = useSpaceComponents(); + const [spaceId, setSpaceId] = useState(''); + const [width, setWidth] = useState(''); + const [zIndex, setZIndex] = useState('1000'); + const [shareUrl, setShareUrl] = useState(''); + const [isHost, setisHost] = useState(false); + const [isLive, setisLive] = useState(false); + const [isMember, setisMember] = useState(false); + const [isJoined, setisJoined] = useState(false); + const [isTimeToStartSpace, setisTimeToStartSpace] = useState(false); + + const updateSpaceId = (e: React.SyntheticEvent) => { + setSpaceId((e.target as HTMLInputElement).value); + }; + + const updateWidgetWidth = (e: React.SyntheticEvent) => { + setWidth((e.target as HTMLInputElement).value); + }; + + const updateZIndex = (e: React.SyntheticEvent) => { + setZIndex((e.target as HTMLInputElement).value); + }; + + const updateShareUrl = (e: React.SyntheticEvent) => { + setShareUrl((e.target as HTMLInputElement).value); + }; + + const updateIsHost = (e: React.SyntheticEvent) => { + setisHost((e.target as HTMLInputElement).checked); + }; + + const updateIsLive = (e: React.SyntheticEvent) => { + setisLive((e.target as HTMLInputElement).checked); + }; + + const updateIsMember = (e: React.SyntheticEvent) => { + setisMember((e.target as HTMLInputElement).checked); + }; + + const updateIsJoined = (e: React.SyntheticEvent) => { + setisJoined((e.target as HTMLInputElement).checked); + }; + + const updateIsTimeToStartSpace = (e: React.SyntheticEvent) => { + setisTimeToStartSpace((e.target as HTMLInputElement).checked); + }; + + return ( +
+ +

Space Widget Test page

+
+ + + + + + + + + + + + + + + + +
+ Temp Props +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ ); +}; + +export default SpaceWidget; diff --git a/packages/examples/sdk-frontend/video/pages/index.tsx b/packages/examples/sdk-frontend/pages/video.tsx similarity index 100% rename from packages/examples/sdk-frontend/video/pages/index.tsx rename to packages/examples/sdk-frontend/pages/video.tsx diff --git a/packages/examples/sdk-frontend/video/styles/globals.css b/packages/examples/sdk-frontend/styles/globals.css similarity index 100% rename from packages/examples/sdk-frontend/video/styles/globals.css rename to packages/examples/sdk-frontend/styles/globals.css diff --git a/packages/examples/sdk-frontend/video/tsconfig.json b/packages/examples/sdk-frontend/tsconfig.json similarity index 100% rename from packages/examples/sdk-frontend/video/tsconfig.json rename to packages/examples/sdk-frontend/tsconfig.json diff --git a/packages/examples/sdk-frontend/video/pages/spaces/index.tsx b/packages/examples/sdk-frontend/video/pages/spaces/index.tsx new file mode 100644 index 000000000..e69de29bb diff --git a/packages/restapi/package.json b/packages/restapi/package.json index b69ceb00d..587d56fc1 100644 --- a/packages/restapi/package.json +++ b/packages/restapi/package.json @@ -9,12 +9,15 @@ "ethers": "^5.6.8" }, "dependencies": { + "@livepeer/webrtmp-sdk": "^0.2.3", "@metamask/eth-sig-util": "^5.0.2", "buffer": "^6.0.3", "crypto-js": "^4.1.1", "immer": "^10.0.2", + "livepeer": "^2.5.8", "openpgp": "^5.5.0", - "simple-peer": "^9.11.1" + "simple-peer": "^9.11.1", + "video-stream-merger": "^4.0.1" }, "scripts": { "test": "TS_NODE_PROJECT='./tsconfig.mocha.json' NODE_OPTIONS='--loader ts-node/esm' mocha -r ts-node/register 'tests/**/*.test.ts' --timeout 120000 --require tests/root.ts --serial" diff --git a/packages/restapi/src/lib/payloads/constants.ts b/packages/restapi/src/lib/payloads/constants.ts index fc0eca252..8930689f9 100644 --- a/packages/restapi/src/lib/payloads/constants.ts +++ b/packages/restapi/src/lib/payloads/constants.ts @@ -46,6 +46,36 @@ export enum NOTIFICATION_TYPE { export enum ADDITIONAL_META_TYPE { CUSTOM = 0, PUSH_VIDEO = 1, + PUSH_SPACE = 2, +} + +// Subset of ADDITIONAL_META_TYPE, to be used exclusively for Push Video, Spaces +export enum VIDEO_CALL_TYPE { + PUSH_VIDEO = 1, + PUSH_SPACE = 2, +} + +export enum SPACE_REQUEST_TYPE { + JOIN_SPEAKER, // space has started, join as a speaker + ESTABLISH_MESH, // request to establish mesh connection + INVITE_TO_PROMOTE, // host invites someone to be promoted as the speaker + REQUEST_TO_PROMOTE, // someone requests the host to be promoted to a spaeker +} + +export enum SPACE_ACCEPT_REQUEST_TYPE { + ACCEPT_JOIN_SPEAKER, + ACCEPT_INVITE, + ACCEPT_PROMOTION, +} + +export enum SPACE_DISCONNECT_TYPE { + STOP, // space is stopped/ended + LEAVE // speaker leaves a space +} + +export enum SPACE_INVITE_ROLES { + CO_HOST, + SPEAKER, } export const DEFAULT_DOMAIN = 'push.org'; diff --git a/packages/restapi/src/lib/payloads/index.ts b/packages/restapi/src/lib/payloads/index.ts index 67ef80fe5..22436ff9a 100644 --- a/packages/restapi/src/lib/payloads/index.ts +++ b/packages/restapi/src/lib/payloads/index.ts @@ -1,2 +1,9 @@ export * from './sendNotifications'; -export {NOTIFICATION_TYPE, IDENTITY_TYPE} from './constants' +export { + NOTIFICATION_TYPE, + IDENTITY_TYPE, + ADDITIONAL_META_TYPE, + SPACE_REQUEST_TYPE, + SPACE_ACCEPT_REQUEST_TYPE, + SPACE_DISCONNECT_TYPE +} from './constants'; diff --git a/packages/restapi/src/lib/space/Space.ts b/packages/restapi/src/lib/space/Space.ts new file mode 100644 index 000000000..942271874 --- /dev/null +++ b/packages/restapi/src/lib/space/Space.ts @@ -0,0 +1,230 @@ +import { produce } from 'immer'; + +import Constants from '../constants'; +import { Video, initVideoCallData } from '../video'; +import { update } from './update'; +import { start } from './start'; +import { inviteToPromote } from './inviteToPromote'; +import { acceptPromotionInvite } from './acceptPromotionInvite'; +import { connectInvitee } from './connectInvitee'; +import { rejectPromotionInvite } from './rejectPromotionInvite'; +import { requestToBePromoted } from './requestToBePromoted'; +import { acceptPromotionRequest } from './acceptPromotionRequest'; +import { rejectPromotionRequest } from './rejectPromotionRequest'; +import { connectPromotor } from './connectPromotor'; +import { addSpeaker } from './addSpeaker'; +import { removeSpeaker } from './removeSpeaker'; +import { join } from './join'; +import { leave } from './leave'; +import { stop } from './stop'; +import { initialize } from './initialize'; +import addToMergedStream from './helpers/addToMergedStream'; + +import { VideoStreamMerger } from 'video-stream-merger'; +import { + ChatStatus, + EnvOptionsType, + SignerType, + SpaceDTO, + SpaceData, +} from '../types'; +import { VIDEO_CALL_TYPE } from '../payloads/constants'; + +const initSpaceSpecificData = { + members: [], + pendingMembers: [], + contractAddressERC20: null, + numberOfERC20: -1, + contractAddressNFT: null, + numberOfNFTTokens: -1, + verificationProof: '', + spaceImage: null, + spaceName: '', + isPublic: false, + spaceDescription: '', + spaceCreator: '', + spaceId: '', + scheduleAt: null, + scheduleEnd: null, + status: null, + inviteeDetails: {}, +}; + +export const initSpaceData = { + ...initSpaceSpecificData, + connectionData: initVideoCallData, +}; + +export interface SpaceConstructorType extends EnvOptionsType { + signer: SignerType; + pgpPrivateKey: string; + chainId: number; + address: string; + setSpaceData: (fn: (data: SpaceData) => SpaceData) => void; +} + +// declaring the Space class + export class Space extends Video { + /* + - temporarily store the streamKey on the class + - will be used by the host to cast to the stream + */ + // protected streamKey: string | null = null; + + protected mergeStreamObject: VideoStreamMerger | null = null; + + protected spaceSpecificData: SpaceDTO; + protected setSpaceSpecificData: (fn: (data: SpaceDTO) => SpaceDTO) => void; + + // will be exposed and should be used from outside the class to change state + setSpaceData: (fn: (data: SpaceData) => SpaceData) => void; + + constructor(options: SpaceConstructorType) { + const { + signer, + pgpPrivateKey, + address, + chainId, + env = Constants.ENV.PROD, + setSpaceData, // to update the 'spaceData' state maintained by the developer + } = options || {}; + + // init the Video class + super({ + signer, + chainId, + pgpPrivateKey, + env, + callType: VIDEO_CALL_TYPE.PUSH_SPACE, + onReceiveStream: (receivedStream: MediaStream) => { + // for a space, that has started broadcast & the local peer is the host + if ( + this.spaceSpecificData.status === ChatStatus.ACTIVE && + this.data.meta.broadcast?.hostAddress && + this.data.meta.broadcast.hostAddress === this.data.local.address + ) { + addToMergedStream(this.mergeStreamObject!, receivedStream); + } + }, + setData: function () { + return; + }, // setData will be overridden below + }); + + // setting state changing functions + + /* + - Will be used internally in the class + - Overriding setData (Video) + - To be used when we only want to modify video call 'data' + */ + this.setData = function (fn) { + const newVideoData = fn(this.data); + + // update the react state + setSpaceData(() => ({ + ...this.spaceSpecificData, + connectionData: newVideoData, + })); + + // update the video class variable + this.data = newVideoData; + }; + + /* + - Will be used internally in the class + - To be used when we only want to modify space specific 'data' + */ + this.setSpaceSpecificData = function (fn) { + const newSpaceSpecificData = fn(this.spaceSpecificData); + + // update the react state + setSpaceData(() => ({ + ...newSpaceSpecificData, + connectionData: this.data, + })); + + // update the video class variable + this.spaceSpecificData = newSpaceSpecificData; + }; + + // set the space state updating function + this.setSpaceData = function (fn) { + const { connectionData: newConnectionData, ...newSpaceSpecificData } = fn( + { + ...this.spaceSpecificData, + connectionData: this.data, + } + ); + + // update the space specific data + this.spaceSpecificData = newSpaceSpecificData; + + // update the video data and update the external state + this.setData(() => newConnectionData); + }; + + // initializing state + + // set the local address inside video call 'data' + this.setData((oldVideoCallData) => { + return produce(oldVideoCallData, (draft) => { + draft.local.address = address; + }); + }); + + // init the state maintained by the developer + setSpaceData(() => initSpaceData); + + // init the spaceSpecificData class variable + this.spaceSpecificData = initSpaceSpecificData; + }; + + + // adding instance methods + + public initialize = initialize; + + public update = update; + + public createAudioStream = async () => { + await this.create({ audio: true, video: false }); + }; + + public start = start; + + // to promote a listener to a speaker/co-host + public inviteToPromote = inviteToPromote; + public acceptPromotionInvite = acceptPromotionInvite; + public connectInvitee = connectInvitee; + public rejectPromotionInvite = rejectPromotionInvite; + + // listener requests to be promoted to a speaker + public requestToBePromoted = requestToBePromoted; + public acceptPromotionRequest = acceptPromotionRequest; + public connectPromotor = connectPromotor; + public rejectPromotionRequest = rejectPromotionRequest; + + /* + - add/remove speaker to the space group as admins + - these methods are only to be used when the space hasnt started yet + */ + public addSpeaker = addSpeaker; + public removeSpeaker = removeSpeaker; + + /* + - add/remove co-host to the space group as admins + - add/remove them from the meta message + - these methods are only to be used when the space hasnt started yet + */ + // public addCoHost = addCoHost; + // public removeCoHost = removeCoHost; + + // add listner to the space group as member + public join = join; + + public leave = leave; + public stop = stop; +} + +export default Space; diff --git a/packages/restapi/src/lib/space/acceptPromotionInvite.ts b/packages/restapi/src/lib/space/acceptPromotionInvite.ts new file mode 100644 index 000000000..bb7765e05 --- /dev/null +++ b/packages/restapi/src/lib/space/acceptPromotionInvite.ts @@ -0,0 +1,28 @@ +import { SPACE_ACCEPT_REQUEST_TYPE } from '../payloads/constants'; +import type Space from './Space'; + +export interface AcceptPromotionInviteType { + signalData: any; + invitorAddress: string; + spaceId: string; +} + +export async function acceptPromotionInvite( + this: Space, + options: AcceptPromotionInviteType +) { + const { signalData, invitorAddress, spaceId } = + options || {}; + + // accept the promotion invite + this.acceptRequest({ + signalData, + senderAddress: this.data.local.address, + recipientAddress: invitorAddress, + chatId: spaceId, + details: { + type: SPACE_ACCEPT_REQUEST_TYPE.ACCEPT_INVITE, + data: {}, + }, + }); +} diff --git a/packages/restapi/src/lib/space/acceptPromotionRequest.ts b/packages/restapi/src/lib/space/acceptPromotionRequest.ts new file mode 100644 index 000000000..1d733d12e --- /dev/null +++ b/packages/restapi/src/lib/space/acceptPromotionRequest.ts @@ -0,0 +1,33 @@ +import { + SPACE_ACCEPT_REQUEST_TYPE, + SPACE_INVITE_ROLES, +} from '../payloads/constants'; +import type Space from './Space'; + +export interface AcceptPromotionRequestType { + signalData: any; + promoteeAddress: string; + role: SPACE_INVITE_ROLES; + spaceId: string; +} + +export async function acceptPromotionRequest( + this: Space, + options: AcceptPromotionRequestType +) { + const { signalData, promoteeAddress, spaceId, role } = options || {}; + + // TODO: change the role of promoteeAddress from listner to 'role' + + // accept the promotion request + this.acceptRequest({ + signalData, + senderAddress: this.data.local.address, + recipientAddress: promoteeAddress, + chatId: spaceId, + details: { + type: SPACE_ACCEPT_REQUEST_TYPE.ACCEPT_PROMOTION, + data: {}, + }, + }); +} diff --git a/packages/restapi/src/lib/space/addSpeaker.ts b/packages/restapi/src/lib/space/addSpeaker.ts new file mode 100644 index 000000000..37924f724 --- /dev/null +++ b/packages/restapi/src/lib/space/addSpeaker.ts @@ -0,0 +1,34 @@ +import { EnvOptionsType } from '../types'; +import { groupDtoToSpaceDto } from '../chat/helpers'; +import { addAdmins } from '../chat/addAdmins'; + +import type Space from './Space'; + +export interface AddSpeakerType extends EnvOptionsType { + address: string; +} + +export async function addSpeaker( + this: Space, + options: AddSpeakerType +): Promise { + const { address } = options; + try { + const group = await addAdmins({ + chatId: this.spaceSpecificData.spaceId, + admins: [address], + signer: this.signer, + env: this.env, + pgpPrivateKey: this.pgpPrivateKey, + }); + + // update space specific data + this.setSpaceSpecificData(() => groupDtoToSpaceDto(group)); + } catch (err) { + console.error( + `[Push SDK] - API - Error - API ${addSpeaker.name} -: `, + err + ); + throw Error(`[Push SDK] - API - Error - API ${addSpeaker.name} -: ${err}`); + } +} diff --git a/packages/restapi/src/lib/space/addSpeakers.ts b/packages/restapi/src/lib/space/addSpeakers.ts index e7311506d..f7121363f 100644 --- a/packages/restapi/src/lib/space/addSpeakers.ts +++ b/packages/restapi/src/lib/space/addSpeakers.ts @@ -6,16 +6,16 @@ import { addAdmins } from '../chat/addAdmins'; export interface AddSpeakersToSpaceType extends EnvOptionsType { spaceId: string; speakers: Array; - account?: string; - signer?: SignerType; + signer: SignerType; pgpPrivateKey?: string; } -export const addSpeakers = async (options: AddSpeakersToSpaceType): Promise => { +export const addSpeakers = async ( + options: AddSpeakersToSpaceType +): Promise => { const { spaceId, speakers, - account = null, signer = null, env = options?.env ?? Constants.ENV.PROD, pgpPrivateKey = options?.pgpPrivateKey ?? null, @@ -24,11 +24,10 @@ export const addSpeakers = async (options: AddSpeakersToSpaceType): Promise { + return produce(oldData, (draft) => { + if (draft.inviteeDetails) delete draft.inviteeDetails[inviteeAddress]; + }); + }); + // TODO: On backend change the role of inviteeAddress + + // complete the webRTC connection + this.connect({ signalData, peerAddress: inviteeAddress }); +} diff --git a/packages/restapi/src/lib/space/connectPromotor.ts b/packages/restapi/src/lib/space/connectPromotor.ts new file mode 100644 index 000000000..4d3151239 --- /dev/null +++ b/packages/restapi/src/lib/space/connectPromotor.ts @@ -0,0 +1,13 @@ +import type Space from './Space'; + +export interface ConnectPromotorType { + signalData: any; + promotorAddress: string; +} + +export async function connectPromotor(this: Space, options: ConnectPromotorType) { + const { signalData, promotorAddress } = options || {}; + + // complete the webRTC connection + this.connect({ signalData, peerAddress: promotorAddress }); +} diff --git a/packages/restapi/src/lib/space/create.ts b/packages/restapi/src/lib/space/create.ts index 593aae9fe..899bfbe67 100644 --- a/packages/restapi/src/lib/space/create.ts +++ b/packages/restapi/src/lib/space/create.ts @@ -1,13 +1,10 @@ import Constants from '../constants'; import { EnvOptionsType, SignerType, SpaceDTO } from '../types'; -import { - groupDtoToSpaceDto -} from './../chat/helpers'; +import { groupDtoToSpaceDto } from './../chat/helpers'; import { createGroup } from '../chat/createGroup'; export interface ChatCreateSpaceType extends EnvOptionsType { - account?: string; - signer?: SignerType; + signer: SignerType; spaceName: string; spaceDescription: string; members: Array; @@ -20,16 +17,13 @@ export interface ChatCreateSpaceType extends EnvOptionsType { numberOfERC20?: number; pgpPrivateKey?: string; meta?: string; - scheduleAt: Date - scheduleEnd?: Date | null + scheduleAt: Date; + scheduleEnd?: Date | null; } -export const create = async ( - options: ChatCreateSpaceType -): Promise => { +export async function create(options: ChatCreateSpaceType): Promise { const { - account = null, - signer = null, + signer, spaceName, spaceDescription, members, @@ -48,39 +42,29 @@ export const create = async ( } = options || {}; try { - if (account == null && signer == null) { - throw new Error(`At least one from account or signer is necessary!`); - } - - const group = await createGroup({ - account: account, - signer: signer, - groupName: spaceName, - groupDescription: spaceDescription, - members: members, - groupImage: spaceImage, - admins: admins, - isPublic: isPublic, - contractAddressNFT: contractAddressNFT, - numberOfNFTs: numberOfNFTs, - contractAddressERC20: contractAddressERC20, - numberOfERC20: numberOfERC20, - env: env, - pgpPrivateKey: pgpPrivateKey, - meta: meta, - groupType: "spaces", - scheduleAt: scheduleAt, - scheduleEnd: scheduleEnd, + const group = await createGroup({ + signer, + groupName: spaceName, + groupDescription: spaceDescription, + members: members, + groupImage: spaceImage, + admins: admins, + isPublic: isPublic, + contractAddressNFT: contractAddressNFT, + numberOfNFTs: numberOfNFTs, + contractAddressERC20: contractAddressERC20, + numberOfERC20: numberOfERC20, + env, + pgpPrivateKey, + meta: meta, + groupType: 'spaces', + scheduleAt: scheduleAt, + scheduleEnd: scheduleEnd, }); - - return groupDtoToSpaceDto(group) + + return groupDtoToSpaceDto(group); } catch (err) { - console.error( - `[Push SDK] - API - Error - API ${create.name} -: `, - err - ); - throw Error( - `[Push SDK] - API - Error - API ${create.name} -: ${err}` - ); + console.error(`[Push SDK] - API - Error - API ${create.name} -: `, err); + throw Error(`[Push SDK] - API - Error - API ${create.name} -: ${err}`); } -}; +} diff --git a/packages/restapi/src/lib/space/helpers/addToMergedStream.ts b/packages/restapi/src/lib/space/helpers/addToMergedStream.ts new file mode 100644 index 000000000..9e939e893 --- /dev/null +++ b/packages/restapi/src/lib/space/helpers/addToMergedStream.ts @@ -0,0 +1,10 @@ +import type { VideoStreamMerger } from 'video-stream-merger'; + +const addToMergedStream = ( + mergeObject: VideoStreamMerger, + streamToBeAdded: MediaStream +) => { + mergeObject.addStream(streamToBeAdded, undefined); +}; + +export default addToMergedStream; diff --git a/packages/restapi/src/lib/space/helpers/getMergeStreamObject.ts b/packages/restapi/src/lib/space/helpers/getMergeStreamObject.ts new file mode 100644 index 000000000..a1322f823 --- /dev/null +++ b/packages/restapi/src/lib/space/helpers/getMergeStreamObject.ts @@ -0,0 +1,14 @@ +import { VideoStreamMerger } from 'video-stream-merger'; + +const getMergeStreamObject = (hostStream: MediaStream) => { + const mergeStreamObject = new VideoStreamMerger(); + + // add the audio stream of host + mergeStreamObject.addStream(hostStream, undefined); + + mergeStreamObject.start(); + + return mergeStreamObject; +}; + +export default getMergeStreamObject; diff --git a/packages/restapi/src/lib/space/index.ts b/packages/restapi/src/lib/space/index.ts index 52feea71a..6891e3d60 100644 --- a/packages/restapi/src/lib/space/index.ts +++ b/packages/restapi/src/lib/space/index.ts @@ -1,15 +1,14 @@ -export * from './create'; -export * from './update'; -export * from './info'; +export * from './spaces'; +export * from './trending'; export * from './get'; -export * from './approve'; -export * from './start'; -export * from './stop'; +export * from './info'; +export * from './create'; +export * from './update_out'; export * from './addSpeakers'; -export * from './addListeners'; export * from './removeSpeakers'; +export * from './addListeners'; export * from './removeListeners'; +export * from './approve'; export * from './requests'; -export * from './spaces'; -export * from './trending'; +export * from './Space' diff --git a/packages/restapi/src/lib/space/initialize.ts b/packages/restapi/src/lib/space/initialize.ts new file mode 100644 index 000000000..85f3dc682 --- /dev/null +++ b/packages/restapi/src/lib/space/initialize.ts @@ -0,0 +1,17 @@ +import type Space from './Space'; +import { get } from './get'; + +export interface InitializeType { + spaceId: string; +} + +export async function initialize(this: Space, options: InitializeType) { + const { spaceId } = options || {}; + + const space = await get({ + spaceId, + env: this.env, + }); + + this.setSpaceSpecificData(() => space); +} diff --git a/packages/restapi/src/lib/space/inviteToPromote.ts b/packages/restapi/src/lib/space/inviteToPromote.ts new file mode 100644 index 000000000..dd5644be3 --- /dev/null +++ b/packages/restapi/src/lib/space/inviteToPromote.ts @@ -0,0 +1,35 @@ +import { produce } from 'immer'; +import { SPACE_INVITE_ROLES, SPACE_REQUEST_TYPE } from '../payloads/constants'; +import type Space from './Space'; + +export interface InviteToPromoteType { + inviteeAddress: string; + role: SPACE_INVITE_ROLES; +} + +export async function inviteToPromote( + this: Space, + options: InviteToPromoteType +) { + const { inviteeAddress, role } = options || {}; + + // adding address to the invitee map + this.setSpaceSpecificData((oldData) => { + return produce(oldData, (draft) => { + if (draft.inviteeDetails) draft.inviteeDetails[inviteeAddress] = role; + }); + }); + + // we send a request to 'inviteeAddress' and try to add them to the mesh connection + this.request({ + senderAddress: this.data.local.address, + recipientAddress: inviteeAddress, + chatId: this.spaceSpecificData.spaceId, + details: { + type: SPACE_REQUEST_TYPE.INVITE_TO_PROMOTE, + data: { + role, + }, + }, + }); +} diff --git a/packages/restapi/src/lib/space/join.ts b/packages/restapi/src/lib/space/join.ts new file mode 100644 index 000000000..d1b640595 --- /dev/null +++ b/packages/restapi/src/lib/space/join.ts @@ -0,0 +1,96 @@ +import { SPACE_ACCEPT_REQUEST_TYPE } from '../payloads/constants'; +import { ChatStatus } from '../types'; +import { VideoDataType } from '../video/helpers/sendVideoCallNotification'; +import { approve } from './approve'; +import { get } from './get'; +import type Space from './Space'; + +export interface JoinSpaceType { + recievedVideoData?: VideoDataType; // only required when joining as a speaker +} + +/** + * + * @param options + * recievedVideoData: only required when joining as a speaker + */ +export async function join(this: Space, options: JoinSpaceType) { + const { recievedVideoData = null } = options || {}; + + try { + const space = await get({ + spaceId: this.spaceSpecificData.spaceId, + env: this.env, + }); + + if (space.status !== ChatStatus.ACTIVE) + throw new Error('Space not active yet'); + + // checking what is the current role of caller address + + let isSpeaker = false; + let isListner = false; + space.members.forEach((member) => { + if (member.wallet === this.data.local.address) { + if (member.isSpeaker) { + isSpeaker = true; + } else { + isListner = true; + } + } + }); + let isSpeakerPending = false; + space.pendingMembers.forEach((pendingMember) => { + if ( + pendingMember.wallet === this.data.local.address && + pendingMember.isSpeaker + ) { + isSpeakerPending = true; + } + }); + + // acc to the found role (speaker or listner), executing req logic + + // if speaker is pending then approve first or if listner is pending/not found then approve first + if (isSpeakerPending || !isListner) { + await approve({ + signer: this.signer, + pgpPrivateKey: this.pgpPrivateKey, + senderAddress: this.spaceSpecificData.spaceId, + env: this.env + }); + } + + if (isSpeaker || isSpeakerPending) { + if (!recievedVideoData) + throw new Error('Joining as a speaker failed due to bad video data'); + + if (recievedVideoData.chatId !== this.spaceSpecificData.spaceId) + throw new Error( + 'Joining as a speaker failed due to mismatch in space id' + ); + + // call acceptRequest to initiate connection + await this.acceptRequest({ + senderAddress: recievedVideoData.recipientAddress, + recipientAddress: recievedVideoData.senderAddress, + signalData: recievedVideoData.signalData, + chatId: recievedVideoData.chatId, + details: { + type: SPACE_ACCEPT_REQUEST_TYPE.ACCEPT_JOIN_SPEAKER, + data: {}, + }, + }); + } + + const updatedSpace = await get({ + spaceId: this.spaceSpecificData.spaceId, + env: this.env, + }); + // update space specific data + this.setSpaceSpecificData(() => updatedSpace); + } catch (err) { + console.error(`[Push SDK] - API - Error - API ${join.name} -: `, err); + throw Error(`[Push SDK] - API - Error - API ${join.name} -: ${err}`); + } +} diff --git a/packages/restapi/src/lib/space/leave.ts b/packages/restapi/src/lib/space/leave.ts new file mode 100644 index 000000000..53b85d56e --- /dev/null +++ b/packages/restapi/src/lib/space/leave.ts @@ -0,0 +1,34 @@ +import { + groupDtoToSpaceDto, + getMembersList, + getAdminsList, +} from '../chat/helpers'; +import { updateGroup } from '../chat/updateGroup'; +import { get } from './get'; + +import type Space from './Space'; +import { SPACE_DISCONNECT_TYPE } from '../payloads/constants'; + +export async function leave(this: Space): Promise { + try { + // should be only called by the host or the speakers + + // if the host is leaving then we need to make someone else the host + + // handle the case where a listner is leaving + + // disconnect with every incoming peer in the mesh connection + this.data.incoming.forEach(({ address }) => { + this.disconnect({ + peerAddress: address, + details: { + type: SPACE_DISCONNECT_TYPE.LEAVE, + data: {}, + }, + }); + }); + } catch (err) { + console.error(`[Push SDK] - API - Error - API ${stop.name} -: `, err); + throw Error(`[Push SDK] - API - Error - API ${stop.name} -: ${err}`); + } +} diff --git a/packages/restapi/src/lib/space/rejectPromotionInvite.ts b/packages/restapi/src/lib/space/rejectPromotionInvite.ts new file mode 100644 index 000000000..6eff90156 --- /dev/null +++ b/packages/restapi/src/lib/space/rejectPromotionInvite.ts @@ -0,0 +1,18 @@ +import type Space from './Space'; + +export interface RejectPromotionInviteType { + invitorAddress: string; +} + +export async function rejectPromotionInvite( + this: Space, + options: RejectPromotionInviteType +) { + const { invitorAddress } = + options || {}; + + // reject the promotion invite + this.disconnect({ + peerAddress: invitorAddress, + }); +} diff --git a/packages/restapi/src/lib/space/rejectPromotionRequest.ts b/packages/restapi/src/lib/space/rejectPromotionRequest.ts new file mode 100644 index 000000000..b4eddee56 --- /dev/null +++ b/packages/restapi/src/lib/space/rejectPromotionRequest.ts @@ -0,0 +1,17 @@ +import type Space from './Space'; + +export interface RejectPromotionRequestType { + promoteeAddress: string; +} + +export async function rejectPromotionRequest( + this: Space, + options: RejectPromotionRequestType +) { + const { promoteeAddress } = options || {}; + + // reject the promotion request + this.disconnect({ + peerAddress: promoteeAddress, + }); +} diff --git a/packages/restapi/src/lib/space/removeSpeaker.ts b/packages/restapi/src/lib/space/removeSpeaker.ts new file mode 100644 index 000000000..84c214d02 --- /dev/null +++ b/packages/restapi/src/lib/space/removeSpeaker.ts @@ -0,0 +1,37 @@ +import { EnvOptionsType } from '../types'; +import { groupDtoToSpaceDto } from '../chat/helpers'; +import { + removeAdmins +} from '../chat/removeAdmins'; +import type Space from './Space'; + +export interface RemoveSpeakerType extends EnvOptionsType { + address: string; +} + +export async function removeSpeaker( + this: Space, + options: RemoveSpeakerType +): Promise { + const { address } = options; + try { + const group = await removeAdmins({ + chatId: this.spaceSpecificData.spaceId, + admins: [address], + signer: this.signer, + env: this.env, + pgpPrivateKey: this.pgpPrivateKey, + }); + + // update space specific data + this.setSpaceSpecificData(() => groupDtoToSpaceDto(group)); + } catch (err) { + console.error( + `[Push SDK] - API - Error - API ${removeSpeaker.name} -: `, + err + ); + throw Error( + `[Push SDK] - API - Error - API ${removeSpeaker.name} -: ${err}` + ); + } +} diff --git a/packages/restapi/src/lib/space/removeSpeakers.ts b/packages/restapi/src/lib/space/removeSpeakers.ts index 79cd12e58..e72137957 100644 --- a/packages/restapi/src/lib/space/removeSpeakers.ts +++ b/packages/restapi/src/lib/space/removeSpeakers.ts @@ -1,52 +1,41 @@ import Constants from '../constants'; -import { - EnvOptionsType, - SignerType, - SpaceDTO -} from '../types'; -import { - groupDtoToSpaceDto -} from '../chat/helpers'; -import { - removeAdmins -} from '../chat/removeAdmins'; +import { EnvOptionsType, SignerType, SpaceDTO } from '../types'; +import { groupDtoToSpaceDto } from '../chat/helpers'; +import { removeAdmins } from '../chat/removeAdmins'; export interface RemoveSpeakersFromSpaceType extends EnvOptionsType { spaceId: string; - speakers: Array < string > ; - account ? : string; - signer ? : SignerType; - pgpPrivateKey ? : string; + speakers: Array; + signer: SignerType; + pgpPrivateKey?: string; } export const removeSpeakers = async ( options: RemoveSpeakersFromSpaceType -): Promise < SpaceDTO > => { +): Promise => { const { - spaceId, - speakers, - account = null, - signer = null, - env = Constants.ENV.PROD, - pgpPrivateKey = null, + spaceId, + speakers, + signer = null, + env = Constants.ENV.PROD, + pgpPrivateKey = null, } = options || {}; try { - const group = await removeAdmins({ - chatId: spaceId, - admins: speakers, - account: account, - signer: signer, - env: env, - pgpPrivateKey: pgpPrivateKey - }); + const group = await removeAdmins({ + chatId: spaceId, + admins: speakers, + signer: signer, + env: env, + pgpPrivateKey: pgpPrivateKey, + }); - return groupDtoToSpaceDto(group); + return groupDtoToSpaceDto(group); } catch (err) { - console.error( - `[Push SDK] - API - Error - API ${removeSpeakers.name} -: `, - err - ); - throw Error( - `[Push SDK] - API - Error - API ${removeSpeakers.name} -: ${err}` - ); + console.error( + `[Push SDK] - API - Error - API ${removeSpeakers.name} -: `, + err + ); + throw Error( + `[Push SDK] - API - Error - API ${removeSpeakers.name} -: ${err}` + ); } -}; \ No newline at end of file +}; diff --git a/packages/restapi/src/lib/space/requestToBePromoted.ts b/packages/restapi/src/lib/space/requestToBePromoted.ts new file mode 100644 index 000000000..b52992841 --- /dev/null +++ b/packages/restapi/src/lib/space/requestToBePromoted.ts @@ -0,0 +1,28 @@ +import { SPACE_INVITE_ROLES, SPACE_REQUEST_TYPE } from '../payloads/constants'; +import type Space from './Space'; + +export interface RequestToBePromotedType { + role: SPACE_INVITE_ROLES; + spaceId: string; + promotorAddress: string; +} + +export async function requestToBePromoted( + this: Space, + options: RequestToBePromotedType +) { + const { role, spaceId, promotorAddress } = options || {}; + + // requesting host to include local computer into the mesh connection + this.request({ + senderAddress: this.data.local.address, + recipientAddress: promotorAddress, + chatId: spaceId, + details: { + type: SPACE_REQUEST_TYPE.REQUEST_TO_PROMOTE, + data: { + role, + }, + }, + }); +} diff --git a/packages/restapi/src/lib/space/start.ts b/packages/restapi/src/lib/space/start.ts index d98e4889e..5d5d3c2db 100644 --- a/packages/restapi/src/lib/space/start.ts +++ b/packages/restapi/src/lib/space/start.ts @@ -1,83 +1,161 @@ -import Constants from '../constants'; +import { EnvOptionsType, SignerType, ChatStatus } from '../types'; import { - EnvOptionsType, - SpaceDTO, - SignerType, - ChatStatus -} from '../types'; -import { - groupDtoToSpaceDto, - getSpacesMembersList, - getSpaceAdminsList + groupDtoToSpaceDto, + getSpacesMembersList, + getSpaceAdminsList, } from './../chat/helpers'; -import { - get -} from './get'; -import { - updateGroup -} from '../chat/updateGroup'; +import { get } from './get'; +import { updateGroup } from '../chat/updateGroup'; +import getMergeStreamObject from './helpers/getMergeStreamObject'; +import axios from 'axios'; +import { Client, isSupported } from '@livepeer/webrtmp-sdk'; + export interface StartSpaceType extends EnvOptionsType { - spaceId: string; - account ? : string; - signer ? : SignerType; - pgpPrivateKey ? : string; + spaceId: string; + account?: string; + signer?: SignerType; + pgpPrivateKey?: string; } -export const start = async ( - options: StartSpaceType -): Promise < SpaceDTO > => { - const { - spaceId, - account = null, - signer = null, - env = Constants.ENV.PROD, - pgpPrivateKey = null, - } = options || {}; - try { - if (account == null && signer == null) { - throw new Error(`At least one from account or signer is necessary!`); - } +import type Space from './Space'; +import { SPACE_REQUEST_TYPE } from '../payloads/constants'; +import { produce } from 'immer'; + +type StartType = { + livepeerApiKey: string; +}; + +export async function start(this: Space, options: StartType): Promise { + const { livepeerApiKey } = options || {}; + + try { + // TODO: Only allow the host to execute this function + + // host should have there audio stream + if (!this.data.local.stream) { + throw new Error('Local audio stream not found'); + } + + const space = await get({ + spaceId: this.spaceSpecificData.spaceId, + env: this.env, + }); + + if (space.status !== ChatStatus.PENDING) { + throw new Error( + 'Unable to start the space as it is not in the pending state' + ); + } + + const convertedMembers = getSpacesMembersList( + space.members, + space.pendingMembers + ); + const convertedAdmins = getSpaceAdminsList( + space.members, + space.pendingMembers + ); - const space = await get({ - spaceId: spaceId, - env, - }) + const group = await updateGroup({ + chatId: this.spaceSpecificData.spaceId, + groupName: space.spaceName, + groupImage: space.spaceImage, + groupDescription: space.spaceDescription, + members: convertedMembers, + admins: convertedAdmins, + signer: this.signer, + env: this.env, + pgpPrivateKey: this.pgpPrivateKey, + scheduleAt: space.scheduleAt, + scheduleEnd: space.scheduleEnd, + status: ChatStatus.ACTIVE, + }); - if (space.status !== ChatStatus.PENDING) { - throw new Error("Unable to start the space as it is not in the pending state"); + // update space data + this.setSpaceData((oldSpaceData) => { + return produce(oldSpaceData, (draft) => { + draft = { + ...groupDtoToSpaceDto(group), + connectionData: draft.connectionData, + }; + draft.connectionData.meta.broadcast = { + livepeerInfo: null, + hostAddress: this.data.local.address, + }; + }); + }); + + /* + - Try calling all the speakers (admins) + - Create a mesh based webRTC connection with all those who pick up + */ + this.request({ + senderAddress: this.data.local.address, + recipientAddress: convertedAdmins.map((convertedAdmin) => { + if (convertedAdmin.startsWith('eip155:')) { + return convertedAdmin.split('eip155:')[1]; } + return convertedAdmin; + }), + chatId: this.spaceSpecificData.spaceId, + details: { + type: SPACE_REQUEST_TYPE.JOIN_SPEAKER, + data: {}, + }, + }); + + // start the livepeer playback and store the playback URL group meta + // send a notification/meta message to all the added listeners (members) telling the space has started + + // create the mergeStream object + const mergeStreamObject = getMergeStreamObject(this.data.local.stream); + // store the mergeStreamObject + this.mergeStreamObject = mergeStreamObject; + + const url = 'https://livepeer.studio/api/stream'; + const data = { + name: this.spaceSpecificData.spaceName, + record: true, + }; + + const { data: responseData } = await axios.post(url, data, { + headers: { + Authorization: 'Bearer ' + livepeerApiKey, + }, + }); + + const { streamKey, playbackId } = responseData; + + console.log('livepeer details', streamKey, playbackId); - const convertedMembers = getSpacesMembersList( - space.members, space.pendingMembers - ); - const convertedAdmins = getSpaceAdminsList( - space.members, space.pendingMembers - ); - - const group = await updateGroup({ - chatId: spaceId, - groupName: space.spaceName, - groupImage: space.spaceImage, - groupDescription: space.spaceDescription, - members: convertedMembers, - admins: convertedAdmins, - account: account, - signer: signer, - env: env, - pgpPrivateKey: pgpPrivateKey, - scheduleAt: space.scheduleAt, - scheduleEnd: space.scheduleEnd, - status: ChatStatus.ACTIVE - }); - - return groupDtoToSpaceDto(group); - } catch (err) { - console.error( - `[Push SDK] - API - Error - API ${start.name} -: `, - err - ); - throw Error( - `[Push SDK] - API - Error - API ${start.name} -: ${err}` - ); + // TODO: store the playbackId on group meta data, temp -> groupDescription + this.update({ spaceDescription: playbackId }); + + if (!isSupported()) { + console.log('webrtmp-sdk is not currently supported on this browser'); } -}; \ No newline at end of file + + console.log('stream key', streamKey); + + // cast to the stream + const client = new Client(); + const session = client.cast(mergeStreamObject.result!, streamKey); + session.on('open', () => { + console.log('Live stream started.'); + // TODO: Update the space data + }); + + session.on('close', () => { + console.log('Live stream stopped.'); + // TODO: Update the space data + }); + + session.on('error', (err) => { + console.log('Live stream error.', err.message); + // TODO: Update the space data + }); + } catch (err) { + console.error(`[Push SDK] - API - Error - API ${start.name} -: `, err); + throw Error(`[Push SDK] - API - Error - API ${start.name} -: ${err}`); + } +} diff --git a/packages/restapi/src/lib/space/stop.ts b/packages/restapi/src/lib/space/stop.ts index 828c34f09..4f69914ec 100644 --- a/packages/restapi/src/lib/space/stop.ts +++ b/packages/restapi/src/lib/space/stop.ts @@ -1,83 +1,72 @@ -import Constants from '../constants'; import { - EnvOptionsType, - SpaceDTO, - SignerType, - ChatStatus -} from '../types'; -import { - groupDtoToSpaceDto, - getSpacesMembersList, - getSpaceAdminsList + groupDtoToSpaceDto, + getSpacesMembersList, + getSpaceAdminsList, } from '../chat/helpers'; -import { - updateGroup -} from '../chat/updateGroup'; -import { - get -} from './get'; -export interface StopSpaceType extends EnvOptionsType { - spaceId: string; - account ? : string; - signer ? : SignerType; - pgpPrivateKey ? : string; -} +import { updateGroup } from '../chat/updateGroup'; +import { get } from './get'; + +import type Space from './Space'; +import { ChatStatus } from '../types'; +import { SPACE_DISCONNECT_TYPE } from '../payloads/constants'; -export const stop = async ( - options: StopSpaceType -): Promise < SpaceDTO > => { - const { - spaceId, - account = null, - signer = null, - env = Constants.ENV.PROD, - pgpPrivateKey = null, - } = options || {}; - try { - if (account == null && signer == null) { - throw new Error(`At least one from account or signer is necessary!`); - } +export async function stop(this: Space): Promise { + try { + // should be only called by the host - const space = await get({ - spaceId: spaceId, - env, - }) + const space = await get({ + spaceId: this.spaceSpecificData.spaceId, + env: this.env, + }); - if (space.status === ChatStatus.ENDED) { - throw new Error("Space already ended"); - } + if (space.status === ChatStatus.ENDED) { + throw new Error('Space already ended'); + } - const convertedMembers = getSpacesMembersList( - space.members, space.pendingMembers - ); - const convertedAdmins = getSpaceAdminsList( - space.members, space.pendingMembers - ); + const convertedMembers = getSpacesMembersList( + space.members, + space.pendingMembers + ); + const convertedAdmins = getSpaceAdminsList( + space.members, + space.pendingMembers + ); - const group = await updateGroup({ - chatId: spaceId, - groupName: space.spaceName, - groupImage: space.spaceImage, - groupDescription: space.spaceDescription, - members: convertedMembers, - admins: convertedAdmins, - account: account, - signer: signer, - env: env, - pgpPrivateKey: pgpPrivateKey, - scheduleAt: space.scheduleAt, - scheduleEnd: space.scheduleEnd, - status: ChatStatus.ENDED - }); + const group = await updateGroup({ + chatId: this.spaceSpecificData.spaceId, + groupName: space.spaceName, + groupImage: space.spaceImage, + groupDescription: space.spaceDescription, + members: convertedMembers, + admins: convertedAdmins, + signer: this.signer, + env: this.env, + pgpPrivateKey: this.pgpPrivateKey, + scheduleAt: space.scheduleAt, + scheduleEnd: space.scheduleEnd, + status: ChatStatus.ENDED, + }); - return groupDtoToSpaceDto(group); - } catch (err) { - console.error( - `[Push SDK] - API - Error - API ${stop.name} -: `, - err - ); - throw Error( - `[Push SDK] - API - Error - API ${stop.name} -: ${err}` - ); - } -}; + // update space specific data + this.setSpaceSpecificData(() => groupDtoToSpaceDto(group)); + + // stop livepeer playback + + /* + - disconnect with every incoming peer in the mesh connection + - other peers should also end their connections as we want to destroy the mesh connection + */ + this.data.incoming.forEach(({ address }) => { + this.disconnect({ + peerAddress: address, + details: { + type: SPACE_DISCONNECT_TYPE.STOP, + data: {}, + }, + }); + }); + } catch (err) { + console.error(`[Push SDK] - API - Error - API ${stop.name} -: `, err); + throw Error(`[Push SDK] - API - Error - API ${stop.name} -: ${err}`); + } +} diff --git a/packages/restapi/src/lib/space/update.ts b/packages/restapi/src/lib/space/update.ts index a7c54fa7f..266baf456 100644 --- a/packages/restapi/src/lib/space/update.ts +++ b/packages/restapi/src/lib/space/update.ts @@ -1,78 +1,71 @@ -import Constants from '../constants'; +import { ChatStatus } from '../types'; import { - EnvOptionsType, - SpaceDTO, - SignerType, - ChatStatus -} from '../types'; -import { - groupDtoToSpaceDto, + getSpaceAdminsList, + getSpacesMembersList, + groupDtoToSpaceDto, } from './../chat/helpers'; -import { - updateGroup -} from '../chat/updateGroup'; +import { updateGroup } from '../chat/updateGroup'; +import { get } from './get'; + +import type Space from './Space'; -export interface ChatUpdateSpaceType extends EnvOptionsType { - account ? : string; - signer ? : SignerType; - spaceId: string; - spaceName: string; - spaceImage: string | null; - spaceDescription: string; - members: Array < string > ; - admins: Array < string > ; - pgpPrivateKey ? : string; - scheduleAt: Date - scheduleEnd ? : Date | null - status: ChatStatus +export interface ChatUpdateSpaceType { + spaceName?: string; + spaceImage?: string | null; + spaceDescription?: string; + scheduleAt?: Date; + scheduleEnd?: Date | null; } -export const update = async ( - options: ChatUpdateSpaceType -): Promise < SpaceDTO > => { - const { - spaceId, - spaceName, - spaceImage, - spaceDescription, - members, - admins, - account = null, - signer = null, - env = Constants.ENV.PROD, - pgpPrivateKey = null, - scheduleAt, - scheduleEnd, - status, - } = options || {}; - try { - if (account == null && signer == null) { - throw new Error(`At least one from account or signer is necessary!`); - } - const group = await updateGroup({ - chatId: spaceId, - groupName: spaceName, - groupImage: spaceImage, - groupDescription: spaceDescription, - members: members, - admins: admins, - account: account, - signer: signer, - env: env, - pgpPrivateKey: pgpPrivateKey, - scheduleAt: scheduleAt, - scheduleEnd: scheduleEnd, - status: status - }); +export async function update( + this: Space, + options: ChatUpdateSpaceType +): Promise { + const { spaceName, spaceImage, spaceDescription, scheduleAt, scheduleEnd } = + options || {}; + try { + const space = await get({ + spaceId: this.spaceSpecificData.spaceId, + env: this.env, + }); - return groupDtoToSpaceDto(group); - } catch (err) { - console.error( - `[Push SDK] - API - Error - API ${update.name} -: `, - err - ); - throw Error( - `[Push SDK] - API - Error - API ${update.name} -: ${err}` - ); + const convertedMembers = getSpacesMembersList( + space.members, + space.pendingMembers + ); + const convertedAdmins = getSpaceAdminsList( + space.members, + space.pendingMembers + ); + + if (space.status === ChatStatus.ACTIVE && scheduleAt) { + throw new Error('Unable change the start date/time of an active space'); } -}; \ No newline at end of file + + if (space.status === ChatStatus.ENDED && scheduleEnd) { + throw new Error('Unable change the end date/time of an ended space'); + } + + const group = await updateGroup({ + chatId: this.spaceSpecificData.spaceId, + groupName: spaceName ? spaceName : space.spaceName, + groupImage: spaceImage ? spaceImage : space.spaceImage, + groupDescription: spaceDescription + ? spaceDescription + : space.spaceDescription, + members: convertedMembers, + admins: convertedAdmins, + signer: this.signer, + env: this.env, + pgpPrivateKey: this.pgpPrivateKey, + scheduleAt: scheduleAt ? scheduleAt : space.scheduleAt, + scheduleEnd: scheduleEnd ? scheduleEnd : space.scheduleEnd, + }); + + // update space specific data + this.setSpaceSpecificData(() => groupDtoToSpaceDto(group)); + } catch (err) { + console.error(`[Push SDK] - API - Error - API ${update.name} -: `, err); + throw Error(`[Push SDK] - API - Error - API ${update.name} -: ${err}`); + } +} diff --git a/packages/restapi/src/lib/space/update_out.ts b/packages/restapi/src/lib/space/update_out.ts new file mode 100644 index 000000000..66e6e6f7a --- /dev/null +++ b/packages/restapi/src/lib/space/update_out.ts @@ -0,0 +1,72 @@ +import Constants from '../constants'; +import { EnvOptionsType, SpaceDTO, SignerType, ChatStatus } from '../types'; +import { groupDtoToSpaceDto } from './../chat/helpers'; +import { updateGroup } from '../chat/updateGroup'; +import { get } from './get'; + +export interface ChatUpdateSpaceType extends EnvOptionsType { + signer: SignerType; + spaceId: string; + spaceName: string; + spaceImage: string | null; + spaceDescription: string; + members: Array; + admins: Array; + pgpPrivateKey?: string; + scheduleAt: Date; + scheduleEnd?: Date | null; + status: ChatStatus; +} + +export const update = async ( + options: ChatUpdateSpaceType +): Promise => { + const { + spaceId, + spaceName, + spaceImage, + spaceDescription, + members, + admins, + signer, + env = Constants.ENV.PROD, + pgpPrivateKey = null, + scheduleAt, + scheduleEnd, + status, + } = options || {}; + try { + const space = await get({ + spaceId, + env, + }); + + if (space.status === ChatStatus.ACTIVE && scheduleAt) { + throw new Error('Unable change the start date/time of an active space'); + } + + if (space.status === ChatStatus.ENDED && scheduleEnd) { + throw new Error('Unable change the end date/time of an ended space'); + } + + const group = await updateGroup({ + chatId: spaceId, + groupName: spaceName, + groupImage: spaceImage, + groupDescription: spaceDescription, + members: members, + admins: admins, + signer: signer, + env: env, + pgpPrivateKey: pgpPrivateKey, + scheduleAt: scheduleAt, + scheduleEnd: scheduleEnd, + status: status, + }); + + return groupDtoToSpaceDto(group); + } catch (err) { + console.error(`[Push SDK] - API - Error - API ${update.name} -: `, err); + throw Error(`[Push SDK] - API - Error - API ${update.name} -: ${err}`); + } +}; diff --git a/packages/restapi/src/lib/types/index.ts b/packages/restapi/src/lib/types/index.ts index 48c643a85..a3b440803 100644 --- a/packages/restapi/src/lib/types/index.ts +++ b/packages/restapi/src/lib/types/index.ts @@ -3,6 +3,10 @@ import { ADDITIONAL_META_TYPE, IDENTITY_TYPE, NOTIFICATION_TYPE, + SPACE_ACCEPT_REQUEST_TYPE, + SPACE_DISCONNECT_TYPE, + SPACE_INVITE_ROLES, + SPACE_REQUEST_TYPE, } from '../../lib/payloads/constants'; import { ENV, MessageType } from '../constants'; import { EthEncryptedData } from '@metamask/eth-sig-util'; @@ -360,7 +364,12 @@ export interface SpaceDTO { spaceId: string; scheduleAt?: Date | null; scheduleEnd?: Date | null; - status: ChatStatus | null + status: ChatStatus | null; + inviteeDetails?: { [key: string]: SPACE_INVITE_ROLES }; +} + +export interface SpaceData extends SpaceDTO { + connectionData: VideoCallData; } export interface Subscribers { @@ -540,7 +549,7 @@ export type VideoCallData = { broadcast?: { livepeerInfo: any; hostAddress: string; - coHostAddress: string; + coHostAddress?: string; }; }; local: { @@ -549,7 +558,7 @@ export type VideoCallData = { video: boolean | null; address: string; }; - incoming: [PeerData]; + incoming: PeerData[]; }; export type VideoCreateInputOptions = { @@ -560,10 +569,14 @@ export type VideoCreateInputOptions = { export type VideoRequestInputOptions = { senderAddress: string; - recipientAddress: string; + recipientAddress: string | string[]; chatId: string; onReceiveMessage?: (message: string) => void; retry?: boolean; + details?: { + type: SPACE_REQUEST_TYPE; + data: Record; + }; }; export type VideoAcceptRequestInputOptions = { @@ -573,16 +586,31 @@ export type VideoAcceptRequestInputOptions = { chatId: string; onReceiveMessage?: (message: string) => void; retry?: boolean; + details?: { + type: SPACE_ACCEPT_REQUEST_TYPE; + data: Record; + }; }; export type VideoConnectInputOptions = { signalData: any; + peerAddress: string; +}; + +export type VideoDisconnectOptions = { + peerAddress: string; + details?: { + type: SPACE_DISCONNECT_TYPE; + data: Record; + }; }; export type EnableVideoInputOptions = { state: boolean; + peerAddress: string; }; export type EnableAudioInputOptions = { state: boolean; + peerAddress: string; }; diff --git a/packages/restapi/src/lib/video/Video.ts b/packages/restapi/src/lib/video/Video.ts index 92e5fb349..f1d340979 100644 --- a/packages/restapi/src/lib/video/Video.ts +++ b/packages/restapi/src/lib/video/Video.ts @@ -25,7 +25,16 @@ import { VideoCallStatus, EnableAudioInputOptions, EnableVideoInputOptions, + VideoDisconnectOptions, } from '../types'; +import getIncomingIndexFromAddress from './helpers/getIncomingIndexFromAddress'; +import getConnectedAddresses from './helpers/getConnectedAddresses'; +import getConnectToAddresses from './helpers/getConnectToAddresses'; +import { + SPACE_DISCONNECT_TYPE, + SPACE_REQUEST_TYPE, + VIDEO_CALL_TYPE, +} from '../payloads/constants'; export const initVideoCallData: VideoCallData = { meta: { @@ -34,6 +43,11 @@ export const initVideoCallData: VideoCallData = { address: '', signal: null, }, + broadcast: { + livepeerInfo: null, + hostAddress: '', + coHostAddress: '', + }, }, local: { stream: null, @@ -55,34 +69,46 @@ export const initVideoCallData: VideoCallData = { export class Video { // user, call related info - private signer: SignerType; - private chainId: number; - private pgpPrivateKey: string; - private env: ENV; + protected signer: SignerType; + protected chainId: number; + protected pgpPrivateKey: string; + protected env: ENV; + protected callType: VIDEO_CALL_TYPE; + protected onReceiveStream: (receivedStream: MediaStream) => void; // storing the peer instance - private peerInstance: any = null; + private peerInstances: { + [key: string]: any; + } = {}; - private data: VideoCallData; + protected data: VideoCallData; setData: (fn: (data: VideoCallData) => VideoCallData) => void; constructor({ signer, chainId, pgpPrivateKey, - env, + env = Constants.ENV.PROD, setData, + callType = VIDEO_CALL_TYPE.PUSH_VIDEO, + onReceiveStream = () => { + return; + }, }: { signer: SignerType; chainId: number; pgpPrivateKey: string; - env?: ENV; setData: (fn: (data: VideoCallData) => VideoCallData) => void; + env?: ENV; + callType?: VIDEO_CALL_TYPE; + onReceiveStream?: (receivedStream: MediaStream) => void; }) { this.signer = signer; this.chainId = chainId; this.pgpPrivateKey = pgpPrivateKey; - this.env = env ? env : Constants.ENV.PROD; + this.env = env; + this.callType = callType; + this.onReceiveStream = onReceiveStream; // init the react state setData(() => initVideoCallData); @@ -127,165 +153,260 @@ export class Video { async request(options: VideoRequestInputOptions): Promise { const { - senderAddress, // notification sender - recipientAddress, // notification receiver + senderAddress, + recipientAddress, chatId, onReceiveMessage = (message: string) => { console.log('received a meesage', message); }, retry = false, + details, } = options || {}; - try { - console.log( - 'request', - 'options', - options, - 'localStream', - this.data.local.stream - ); - - // fetching the iceServers config - const iceServerConfig = await getIceServerConfig(this.env); + console.log('request', 'options', options); - this.peerInstance = new Peer({ - initiator: true, - trickle: false, - stream: this.data.local.stream, - config: { - iceServers: iceServerConfig, - }, - }); + const recipientAddresses = Array.isArray(recipientAddress) + ? recipientAddress + : [recipientAddress]; - this.peerInstance.on('signal', (data: any) => { + for (const recipientAddress of recipientAddresses) { + try { + // set videoCallInfo state with status 1 (call initiated) this.setData((oldData) => { return produce(oldData, (draft) => { - draft.meta.initiator.signal = data; + draft.local.address = senderAddress; + draft.meta.chatId = chatId; + draft.meta.initiator.address = senderAddress; + + const incomingIndex = getIncomingIndexFromAddress( + oldData.incoming, + recipientAddress + ); + + if (incomingIndex === -1) { + draft.incoming.push({ + stream: null, + audio: null, + video: null, + address: recipientAddress, + status: retry + ? VideoCallStatus.RETRY_INITIALIZED + : VideoCallStatus.INITIALIZED, + retryCount: retry ? 1 : 0, + }); + } else { + draft.incoming[incomingIndex].address = recipientAddress; + draft.incoming[incomingIndex].status = retry + ? VideoCallStatus.RETRY_INITIALIZED + : VideoCallStatus.INITIALIZED; + draft.incoming[incomingIndex].retryCount += retry ? 1 : 0; + } }); }); - // sending notification to the recipientAddress with video call signaling data - sendVideoCallNotification( - { - signer: this.signer, - chainId: this.chainId, - pgpPrivateKey: this.pgpPrivateKey, + // fetching the iceServers config + const iceServerConfig = await getIceServerConfig(this.env); + this.peerInstances[recipientAddress] = new Peer({ + initiator: true, + trickle: false, + stream: this.data.local.stream, + config: { + iceServers: iceServerConfig, }, - { - senderAddress, - recipientAddress, - status: retry - ? VideoCallStatus.RETRY_INITIALIZED - : VideoCallStatus.INITIALIZED, - chatId, - signalData: data, - env: this.env, - } - ); - }); + }); - this.peerInstance.on('connect', () => { - this.peerInstance.send(`initial message from ${senderAddress}`); - this.peerInstance.send( - JSON.stringify({ - type: 'isVideoOn', - isVideoOn: this.data.local.video, - }) - ); - this.peerInstance.send( - JSON.stringify({ - type: 'isAudioOn', - isAudioOn: this.data.local.audio, - }) - ); - }); + this.peerInstances[recipientAddress].on('signal', (data: any) => { + this.setData((oldData) => { + return produce(oldData, (draft) => { + draft.meta.initiator.signal = data; + }); + }); - this.peerInstance.on('data', (data: any) => { - if (isJSON(data)) { - const parsedData = JSON.parse(data); - if (parsedData.type === 'isVideoOn') { - this.setData((oldData) => { - return produce(oldData, (draft) => { - draft.incoming[0].video = parsedData.isVideoOn; + // sending notification to the recipientAddress with video call signaling data + sendVideoCallNotification( + { + signer: this.signer, + chainId: this.chainId, + pgpPrivateKey: this.pgpPrivateKey, + }, + { + senderAddress, + recipientAddress, + status: retry + ? VideoCallStatus.RETRY_INITIALIZED + : VideoCallStatus.INITIALIZED, + chatId, + signalData: data, + env: this.env, + callType: this.callType, + callDetails: details, + } + ); + }); + + this.peerInstances[recipientAddress].on('connect', () => { + this.peerInstances[recipientAddress].send( + JSON.stringify({ + type: 'isVideoOn', + value: this.data.local.video, + }) + ); + this.peerInstances[recipientAddress].send( + JSON.stringify({ + type: 'isAudioOn', + value: this.data.local.audio, + }) + ); + }); + + this.peerInstances[recipientAddress].on('data', (data: any) => { + if (isJSON(data)) { + const parsedData = JSON.parse(data); + + if (parsedData.type === 'connectedAddress') { + console.log('CONNECTED ADDRESSES', parsedData.value); + + const receivedConnectedAddresses = parsedData.value; + const localConnectedAddresses = getConnectedAddresses({ + incomingPeers: this.data.incoming, }); - }); - } - if (parsedData.type === 'isAudioOn') { - this.setData((oldData) => { - return produce(oldData, (draft) => { - draft.incoming[0].audio = parsedData.isAudioOn; + // find out the address to which local peer is not connected to but the remote peer is + // then connect with them + const connectToAddresses = getConnectToAddresses({ + localAddress: senderAddress, + localConnectedAddresses, + receivedConnectedAddresses, }); - }); - } + for (const connectToAddress of connectToAddresses) { + this.request({ + senderAddress, + recipientAddress: connectToAddress, + chatId, + details: { + type: SPACE_REQUEST_TYPE.ESTABLISH_MESH, + data: {}, + }, + }); + } + } - if (parsedData.type === 'endCall') { - // destroy the peerInstance - this.peerInstance?.destroy(); - this.peerInstance = null; + if (parsedData.type === 'isVideoOn') { + console.log('IS VIDEO ON', parsedData.value); + this.setData((oldData) => { + return produce(oldData, (draft) => { + const incomingIndex = getIncomingIndexFromAddress( + oldData.incoming, + recipientAddress + ); + draft.incoming[incomingIndex].video = parsedData.value; + }); + }); + } - // destroy the local stream - if (this.data.local.stream) { - endStream(this.data.local.stream); + if (parsedData.type === 'isAudioOn') { + console.log('IS AUDIO ON', parsedData.value); + this.setData((oldData) => { + return produce(oldData, (draft) => { + const incomingIndex = getIncomingIndexFromAddress( + oldData.incoming, + recipientAddress + ); + draft.incoming[incomingIndex].audio = parsedData.value; + }); + }); } - // reset the state - this.setData(() => initVideoCallData); + if (parsedData.type === 'endCall') { + console.log('END CALL'); + + if ( + this.callType === VIDEO_CALL_TYPE.PUSH_SPACE && + parsedData?.details?.type === SPACE_DISCONNECT_TYPE.LEAVE + ) { + // destroy connection to only the current peer + this.peerInstances[recipientAddress]?.destroy(); + this.peerInstances[recipientAddress] = null; + this.setData((oldData) => { + return produce(oldData, (draft) => { + const incomingIndex = getIncomingIndexFromAddress( + oldData.incoming, + recipientAddress + ); + draft.incoming.splice(incomingIndex, 1); + }); + }); + } + if ( + this.callType === VIDEO_CALL_TYPE.PUSH_SPACE && + parsedData?.details?.type === SPACE_DISCONNECT_TYPE.STOP + ) { + // destroy connection to all the peers + for (const connectedAddress in this.peerInstances) { + this.peerInstances[connectedAddress]?.destroy(); + this.peerInstances[connectedAddress] = null; + } + } + + if ( + this.callType === VIDEO_CALL_TYPE.PUSH_VIDEO || + (this.callType === VIDEO_CALL_TYPE.PUSH_SPACE && + parsedData?.details?.type === SPACE_DISCONNECT_TYPE.STOP) + ) { + // destroy the local stream + if (this.data.local.stream) { + endStream(this.data.local.stream); + } + + // reset the state + this.setData(() => initVideoCallData); + } + } + } else { + onReceiveMessage(data); } - } else { - onReceiveMessage(data); - } - }); - - this.peerInstance.on('stream', (currentStream: MediaStream) => { - this.setData((oldData) => { - return produce(oldData, (draft) => { - draft.incoming[0].stream = currentStream; - }); }); - }); - // set videoCallInfo state with status 1 (call initiated) - this.setData((oldData) => { - return produce(oldData, (draft) => { - draft.local.address = senderAddress; - draft.incoming[0].address = recipientAddress; - draft.meta.chatId = chatId; - draft.meta.initiator.address = senderAddress; - draft.incoming[0].status = retry - ? VideoCallStatus.RETRY_INITIALIZED - : VideoCallStatus.INITIALIZED; - draft.incoming[0].retryCount += retry ? 1 : 0; - }); - }); - } catch (err) { - console.log('error in request', err); + this.peerInstances[recipientAddress].on( + 'stream', + (currentStream: MediaStream) => { + console.log('received incoming stream', currentStream); + this.onReceiveStream(currentStream); + this.setData((oldData) => { + return produce(oldData, (draft) => { + const incomingIndex = getIncomingIndexFromAddress( + oldData.incoming, + recipientAddress + ); + draft.incoming[incomingIndex].stream = currentStream; + }); + }); + } + ); + } catch (err) { + console.log('error in request', err); + } } } async acceptRequest(options: VideoAcceptRequestInputOptions): Promise { const { signalData, - senderAddress, // notification sender - recipientAddress, // notification receiver + senderAddress, + recipientAddress, chatId, onReceiveMessage = (message: string) => { console.log('received a meesage', message); }, retry = false, + details, } = options || {}; try { - console.log( - 'accept request', - 'options', - options, - 'peerInstance', - this.peerInstance - ); + console.log('accept request', 'options', options); // if peerInstance is not null -> acceptRequest/request was called before - if (this.peerInstance) { + if (this.peerInstances[recipientAddress]) { // to prevent connection error we stop the exec of acceptRequest return Promise.resolve(); } @@ -294,20 +415,39 @@ export class Video { this.setData((oldData) => { return produce(oldData, (draft) => { draft.local.address = senderAddress; - draft.incoming[0].address = recipientAddress; draft.meta.chatId = chatId; draft.meta.initiator.address = senderAddress; - draft.incoming[0].status = retry - ? VideoCallStatus.RETRY_RECEIVED - : VideoCallStatus.RECEIVED; - draft.incoming[0].retryCount += retry ? 1 : 0; + + const incomingIndex = getIncomingIndexFromAddress( + oldData.incoming, + recipientAddress + ); + + if (incomingIndex === -1) { + draft.incoming.push({ + stream: null, + audio: null, + video: null, + address: recipientAddress, + status: retry + ? VideoCallStatus.RETRY_INITIALIZED + : VideoCallStatus.INITIALIZED, + retryCount: retry ? 1 : 0, + }); + } else { + draft.incoming[incomingIndex].address = recipientAddress; + draft.incoming[incomingIndex].status = retry + ? VideoCallStatus.RETRY_RECEIVED + : VideoCallStatus.RECEIVED; + draft.incoming[incomingIndex].retryCount += retry ? 1 : 0; + } }); }); // fetching the iceServers config const iceServerConfig = await getIceServerConfig(this.env); - this.peerInstance = new Peer({ + this.peerInstances[recipientAddress] = new Peer({ initiator: false, trickle: false, stream: this.data.local.stream, @@ -317,12 +457,12 @@ export class Video { }); // setup error handler - this.peerInstance.on('error', (err: any) => { + this.peerInstances[recipientAddress].on('error', (err: any) => { console.log('error in accept request', err); if (this.data.incoming[0].retryCount >= 5) { console.log('Max retries exceeded, please try again.'); - this.disconnect(); + this.disconnect({ peerAddress: recipientAddress }); } // retrying in case of connection error @@ -343,9 +483,9 @@ export class Video { ); }); - this.peerInstance.signal(signalData); + this.peerInstances[recipientAddress].signal(signalData); - this.peerInstance.on('signal', (data: any) => { + this.peerInstances[recipientAddress].on('signal', (data: any) => { this.setData((oldData) => { return produce(oldData, (draft) => { draft.meta.initiator.signal = data; @@ -367,112 +507,225 @@ export class Video { chatId, signalData: data, env: this.env, + callType: this.callType, + callDetails: details, } ); }); - this.peerInstance.on('connect', () => { - this.peerInstance.send('initial message from receiver'); - this.peerInstance.send( + this.peerInstances[recipientAddress].on('connect', () => { + this.peerInstances[recipientAddress].send( JSON.stringify({ type: 'isVideoOn', - isVideoOn: this.data.local.video, + value: this.data.local.video, }) ); - this.peerInstance.send( + this.peerInstances[recipientAddress].send( JSON.stringify({ type: 'isAudioOn', - isAudioOn: this.data.local.audio, + value: this.data.local.audio, }) ); // set videoCallInfo state with status connected for the receiver's end this.setData((oldData) => { return produce(oldData, (draft) => { - draft.incoming[0].status = VideoCallStatus.CONNECTED; + const incomingIndex = getIncomingIndexFromAddress( + oldData.incoming, + recipientAddress + ); + draft.incoming[incomingIndex].status = VideoCallStatus.CONNECTED; }); }); }); - this.peerInstance.on('data', (data: any) => { + this.peerInstances[recipientAddress].on('data', (data: any) => { if (isJSON(data)) { const parsedData = JSON.parse(data); + + if (parsedData.type === 'connectedAddress') { + console.log('CONNECTED ADDRESSES', parsedData.value); + + const receivedConnectedAddresses = parsedData.value; + const localConnectedAddresses = getConnectedAddresses({ + incomingPeers: this.data.incoming, + }); + + // find out the address to which local peer is not connected to but the remote peer is + // then connect with them + const connectToAddresses = getConnectToAddresses({ + localAddress: senderAddress, + localConnectedAddresses, + receivedConnectedAddresses, + }); + for (const connectToAddress of connectToAddresses) { + this.request({ + senderAddress, + recipientAddress: connectToAddress, + chatId, + details: { + type: SPACE_REQUEST_TYPE.ESTABLISH_MESH, + data: {}, + }, + }); + } + + // send the addresses the local peer is connected to remote peer + this.peerInstances[recipientAddress].send( + JSON.stringify({ + type: 'connectedAddresses', + value: localConnectedAddresses, + }) + ); + } + if (parsedData.type === 'isVideoOn') { + console.log('IS VIDEO ON', parsedData.value); this.setData((oldData) => { return produce(oldData, (draft) => { - draft.incoming[0].video = parsedData.isVideoOn; + const incomingIndex = getIncomingIndexFromAddress( + oldData.incoming, + recipientAddress + ); + draft.incoming[incomingIndex].video = parsedData.value; }); }); } if (parsedData.type === 'isAudioOn') { + console.log('IS AUDIO ON', parsedData.value); this.setData((oldData) => { return produce(oldData, (draft) => { - draft.incoming[0].audio = parsedData.isAudioOn; + const incomingIndex = getIncomingIndexFromAddress( + oldData.incoming, + recipientAddress + ); + draft.incoming[incomingIndex].audio = parsedData.value; }); }); } if (parsedData.type === 'endCall') { - // destroy the peerInstance - this.peerInstance?.destroy(); - this.peerInstance = null; - - // destroy the local stream - if (this.data.local.stream) { - endStream(this.data.local.stream); + console.log('END CALL'); + + if ( + this.callType === VIDEO_CALL_TYPE.PUSH_SPACE && + parsedData?.details?.type === SPACE_DISCONNECT_TYPE.LEAVE + ) { + // destroy connection to only the current peer + this.peerInstances[recipientAddress]?.destroy(); + this.peerInstances[recipientAddress] = null; + this.setData((oldData) => { + return produce(oldData, (draft) => { + const incomingIndex = getIncomingIndexFromAddress( + oldData.incoming, + recipientAddress + ); + draft.incoming.splice(incomingIndex, 1); + }); + }); + } + if ( + this.callType === VIDEO_CALL_TYPE.PUSH_SPACE && + parsedData?.details?.type === SPACE_DISCONNECT_TYPE.STOP + ) { + // destroy connection to all the peers + for (const connectedAddress in this.peerInstances) { + this.peerInstances[connectedAddress]?.destroy(); + this.peerInstances[connectedAddress] = null; + } } - // reset the state - this.setData(() => initVideoCallData); + if ( + this.callType === VIDEO_CALL_TYPE.PUSH_VIDEO || + (this.callType === VIDEO_CALL_TYPE.PUSH_SPACE && + parsedData?.details?.type === SPACE_DISCONNECT_TYPE.STOP) + ) { + // destroy the local stream + if (this.data.local.stream) { + endStream(this.data.local.stream); + } + + // reset the state + this.setData(() => initVideoCallData); + } } } else { onReceiveMessage(data); } }); - this.peerInstance.on('stream', (currentStream: MediaStream) => { - this.setData((oldData) => { - return produce(oldData, (draft) => { - draft.incoming[0].stream = currentStream; + this.peerInstances[recipientAddress].on( + 'stream', + (currentStream: MediaStream) => { + console.log('received incoming stream', currentStream); + this.onReceiveStream(currentStream); + this.setData((oldData) => { + return produce(oldData, (draft) => { + const incomingIndex = getIncomingIndexFromAddress( + oldData.incoming, + recipientAddress + ); + draft.incoming[incomingIndex].stream = currentStream; + }); }); - }); - }); + } + ); } catch (err) { console.log('error in accept request', err); } } connect(options: VideoConnectInputOptions): void { - const { signalData } = options || {}; + const { signalData, peerAddress } = options || {}; try { console.log('connect', 'options', options); // setup error handler - this.peerInstance.on('error', (err: any) => { + this.peerInstances[peerAddress].on('error', (err: any) => { console.log('error in connect', err); - if (this.data.incoming[0].retryCount >= 5) { + const incomingIndex = getIncomingIndexFromAddress( + this.data.incoming, + peerAddress + ); + + if (this.data.incoming[incomingIndex].retryCount >= 5) { console.log('Max retries exceeded, please try again.'); - this.disconnect(); + this.disconnect({ peerAddress }); } // retrying in case of connection error this.request({ senderAddress: this.data.local.address, - recipientAddress: this.data.incoming[0].address, + recipientAddress: this.data.incoming[incomingIndex].address, chatId: this.data.meta.chatId, retry: true, }); }); - this.peerInstance?.signal(signalData); + this.peerInstances[peerAddress]?.signal(signalData); + + // send the addresses the local peer is connected to remote peer + const connectedAddresses = getConnectedAddresses({ + incomingPeers: this.data.incoming, + }); + this.peerInstances[peerAddress].send( + JSON.stringify({ + type: 'connectedAddresses', + value: connectedAddresses, + }) + ); // set videoCallInfo state with status connected for the caller's end this.setData((oldData) => { return produce(oldData, (draft) => { - draft.incoming[0].status = VideoCallStatus.CONNECTED; + const incomingIndex = getIncomingIndexFromAddress( + oldData.incoming, + peerAddress + ); + draft.incoming[incomingIndex].status = VideoCallStatus.CONNECTED; }); }); } catch (err) { @@ -480,13 +733,27 @@ export class Video { } } - disconnect(): void { + disconnect(options: VideoDisconnectOptions): void { + const { peerAddress, details } = options || {}; + try { - console.log('disconnect', 'status', this.data.incoming[0].status); - if (this.data.incoming[0].status === VideoCallStatus.CONNECTED) { - this.peerInstance?.send( - JSON.stringify({ type: 'endCall', endCall: true }) + const incomingIndex = getIncomingIndexFromAddress( + this.data.incoming, + peerAddress + ); + + console.log( + 'disconnect', + 'status', + this.data.incoming[incomingIndex].status + ); + if ( + this.data.incoming[incomingIndex].status === VideoCallStatus.CONNECTED + ) { + this.peerInstances[peerAddress]?.send( + JSON.stringify({ type: 'endCall', value: true, details }) ); + this.peerInstances[peerAddress]?.destroy(); } else { // for disconnecting during status INITIALIZED, RECEIVED, RETRY_INITIALIZED, RETRY_RECEIVED // send a notif to the other user signaling status = DISCONNECTED @@ -498,18 +765,20 @@ export class Video { }, { senderAddress: this.data.local.address, - recipientAddress: this.data.incoming[0].address, + recipientAddress: this.data.incoming[incomingIndex].address, status: VideoCallStatus.DISCONNECTED, chatId: this.data.meta.chatId, signalData: null, env: this.env, + callType: this.callType, + callDetails: details, } ); } // destroy the peerInstance - this.peerInstance?.destroy(); - this.peerInstance = null; + this.peerInstances[peerAddress]?.destroy(); + this.peerInstances[peerAddress] = null; // destroy the local stream if (this.data.local.stream) { @@ -526,16 +795,23 @@ export class Video { // functions for enabling/disabling local audio and video enableVideo(options: EnableVideoInputOptions): void { - const { state } = options || {}; + const { state, peerAddress } = options || {}; if (this.data.local.video !== state) { // need to change the video state - if (this.data.incoming[0].status === VideoCallStatus.CONNECTED) { - this.peerInstance?.send( + const incomingIndex = getIncomingIndexFromAddress( + this.data.incoming, + peerAddress + ); + + if ( + this.data.incoming[incomingIndex].status === VideoCallStatus.CONNECTED + ) { + this.peerInstances[peerAddress]?.send( JSON.stringify({ type: 'isVideoOn', - isVideoOn: state, + value: state, }) ); } @@ -555,14 +831,21 @@ export class Video { } enableAudio(options: EnableAudioInputOptions): void { - const { state } = options || {}; + const { state, peerAddress } = options || {}; if (this.data.local.audio !== state) { // need to change the audio state - if (this.data.incoming[0].status === VideoCallStatus.CONNECTED) { - this.peerInstance?.send( - JSON.stringify({ type: 'isAudioOn', isAudioOn: state }) + const incomingIndex = getIncomingIndexFromAddress( + this.data.incoming, + peerAddress + ); + + if ( + this.data.incoming[incomingIndex].status === VideoCallStatus.CONNECTED + ) { + this.peerInstances[peerAddress]?.send( + JSON.stringify({ type: 'isAudioOn', value: state }) ); } if (this.data.local.stream) { diff --git a/packages/restapi/src/lib/video/helpers/getConnectToAddresses.ts b/packages/restapi/src/lib/video/helpers/getConnectToAddresses.ts new file mode 100644 index 000000000..6731ef169 --- /dev/null +++ b/packages/restapi/src/lib/video/helpers/getConnectToAddresses.ts @@ -0,0 +1,17 @@ +const getConnectToAddresses = ({ + localAddress, + localConnectedAddresses, + receivedConnectedAddresses, +}: { + localAddress: string; + localConnectedAddresses: string[]; + receivedConnectedAddresses: string[]; +}): string[] => { + return receivedConnectedAddresses.filter( + (receivedConnectedAddress) => + !localConnectedAddresses.includes(receivedConnectedAddress) && + receivedConnectedAddress !== localAddress + ); +}; + +export default getConnectToAddresses; diff --git a/packages/restapi/src/lib/video/helpers/getConnectedAddresses.ts b/packages/restapi/src/lib/video/helpers/getConnectedAddresses.ts new file mode 100644 index 000000000..7e9d9a149 --- /dev/null +++ b/packages/restapi/src/lib/video/helpers/getConnectedAddresses.ts @@ -0,0 +1,17 @@ +import { PeerData, VideoCallStatus } from '../../types'; + +const getConnectedAddresses = ({ + incomingPeers, +}: { + incomingPeers: PeerData[]; +}): string[] => { + const connectedAddresses: string[] = []; + incomingPeers.forEach((incomingPeer) => { + if (incomingPeer.status === VideoCallStatus.CONNECTED) { + connectedAddresses.push(incomingPeer.address); + } + }); + return connectedAddresses; +}; + +export default getConnectedAddresses; diff --git a/packages/restapi/src/lib/video/helpers/getIceServerConfig.ts b/packages/restapi/src/lib/video/helpers/getIceServerConfig.ts index 8e7acdad8..cb0d5ebaa 100644 --- a/packages/restapi/src/lib/video/helpers/getIceServerConfig.ts +++ b/packages/restapi/src/lib/video/helpers/getIceServerConfig.ts @@ -1,10 +1,20 @@ import axios from 'axios'; import { getAPIBaseUrls } from '../../helpers'; import Constants from '../../constants'; +import * as CryptoJS from 'crypto-js'; + +const ENCRYPTION_KEY = 'turnserversecret'; export const getIceServerConfig = async (env = Constants.ENV.PROD) => { const API_BASE_URL = getAPIBaseUrls(env); const apiEndpoint = `${API_BASE_URL}/v1/turnserver/iceconfig`; - const { data } = await axios.get(apiEndpoint); - return data; + const { data: encryptedData } = await axios.get(apiEndpoint); + + const { config: decryptedData } = JSON.parse( + CryptoJS.AES.decrypt(encryptedData, ENCRYPTION_KEY).toString( + CryptoJS.enc.Utf8 + ) + ); + + return decryptedData; }; diff --git a/packages/restapi/src/lib/video/helpers/getIncomingIndexFromAddress.ts b/packages/restapi/src/lib/video/helpers/getIncomingIndexFromAddress.ts new file mode 100644 index 000000000..e4c61cf44 --- /dev/null +++ b/packages/restapi/src/lib/video/helpers/getIncomingIndexFromAddress.ts @@ -0,0 +1,7 @@ +import { PeerData } from "../../types"; + +const getIncomingIndexFromAddress = (incomingPeers: PeerData[], address: string) => { + return incomingPeers.findIndex(incomingPeer => incomingPeer.address === address); +} + +export default getIncomingIndexFromAddress; diff --git a/packages/restapi/src/lib/video/helpers/sendVideoCallNotification.ts b/packages/restapi/src/lib/video/helpers/sendVideoCallNotification.ts index 07beed66c..935375d6e 100644 --- a/packages/restapi/src/lib/video/helpers/sendVideoCallNotification.ts +++ b/packages/restapi/src/lib/video/helpers/sendVideoCallNotification.ts @@ -1,9 +1,20 @@ import Constants, { ENV } from '../../constants'; import { getCAIPWithChainId } from '../../helpers'; import { sendNotification } from '../../payloads'; -import { ADDITIONAL_META_TYPE } from '../../payloads/constants'; +import { + NOTIFICATION_TYPE, + SPACE_ACCEPT_REQUEST_TYPE, + SPACE_DISCONNECT_TYPE, + SPACE_REQUEST_TYPE, + VIDEO_CALL_TYPE, +} from '../../payloads/constants'; import { SignerType, VideoCallStatus } from '../../types'; +interface CallDetailsType { + type: SPACE_REQUEST_TYPE | SPACE_ACCEPT_REQUEST_TYPE | SPACE_DISCONNECT_TYPE; + data: Record; +}; + interface VideoCallInfoType { recipientAddress: string; senderAddress: string; @@ -11,6 +22,8 @@ interface VideoCallInfoType { signalData: any; status: VideoCallStatus; env?: ENV; + callType?: VIDEO_CALL_TYPE; + callDetails?: CallDetailsType; } interface UserInfoType { @@ -19,12 +32,13 @@ interface UserInfoType { pgpPrivateKey: string; } -interface VideoDataType { +export interface VideoDataType { recipientAddress: string; senderAddress: string; chatId: string; signalData?: any; status: VideoCallStatus; + callDetails?: CallDetailsType; } const sendVideoCallNotification = async ( @@ -33,9 +47,11 @@ const sendVideoCallNotification = async ( recipientAddress, senderAddress, chatId, - signalData = null, status, + signalData = null, env = Constants.ENV.PROD, + callType = VIDEO_CALL_TYPE.PUSH_VIDEO, + callDetails }: VideoCallInfoType ) => { try { @@ -45,6 +61,7 @@ const sendVideoCallNotification = async ( chatId, signalData, status, + callDetails }; console.log('sendVideoCallNotification', 'videoData', videoData); @@ -57,12 +74,14 @@ const sendVideoCallNotification = async ( const notificationText = `Video Call from ${senderAddress}`; + const notificationType = NOTIFICATION_TYPE.TARGETTED; + await sendNotification({ senderType: 1, // for chat notification signer, pgpPrivateKey, chatId, - type: 3, + type: notificationType, identityType: 2, notification: { title: notificationText, @@ -74,9 +93,10 @@ const sendVideoCallNotification = async ( cta: '', img: '', additionalMeta: { - type: `${ADDITIONAL_META_TYPE.PUSH_VIDEO}+1`, + // type: `${callType}+1`, + type: `${VIDEO_CALL_TYPE.PUSH_VIDEO}+1`, data: JSON.stringify(videoData), - } + }, }, recipients: recipientAddressInCaip, channel: senderAddressInCaip, diff --git a/packages/restapi/src/lib/video/index.ts b/packages/restapi/src/lib/video/index.ts index b157270a0..ac0701b1a 100644 --- a/packages/restapi/src/lib/video/index.ts +++ b/packages/restapi/src/lib/video/index.ts @@ -1 +1,2 @@ export * from './Video'; +export { VideoDataType } from './helpers/sendVideoCallNotification'; diff --git a/packages/restapi/yarn.lock b/packages/restapi/yarn.lock index ebb32538b..5bb63c29d 100644 --- a/packages/restapi/yarn.lock +++ b/packages/restapi/yarn.lock @@ -3,1798 +3,1585 @@ "@chainsafe/as-sha256@^0.3.1": - "integrity" "sha512-hldFFYuf49ed7DAakWVXSJODuq3pzJEguD8tQ7h+sGkM18vja+OFoJI9krnGmgzyuZC2ETX0NOIcCTy31v2Mtg==" - "resolved" "https://registry.npmjs.org/@chainsafe/as-sha256/-/as-sha256-0.3.1.tgz" - "version" "0.3.1" + version "0.3.1" + resolved "https://registry.npmjs.org/@chainsafe/as-sha256/-/as-sha256-0.3.1.tgz" + integrity sha512-hldFFYuf49ed7DAakWVXSJODuq3pzJEguD8tQ7h+sGkM18vja+OFoJI9krnGmgzyuZC2ETX0NOIcCTy31v2Mtg== "@chainsafe/persistent-merkle-tree@^0.4.2": - "integrity" "sha512-lLO3ihKPngXLTus/L7WHKaw9PnNJWizlOF1H9NNzHP6Xvh82vzg9F2bzkXhYIFshMZ2gTCEz8tq6STe7r5NDfQ==" - "resolved" "https://registry.npmjs.org/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.4.2.tgz" - "version" "0.4.2" + version "0.4.2" + resolved "https://registry.npmjs.org/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.4.2.tgz" + integrity sha512-lLO3ihKPngXLTus/L7WHKaw9PnNJWizlOF1H9NNzHP6Xvh82vzg9F2bzkXhYIFshMZ2gTCEz8tq6STe7r5NDfQ== dependencies: "@chainsafe/as-sha256" "^0.3.1" "@chainsafe/ssz@0.9.4": - "integrity" "sha512-77Qtg2N1ayqs4Bg/wvnWfg5Bta7iy7IRh8XqXh7oNMeP2HBbBwx8m6yTpA8p0EHItWPEBkgZd5S5/LSlp3GXuQ==" - "resolved" "https://registry.npmjs.org/@chainsafe/ssz/-/ssz-0.9.4.tgz" - "version" "0.9.4" + version "0.9.4" + resolved "https://registry.npmjs.org/@chainsafe/ssz/-/ssz-0.9.4.tgz" + integrity sha512-77Qtg2N1ayqs4Bg/wvnWfg5Bta7iy7IRh8XqXh7oNMeP2HBbBwx8m6yTpA8p0EHItWPEBkgZd5S5/LSlp3GXuQ== dependencies: "@chainsafe/as-sha256" "^0.3.1" "@chainsafe/persistent-merkle-tree" "^0.4.2" - "case" "^1.6.3" + case "^1.6.3" "@cspotcode/source-map-support@^0.8.0": - "integrity" "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==" - "resolved" "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz" - "version" "0.8.1" + version "0.8.1" + resolved "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== dependencies: "@jridgewell/trace-mapping" "0.3.9" "@ethereumjs/rlp@^4.0.1": - "integrity" "sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==" - "resolved" "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-4.0.1.tgz" - "version" "4.0.1" + version "4.0.1" + resolved "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-4.0.1.tgz" + integrity sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw== "@ethereumjs/util@^8.0.0": - "integrity" "sha512-259rXKK3b3D8HRVdRmlOEi6QFvwxdt304hhrEAmpZhsj7ufXEOTIc9JRZPMnXatKjECokdLNBcDOFBeBSzAIaw==" - "resolved" "https://registry.npmjs.org/@ethereumjs/util/-/util-8.0.5.tgz" - "version" "8.0.5" + version "8.0.5" + resolved "https://registry.npmjs.org/@ethereumjs/util/-/util-8.0.5.tgz" + integrity sha512-259rXKK3b3D8HRVdRmlOEi6QFvwxdt304hhrEAmpZhsj7ufXEOTIc9JRZPMnXatKjECokdLNBcDOFBeBSzAIaw== dependencies: "@chainsafe/ssz" "0.9.4" "@ethereumjs/rlp" "^4.0.1" - "ethereum-cryptography" "^1.1.2" - -"@ethersproject/abi@^5.7.0", "@ethersproject/abi@5.7.0": - "integrity" "sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==" - "resolved" "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz" - "version" "5.7.0" - dependencies: - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/abstract-provider@^5.7.0", "@ethersproject/abstract-provider@5.7.0": - "integrity" "sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==" - "resolved" "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz" - "version" "5.7.0" - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/networks" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/web" "^5.7.0" - -"@ethersproject/abstract-signer@^5.7.0", "@ethersproject/abstract-signer@5.7.0": - "integrity" "sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==" - "resolved" "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz" - "version" "5.7.0" - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - -"@ethersproject/address@^5.7.0", "@ethersproject/address@5.7.0": - "integrity" "sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==" - "resolved" "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz" - "version" "5.7.0" - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - -"@ethersproject/base64@^5.7.0", "@ethersproject/base64@5.7.0": - "integrity" "sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==" - "resolved" "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz" - "version" "5.7.0" - dependencies: - "@ethersproject/bytes" "^5.7.0" - -"@ethersproject/basex@^5.7.0", "@ethersproject/basex@5.7.0": - "integrity" "sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==" - "resolved" "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.7.0.tgz" - "version" "5.7.0" - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - -"@ethersproject/bignumber@^5.7.0", "@ethersproject/bignumber@5.7.0": - "integrity" "sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==" - "resolved" "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz" - "version" "5.7.0" - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "bn.js" "^5.2.1" - -"@ethersproject/bytes@^5.7.0", "@ethersproject/bytes@5.7.0": - "integrity" "sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==" - "resolved" "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz" - "version" "5.7.0" - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/constants@^5.7.0", "@ethersproject/constants@5.7.0": - "integrity" "sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==" - "resolved" "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz" - "version" "5.7.0" - dependencies: - "@ethersproject/bignumber" "^5.7.0" - -"@ethersproject/contracts@5.7.0": - "integrity" "sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==" - "resolved" "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.7.0.tgz" - "version" "5.7.0" - dependencies: - "@ethersproject/abi" "^5.7.0" - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - -"@ethersproject/hash@^5.7.0", "@ethersproject/hash@5.7.0": - "integrity" "sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==" - "resolved" "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz" - "version" "5.7.0" - dependencies: - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/base64" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/hdnode@^5.7.0", "@ethersproject/hdnode@5.7.0": - "integrity" "sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==" - "resolved" "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.7.0.tgz" - "version" "5.7.0" - dependencies: - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/basex" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/pbkdf2" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/signing-key" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/wordlists" "^5.7.0" - -"@ethersproject/json-wallets@^5.7.0", "@ethersproject/json-wallets@5.7.0": - "integrity" "sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==" - "resolved" "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz" - "version" "5.7.0" - dependencies: - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/hdnode" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/pbkdf2" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "aes-js" "3.0.0" - "scrypt-js" "3.0.1" - -"@ethersproject/keccak256@^5.7.0", "@ethersproject/keccak256@5.7.0": - "integrity" "sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==" - "resolved" "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz" - "version" "5.7.0" - dependencies: - "@ethersproject/bytes" "^5.7.0" - "js-sha3" "0.8.0" - -"@ethersproject/logger@^5.7.0", "@ethersproject/logger@5.7.0": - "integrity" "sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==" - "resolved" "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz" - "version" "5.7.0" - -"@ethersproject/networks@^5.7.0", "@ethersproject/networks@5.7.1": - "integrity" "sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==" - "resolved" "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz" - "version" "5.7.1" - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/pbkdf2@^5.7.0", "@ethersproject/pbkdf2@5.7.0": - "integrity" "sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==" - "resolved" "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz" - "version" "5.7.0" - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - -"@ethersproject/properties@^5.7.0", "@ethersproject/properties@5.7.0": - "integrity" "sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==" - "resolved" "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz" - "version" "5.7.0" - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/providers@5.7.2": - "integrity" "sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==" - "resolved" "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.7.2.tgz" - "version" "5.7.2" - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/base64" "^5.7.0" - "@ethersproject/basex" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/networks" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/web" "^5.7.0" - "bech32" "1.1.4" - "ws" "7.4.6" - -"@ethersproject/random@^5.7.0", "@ethersproject/random@5.7.0": - "integrity" "sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==" - "resolved" "https://registry.npmjs.org/@ethersproject/random/-/random-5.7.0.tgz" - "version" "5.7.0" - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/rlp@^5.7.0", "@ethersproject/rlp@5.7.0": - "integrity" "sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==" - "resolved" "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz" - "version" "5.7.0" - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/sha2@^5.7.0", "@ethersproject/sha2@5.7.0": - "integrity" "sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==" - "resolved" "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.7.0.tgz" - "version" "5.7.0" - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "hash.js" "1.1.7" - -"@ethersproject/signing-key@^5.7.0", "@ethersproject/signing-key@5.7.0": - "integrity" "sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==" - "resolved" "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz" - "version" "5.7.0" - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "bn.js" "^5.2.1" - "elliptic" "6.5.4" - "hash.js" "1.1.7" - -"@ethersproject/solidity@5.7.0": - "integrity" "sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==" - "resolved" "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.7.0.tgz" - "version" "5.7.0" - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/strings@^5.7.0", "@ethersproject/strings@5.7.0": - "integrity" "sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==" - "resolved" "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz" - "version" "5.7.0" - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/transactions@^5.7.0", "@ethersproject/transactions@5.7.0": - "integrity" "sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==" - "resolved" "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz" - "version" "5.7.0" - dependencies: - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - "@ethersproject/signing-key" "^5.7.0" - -"@ethersproject/units@5.7.0": - "integrity" "sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==" - "resolved" "https://registry.npmjs.org/@ethersproject/units/-/units-5.7.0.tgz" - "version" "5.7.0" - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/wallet@5.7.0": - "integrity" "sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==" - "resolved" "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.7.0.tgz" - "version" "5.7.0" - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/hdnode" "^5.7.0" - "@ethersproject/json-wallets" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/signing-key" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/wordlists" "^5.7.0" - -"@ethersproject/web@^5.7.0", "@ethersproject/web@5.7.1": - "integrity" "sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==" - "resolved" "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz" - "version" "5.7.1" - dependencies: - "@ethersproject/base64" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/wordlists@^5.7.0", "@ethersproject/wordlists@5.7.0": - "integrity" "sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==" - "resolved" "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.7.0.tgz" - "version" "5.7.0" - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" + ethereum-cryptography "^1.1.2" "@jridgewell/resolve-uri@^3.0.3": - "integrity" "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" - "resolved" "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz" - "version" "3.1.0" + version "3.1.0" + resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== "@jridgewell/sourcemap-codec@^1.4.10": - "integrity" "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" - "resolved" "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz" - "version" "1.4.14" + version "1.4.14" + resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== "@jridgewell/trace-mapping@0.3.9": - "integrity" "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==" - "resolved" "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz" - "version" "0.3.9" + version "0.3.9" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== dependencies: "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" +"@livepeer/core@^1.5.8": + version "1.5.8" + resolved "https://registry.yarnpkg.com/@livepeer/core/-/core-1.5.8.tgz#c048bffb216a7d0dc831d2de2956652262b318de" + integrity sha512-h/afwfan0y5DugHz/lZhsTzTeDs2lzVFuuHyJrU3EPZl0SvHHFT0cI47/vRjLY6aV1UfJglQwZAa6auPrVXM9w== + dependencies: + cross-fetch "^3.1.5" + ms "^3.0.0-canary.1" + multiformats "9.9.0" + tus-js-client "^3.0.1" + zustand "^4.3.2" + +"@livepeer/webrtmp-sdk@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@livepeer/webrtmp-sdk/-/webrtmp-sdk-0.2.3.tgz#10c5baca5517b8f14ec766df15be467d14e7c8d7" + integrity sha512-tJ2gGhUZfbeXmIkZHxY/WNS0C9SYUhJ/6QlYhot1CJlBuXkuoki9gSGhYhS3G7Vu/HchL1HU/DXWKhrQhlogXg== + dependencies: + events "3.3.0" + "@metamask/eth-sig-util@^5.0.2": - "integrity" "sha512-RU6fG/H6/UlBol221uBkq5C7w3TwLK611nEZliO2u+kO0vHKGBXnIPlhI0tzKUigjhUeOd9mhCNbNvhh0LKt9Q==" - "resolved" "https://registry.npmjs.org/@metamask/eth-sig-util/-/eth-sig-util-5.0.2.tgz" - "version" "5.0.2" + version "5.0.2" + resolved "https://registry.npmjs.org/@metamask/eth-sig-util/-/eth-sig-util-5.0.2.tgz" + integrity sha512-RU6fG/H6/UlBol221uBkq5C7w3TwLK611nEZliO2u+kO0vHKGBXnIPlhI0tzKUigjhUeOd9mhCNbNvhh0LKt9Q== dependencies: "@ethereumjs/util" "^8.0.0" - "bn.js" "^4.11.8" - "ethereum-cryptography" "^1.1.2" - "ethjs-util" "^0.1.6" - "tweetnacl" "^1.0.3" - "tweetnacl-util" "^0.15.1" - -"@noble/hashes@~1.2.0", "@noble/hashes@1.2.0": - "integrity" "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==" - "resolved" "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz" - "version" "1.2.0" - -"@noble/secp256k1@~1.7.0", "@noble/secp256k1@1.7.1": - "integrity" "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==" - "resolved" "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz" - "version" "1.7.1" + bn.js "^4.11.8" + ethereum-cryptography "^1.1.2" + ethjs-util "^0.1.6" + tweetnacl "^1.0.3" + tweetnacl-util "^0.15.1" + +"@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": + version "1.2.0" + resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz" + integrity sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ== + +"@noble/secp256k1@1.7.1", "@noble/secp256k1@~1.7.0": + version "1.7.1" + resolved "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz" + integrity sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw== "@scure/base@~1.1.0": - "integrity" "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==" - "resolved" "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz" - "version" "1.1.1" + version "1.1.1" + resolved "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz" + integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA== "@scure/bip32@1.1.5": - "integrity" "sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==" - "resolved" "https://registry.npmjs.org/@scure/bip32/-/bip32-1.1.5.tgz" - "version" "1.1.5" + version "1.1.5" + resolved "https://registry.npmjs.org/@scure/bip32/-/bip32-1.1.5.tgz" + integrity sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw== dependencies: "@noble/hashes" "~1.2.0" "@noble/secp256k1" "~1.7.0" "@scure/base" "~1.1.0" "@scure/bip39@1.1.1": - "integrity" "sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==" - "resolved" "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.1.tgz" - "version" "1.1.1" + version "1.1.1" + resolved "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.1.tgz" + integrity sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg== dependencies: "@noble/hashes" "~1.2.0" "@scure/base" "~1.1.0" +"@stitches/core@^1.2.8": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@stitches/core/-/core-1.2.8.tgz#dce3b8fdc764fbc6dbea30c83b73bfb52cf96173" + integrity sha512-Gfkvwk9o9kE9r9XNBmJRfV8zONvXThnm1tcuojL04Uy5uRyqg93DC83lDebl0rocZCfKSjUv+fWYtMQmEDJldg== + "@tsconfig/node10@^1.0.7": - "integrity" "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==" - "resolved" "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz" - "version" "1.0.9" + version "1.0.9" + resolved "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz" + integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== "@tsconfig/node12@^1.0.7": - "integrity" "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" - "resolved" "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz" - "version" "1.0.11" + version "1.0.11" + resolved "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== "@tsconfig/node14@^1.0.0": - "integrity" "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" - "resolved" "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz" - "version" "1.0.3" + version "1.0.3" + resolved "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== "@tsconfig/node16@^1.0.2": - "integrity" "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==" - "resolved" "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz" - "version" "1.0.3" + version "1.0.3" + resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz" + integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== "@types/chai-as-promised@^7.1.5": - "integrity" "sha512-jStwss93SITGBwt/niYrkf2C+/1KTeZCZl1LaeezTlqppAKeoQC7jxyqYuP72sxBGKCIbw7oHgbYssIRzT5FCQ==" - "resolved" "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.5.tgz" - "version" "7.1.5" + version "7.1.5" + resolved "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.5.tgz" + integrity sha512-jStwss93SITGBwt/niYrkf2C+/1KTeZCZl1LaeezTlqppAKeoQC7jxyqYuP72sxBGKCIbw7oHgbYssIRzT5FCQ== dependencies: "@types/chai" "*" "@types/chai@*", "@types/chai@^4.3.4": - "integrity" "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==" - "resolved" "https://registry.npmjs.org/@types/chai/-/chai-4.3.4.tgz" - "version" "4.3.4" + version "4.3.4" + resolved "https://registry.npmjs.org/@types/chai/-/chai-4.3.4.tgz" + integrity sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw== "@types/crypto-js@^4.1.1": - "integrity" "sha512-BG7fQKZ689HIoc5h+6D2Dgq1fABRa0RbBWKBd9SP/MVRVXROflpm5fhwyATX5duFmbStzyzyycPB8qUYKDH3NA==" - "resolved" "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.1.1.tgz" - "version" "4.1.1" + version "4.1.1" + resolved "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.1.1.tgz" + integrity sha512-BG7fQKZ689HIoc5h+6D2Dgq1fABRa0RbBWKBd9SP/MVRVXROflpm5fhwyATX5duFmbStzyzyycPB8qUYKDH3NA== "@types/mocha@^10.0.1": - "integrity" "sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q==" - "resolved" "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.1.tgz" - "version" "10.0.1" + version "10.0.1" + resolved "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.1.tgz" + integrity sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q== "@types/mocha@^5.2.0": - "integrity" "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==" - "resolved" "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz" - "version" "5.2.7" - -"@types/node@*": - "integrity" "sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ==" - "resolved" "https://registry.npmjs.org/@types/node/-/node-20.2.5.tgz" - "version" "20.2.5" - -"acorn-walk@^8.1.1": - "integrity" "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==" - "resolved" "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz" - "version" "8.2.0" - -"acorn@^8.4.1": - "integrity" "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==" - "resolved" "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz" - "version" "8.8.2" - -"aes-js@3.0.0": - "integrity" "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==" - "resolved" "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz" - "version" "3.0.0" - -"ansi-colors@4.1.1": - "integrity" "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==" - "resolved" "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz" - "version" "4.1.1" - -"ansi-regex@^2.0.0": - "integrity" "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" - "resolved" "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz" - "version" "2.1.1" - -"ansi-regex@^3.0.0": - "integrity" "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==" - "resolved" "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz" - "version" "3.0.1" - -"ansi-regex@^5.0.1": - "integrity" "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - "resolved" "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" - "version" "5.0.1" - -"ansi-styles@^3.2.1": - "integrity" "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==" - "resolved" "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" - "version" "3.2.1" - dependencies: - "color-convert" "^1.9.0" - -"ansi-styles@^4.0.0", "ansi-styles@^4.1.0": - "integrity" "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==" - "resolved" "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" - "version" "4.3.0" - dependencies: - "color-convert" "^2.0.1" - -"anymatch@~3.1.2": - "integrity" "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==" - "resolved" "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz" - "version" "3.1.3" - dependencies: - "normalize-path" "^3.0.0" - "picomatch" "^2.0.4" - -"arg@^4.1.0": - "integrity" "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" - "resolved" "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz" - "version" "4.1.3" - -"argparse@^2.0.1": - "integrity" "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - "resolved" "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" - "version" "2.0.1" - -"asn1.js@^5.0.0": - "integrity" "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==" - "resolved" "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz" - "version" "5.4.1" - dependencies: - "bn.js" "^4.0.0" - "inherits" "^2.0.1" - "minimalistic-assert" "^1.0.0" - "safer-buffer" "^2.1.0" - -"assertion-error@^1.1.0": - "integrity" "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==" - "resolved" "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz" - "version" "1.1.0" - -"balanced-match@^1.0.0": - "integrity" "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - "resolved" "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" - "version" "1.0.2" - -"base64-js@^1.3.1": - "integrity" "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" - "resolved" "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" - "version" "1.5.1" - -"bech32@1.1.4": - "integrity" "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" - "resolved" "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz" - "version" "1.1.4" - -"binary-extensions@^2.0.0": - "integrity" "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" - "resolved" "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz" - "version" "2.2.0" - -"bn.js@^4.0.0", "bn.js@^4.11.8", "bn.js@^4.11.9": - "integrity" "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - "resolved" "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz" - "version" "4.12.0" - -"bn.js@^5.2.1": - "integrity" "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" - "resolved" "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz" - "version" "5.2.1" - -"brace-expansion@^1.1.7": - "integrity" "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==" - "resolved" "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" - "version" "1.1.11" - dependencies: - "balanced-match" "^1.0.0" - "concat-map" "0.0.1" - -"brace-expansion@^2.0.1": - "integrity" "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==" - "resolved" "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz" - "version" "2.0.1" - dependencies: - "balanced-match" "^1.0.0" - -"braces@~3.0.2": - "integrity" "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==" - "resolved" "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" - "version" "3.0.2" - dependencies: - "fill-range" "^7.0.1" - -"brorand@^1.1.0": - "integrity" "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" - "resolved" "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz" - "version" "1.1.0" - -"browser-stdout@1.3.1": - "integrity" "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" - "resolved" "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz" - "version" "1.3.1" - -"buffer@^6.0.3": - "integrity" "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==" - "resolved" "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz" - "version" "6.0.3" - dependencies: - "base64-js" "^1.3.1" - "ieee754" "^1.2.1" - -"camelcase@^4.1.0": - "integrity" "sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw==" - "resolved" "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz" - "version" "4.1.0" - -"camelcase@^6.0.0": - "integrity" "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==" - "resolved" "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" - "version" "6.3.0" - -"case@^1.6.3": - "integrity" "sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ==" - "resolved" "https://registry.npmjs.org/case/-/case-1.6.3.tgz" - "version" "1.6.3" - -"chai-as-promised@^7.1.1": - "integrity" "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==" - "resolved" "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz" - "version" "7.1.1" - dependencies: - "check-error" "^1.0.2" - -"chai@^4.3.7", "chai@>= 2.1.2 < 5": - "integrity" "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==" - "resolved" "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz" - "version" "4.3.7" - dependencies: - "assertion-error" "^1.1.0" - "check-error" "^1.0.2" - "deep-eql" "^4.1.2" - "get-func-name" "^2.0.0" - "loupe" "^2.3.1" - "pathval" "^1.1.1" - "type-detect" "^4.0.5" - -"chalk@^2.4.1": - "integrity" "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==" - "resolved" "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" - "version" "2.4.2" - dependencies: - "ansi-styles" "^3.2.1" - "escape-string-regexp" "^1.0.5" - "supports-color" "^5.3.0" - -"chalk@^4.1.0": - "integrity" "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==" - "resolved" "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" - "version" "4.1.2" - dependencies: - "ansi-styles" "^4.1.0" - "supports-color" "^7.1.0" - -"check-error@^1.0.2": - "integrity" "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==" - "resolved" "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz" - "version" "1.0.2" - -"chokidar@3.5.3": - "integrity" "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==" - "resolved" "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz" - "version" "3.5.3" - dependencies: - "anymatch" "~3.1.2" - "braces" "~3.0.2" - "glob-parent" "~5.1.2" - "is-binary-path" "~2.1.0" - "is-glob" "~4.0.1" - "normalize-path" "~3.0.0" - "readdirp" "~3.6.0" + version "5.2.7" + resolved "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz" + integrity sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ== + +acorn-walk@^8.1.1: + version "8.2.0" + resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + +acorn@^8.4.1: + version "8.8.2" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz" + integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== + +ansi-colors@4.1.1: + version "4.1.1" + resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz" + integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== + +ansi-regex@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz" + integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +asn1.js@^5.0.0: + version "5.4.1" + resolved "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz" + integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + safer-buffer "^2.1.0" + +assertion-error@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +bn.js@^4.0.0, bn.js@^4.11.8: + version "4.12.0" + resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@~3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +buffer-from@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +buffer@^6.0.3: + version "6.0.3" + resolved "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + +camelcase@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz" + integrity sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw== + +camelcase@^6.0.0: + version "6.3.0" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +case@^1.6.3: + version "1.6.3" + resolved "https://registry.npmjs.org/case/-/case-1.6.3.tgz" + integrity sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ== + +chai-as-promised@^7.1.1: + version "7.1.1" + resolved "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz" + integrity sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA== + dependencies: + check-error "^1.0.2" + +chai@^4.3.7: + version "4.3.7" + resolved "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz" + integrity sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.2" + deep-eql "^4.1.2" + get-func-name "^2.0.0" + loupe "^2.3.1" + pathval "^1.1.1" + type-detect "^4.0.5" + +chalk@^2.4.1: + version "2.4.2" + resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +check-error@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz" + integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA== + +chokidar@3.5.3: + version "3.5.3" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" optionalDependencies: - "fsevents" "~2.3.2" - -"cliui@^4.0.0": - "integrity" "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==" - "resolved" "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz" - "version" "4.1.0" - dependencies: - "string-width" "^2.1.1" - "strip-ansi" "^4.0.0" - "wrap-ansi" "^2.0.0" - -"cliui@^7.0.2": - "integrity" "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==" - "resolved" "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz" - "version" "7.0.4" - dependencies: - "string-width" "^4.2.0" - "strip-ansi" "^6.0.0" - "wrap-ansi" "^7.0.0" - -"code-point-at@^1.0.0": - "integrity" "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" - "resolved" "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz" - "version" "1.1.0" - -"color-convert@^1.9.0": - "integrity" "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==" - "resolved" "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" - "version" "1.9.3" - dependencies: - "color-name" "1.1.3" - -"color-convert@^2.0.1": - "integrity" "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==" - "resolved" "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" - "version" "2.0.1" - dependencies: - "color-name" "~1.1.4" - -"color-name@~1.1.4": - "integrity" "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - "resolved" "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" - "version" "1.1.4" - -"color-name@1.1.3": - "integrity" "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - "resolved" "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" - "version" "1.1.3" - -"concat-map@0.0.1": - "integrity" "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - "resolved" "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" - "version" "0.0.1" - -"create-require@^1.1.0": - "integrity" "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" - "resolved" "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz" - "version" "1.1.1" - -"cross-spawn@^6.0.0", "cross-spawn@^6.0.5": - "integrity" "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==" - "resolved" "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz" - "version" "6.0.5" - dependencies: - "nice-try" "^1.0.4" - "path-key" "^2.0.1" - "semver" "^5.5.0" - "shebang-command" "^1.2.0" - "which" "^1.2.9" - -"crypto-js@^4.1.1": - "integrity" "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" - "resolved" "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz" - "version" "4.1.1" - -"debug@^4.3.2", "debug@4.3.4": - "integrity" "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==" - "resolved" "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" - "version" "4.3.4" - dependencies: - "ms" "2.1.2" - -"decamelize@^1.1.1": - "integrity" "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==" - "resolved" "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz" - "version" "1.2.0" - -"decamelize@^4.0.0": - "integrity" "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==" - "resolved" "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz" - "version" "4.0.0" - -"deep-eql@^4.1.2": - "integrity" "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==" - "resolved" "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz" - "version" "4.1.3" - dependencies: - "type-detect" "^4.0.0" - -"diff@^4.0.1": - "integrity" "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" - "resolved" "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" - "version" "4.0.2" - -"diff@5.0.0": - "integrity" "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==" - "resolved" "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz" - "version" "5.0.0" - -"elliptic@6.5.4": - "integrity" "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==" - "resolved" "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz" - "version" "6.5.4" - dependencies: - "bn.js" "^4.11.9" - "brorand" "^1.1.0" - "hash.js" "^1.0.0" - "hmac-drbg" "^1.0.1" - "inherits" "^2.0.4" - "minimalistic-assert" "^1.0.1" - "minimalistic-crypto-utils" "^1.0.1" - -"emoji-regex@^8.0.0": - "integrity" "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - "resolved" "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" - "version" "8.0.0" - -"end-of-stream@^1.1.0": - "integrity" "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==" - "resolved" "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz" - "version" "1.4.4" - dependencies: - "once" "^1.4.0" - -"err-code@^3.0.1": - "integrity" "sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==" - "resolved" "https://registry.npmjs.org/err-code/-/err-code-3.0.1.tgz" - "version" "3.0.1" - -"escalade@^3.1.1": - "integrity" "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" - "resolved" "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" - "version" "3.1.1" - -"escape-string-regexp@^1.0.5": - "integrity" "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" - "resolved" "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" - "version" "1.0.5" - -"escape-string-regexp@4.0.0": - "integrity" "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" - "resolved" "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" - "version" "4.0.0" - -"ethereum-cryptography@^1.1.2": - "integrity" "sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==" - "resolved" "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz" - "version" "1.2.0" + fsevents "~2.3.2" + +cliui@^4.0.0: + version "4.1.0" + resolved "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz" + integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ== + dependencies: + string-width "^2.1.1" + strip-ansi "^4.0.0" + wrap-ansi "^2.0.0" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz" + integrity sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA== + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +combine-errors@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/combine-errors/-/combine-errors-3.0.3.tgz#f4df6740083e5703a3181110c2b10551f003da86" + integrity sha512-C8ikRNRMygCwaTx+Ek3Yr+OuZzgZjduCOfSQBjbM8V3MfgcjSTeto/GXP6PAwKvJz/v15b7GHZvx5rOlczFw/Q== + dependencies: + custom-error-instance "2.1.1" + lodash.uniqby "4.5.0" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +core-js@^3.27.2: + version "3.31.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.31.0.tgz#4471dd33e366c79d8c0977ed2d940821719db344" + integrity sha512-NIp2TQSGfR6ba5aalZD+ZQ1fSxGhDo/s1w0nx3RYzf2pnJxt7YynxFlFScP6eV7+GZsKO95NSjGxyJsU3DZgeQ== + +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +cross-fetch@^3.1.5: + version "3.1.8" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82" + integrity sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg== + dependencies: + node-fetch "^2.6.12" + +cross-spawn@^6.0.0, cross-spawn@^6.0.5: + version "6.0.5" + resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + +crypto-js@^4.1.1: + version "4.1.1" + resolved "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz" + integrity sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw== + +custom-error-instance@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/custom-error-instance/-/custom-error-instance-2.1.1.tgz#3cf6391487a6629a6247eb0ca0ce00081b7e361a" + integrity sha512-p6JFxJc3M4OTD2li2qaHkDCw9SfMw82Ldr6OC9Je1aXiGfhx2W8p3GaoeaGrPJTUN9NirTM/KTxHWMUdR1rsUg== + +debug@4.3.4, debug@^4.3.2: + version "4.3.4" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +decamelize@^1.1.1: + version "1.2.0" + resolved "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz" + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== + +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + +deep-eql@^4.1.2: + version "4.1.3" + resolved "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz" + integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== + dependencies: + type-detect "^4.0.0" + +diff@5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz" + integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +err-code@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/err-code/-/err-code-3.0.1.tgz" + integrity sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA== + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-string-regexp@4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +ethereum-cryptography@^1.1.2: + version "1.2.0" + resolved "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz" + integrity sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw== dependencies: "@noble/hashes" "1.2.0" "@noble/secp256k1" "1.7.1" "@scure/bip32" "1.1.5" "@scure/bip39" "1.1.1" -"ethers@^5.6.8": - "integrity" "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==" - "resolved" "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz" - "version" "5.7.2" - dependencies: - "@ethersproject/abi" "5.7.0" - "@ethersproject/abstract-provider" "5.7.0" - "@ethersproject/abstract-signer" "5.7.0" - "@ethersproject/address" "5.7.0" - "@ethersproject/base64" "5.7.0" - "@ethersproject/basex" "5.7.0" - "@ethersproject/bignumber" "5.7.0" - "@ethersproject/bytes" "5.7.0" - "@ethersproject/constants" "5.7.0" - "@ethersproject/contracts" "5.7.0" - "@ethersproject/hash" "5.7.0" - "@ethersproject/hdnode" "5.7.0" - "@ethersproject/json-wallets" "5.7.0" - "@ethersproject/keccak256" "5.7.0" - "@ethersproject/logger" "5.7.0" - "@ethersproject/networks" "5.7.1" - "@ethersproject/pbkdf2" "5.7.0" - "@ethersproject/properties" "5.7.0" - "@ethersproject/providers" "5.7.2" - "@ethersproject/random" "5.7.0" - "@ethersproject/rlp" "5.7.0" - "@ethersproject/sha2" "5.7.0" - "@ethersproject/signing-key" "5.7.0" - "@ethersproject/solidity" "5.7.0" - "@ethersproject/strings" "5.7.0" - "@ethersproject/transactions" "5.7.0" - "@ethersproject/units" "5.7.0" - "@ethersproject/wallet" "5.7.0" - "@ethersproject/web" "5.7.1" - "@ethersproject/wordlists" "5.7.0" - -"ethjs-util@^0.1.6": - "integrity" "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==" - "resolved" "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz" - "version" "0.1.6" - dependencies: - "is-hex-prefixed" "1.0.0" - "strip-hex-prefix" "1.0.0" - -"execa@^1.0.0": - "integrity" "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==" - "resolved" "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz" - "version" "1.0.0" - dependencies: - "cross-spawn" "^6.0.0" - "get-stream" "^4.0.0" - "is-stream" "^1.1.0" - "npm-run-path" "^2.0.0" - "p-finally" "^1.0.0" - "signal-exit" "^3.0.0" - "strip-eof" "^1.0.0" - -"fill-range@^7.0.1": - "integrity" "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==" - "resolved" "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" - "version" "7.0.1" - dependencies: - "to-regex-range" "^5.0.1" - -"find-up@^2.1.0": - "integrity" "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==" - "resolved" "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz" - "version" "2.1.0" - dependencies: - "locate-path" "^2.0.0" - -"find-up@5.0.0": - "integrity" "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==" - "resolved" "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" - "version" "5.0.0" - dependencies: - "locate-path" "^6.0.0" - "path-exists" "^4.0.0" - -"flat@^5.0.2": - "integrity" "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==" - "resolved" "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz" - "version" "5.0.2" - -"fs.realpath@^1.0.0": - "integrity" "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - "resolved" "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" - "version" "1.0.0" - -"fsevents@~2.3.2": - "integrity" "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==" - "resolved" "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz" - "version" "2.3.2" - -"get-browser-rtc@^1.1.0": - "integrity" "sha512-MghbMJ61EJrRsDe7w1Bvqt3ZsBuqhce5nrn/XAwgwOXhcsz53/ltdxOse1h/8eKXj5slzxdsz56g5rzOFSGwfQ==" - "resolved" "https://registry.npmjs.org/get-browser-rtc/-/get-browser-rtc-1.1.0.tgz" - "version" "1.1.0" - -"get-caller-file@^1.0.1": - "integrity" "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" - "resolved" "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz" - "version" "1.0.3" - -"get-caller-file@^2.0.5": - "integrity" "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" - "resolved" "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" - "version" "2.0.5" - -"get-func-name@^2.0.0": - "integrity" "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==" - "resolved" "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz" - "version" "2.0.0" - -"get-stream@^4.0.0": - "integrity" "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==" - "resolved" "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz" - "version" "4.1.0" - dependencies: - "pump" "^3.0.0" - -"glob-parent@~5.1.2": - "integrity" "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==" - "resolved" "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" - "version" "5.1.2" - dependencies: - "is-glob" "^4.0.1" - -"glob@7.2.0": - "integrity" "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==" - "resolved" "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz" - "version" "7.2.0" - dependencies: - "fs.realpath" "^1.0.0" - "inflight" "^1.0.4" - "inherits" "2" - "minimatch" "^3.0.4" - "once" "^1.3.0" - "path-is-absolute" "^1.0.0" - -"has-flag@^3.0.0": - "integrity" "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" - "resolved" "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" - "version" "3.0.0" - -"has-flag@^4.0.0": - "integrity" "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - "resolved" "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" - "version" "4.0.0" - -"hash.js@^1.0.0", "hash.js@^1.0.3", "hash.js@1.1.7": - "integrity" "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==" - "resolved" "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz" - "version" "1.1.7" - dependencies: - "inherits" "^2.0.3" - "minimalistic-assert" "^1.0.1" - -"he@1.2.0": - "integrity" "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" - "resolved" "https://registry.npmjs.org/he/-/he-1.2.0.tgz" - "version" "1.2.0" - -"hmac-drbg@^1.0.1": - "integrity" "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==" - "resolved" "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz" - "version" "1.0.1" - dependencies: - "hash.js" "^1.0.3" - "minimalistic-assert" "^1.0.0" - "minimalistic-crypto-utils" "^1.0.1" - -"ieee754@^1.2.1": - "integrity" "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" - "resolved" "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz" - "version" "1.2.1" - -"immer@^10.0.2": - "integrity" "sha512-Rx3CqeqQ19sxUtYV9CU911Vhy8/721wRFnJv3REVGWUmoAcIwzifTsdmJte/MV+0/XpM35LZdQMBGkRIoLPwQA==" - "resolved" "https://registry.npmjs.org/immer/-/immer-10.0.2.tgz" - "version" "10.0.2" - -"inflight@^1.0.4": - "integrity" "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==" - "resolved" "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" - "version" "1.0.6" - dependencies: - "once" "^1.3.0" - "wrappy" "1" - -"inherits@^2.0.1", "inherits@^2.0.3", "inherits@^2.0.4", "inherits@2": - "integrity" "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - "resolved" "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" - "version" "2.0.4" - -"invert-kv@^2.0.0": - "integrity" "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==" - "resolved" "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz" - "version" "2.0.0" - -"is-binary-path@~2.1.0": - "integrity" "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==" - "resolved" "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" - "version" "2.1.0" - dependencies: - "binary-extensions" "^2.0.0" - -"is-extglob@^2.1.1": - "integrity" "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" - "resolved" "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" - "version" "2.1.1" - -"is-fullwidth-code-point@^1.0.0": - "integrity" "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==" - "resolved" "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz" - "version" "1.0.0" - dependencies: - "number-is-nan" "^1.0.0" - -"is-fullwidth-code-point@^2.0.0": - "integrity" "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==" - "resolved" "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz" - "version" "2.0.0" - -"is-fullwidth-code-point@^3.0.0": - "integrity" "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - "resolved" "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" - "version" "3.0.0" - -"is-glob@^4.0.1", "is-glob@~4.0.1": - "integrity" "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==" - "resolved" "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" - "version" "4.0.3" - dependencies: - "is-extglob" "^2.1.1" - -"is-hex-prefixed@1.0.0": - "integrity" "sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA==" - "resolved" "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz" - "version" "1.0.0" - -"is-number@^7.0.0": - "integrity" "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - "resolved" "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" - "version" "7.0.0" - -"is-plain-obj@^2.1.0": - "integrity" "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==" - "resolved" "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz" - "version" "2.1.0" - -"is-stream@^1.1.0": - "integrity" "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==" - "resolved" "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz" - "version" "1.1.0" - -"is-unicode-supported@^0.1.0": - "integrity" "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==" - "resolved" "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz" - "version" "0.1.0" - -"isexe@^2.0.0": - "integrity" "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - "resolved" "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" - "version" "2.0.0" - -"js-sha3@0.8.0": - "integrity" "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" - "resolved" "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz" - "version" "0.8.0" - -"js-yaml@4.1.0": - "integrity" "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==" - "resolved" "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" - "version" "4.1.0" - dependencies: - "argparse" "^2.0.1" - -"lcid@^2.0.0": - "integrity" "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==" - "resolved" "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz" - "version" "2.0.0" - dependencies: - "invert-kv" "^2.0.0" - -"locate-path@^2.0.0": - "integrity" "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==" - "resolved" "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz" - "version" "2.0.0" - dependencies: - "p-locate" "^2.0.0" - "path-exists" "^3.0.0" - -"locate-path@^6.0.0": - "integrity" "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==" - "resolved" "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" - "version" "6.0.0" - dependencies: - "p-locate" "^5.0.0" - -"log-symbols@4.1.0": - "integrity" "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==" - "resolved" "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz" - "version" "4.1.0" - dependencies: - "chalk" "^4.1.0" - "is-unicode-supported" "^0.1.0" - -"loupe@^2.3.1": - "integrity" "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==" - "resolved" "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz" - "version" "2.3.6" - dependencies: - "get-func-name" "^2.0.0" - -"make-error@^1.1.1": - "integrity" "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" - "resolved" "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz" - "version" "1.3.6" - -"map-age-cleaner@^0.1.1": - "integrity" "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==" - "resolved" "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz" - "version" "0.1.3" - dependencies: - "p-defer" "^1.0.0" - -"mem@^4.0.0": - "integrity" "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==" - "resolved" "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz" - "version" "4.3.0" +ethjs-util@^0.1.6: + version "0.1.6" + resolved "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz" + integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== + dependencies: + is-hex-prefixed "1.0.0" + strip-hex-prefix "1.0.0" + +events@3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +execa@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz" + integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== + dependencies: + cross-spawn "^6.0.0" + get-stream "^4.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +find-up@5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz" + integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== + dependencies: + locate-path "^2.0.0" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +get-browser-rtc@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/get-browser-rtc/-/get-browser-rtc-1.1.0.tgz" + integrity sha512-MghbMJ61EJrRsDe7w1Bvqt3ZsBuqhce5nrn/XAwgwOXhcsz53/ltdxOse1h/8eKXj5slzxdsz56g5rzOFSGwfQ== + +get-caller-file@^1.0.1: + version "1.0.3" + resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz" + integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-func-name@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz" + integrity sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig== + +get-stream@^4.0.0: + version "4.1.0" + resolved "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + +glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob@7.2.0: + version "7.2.0" + resolved "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +graceful-fs@^4.2.4: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +he@1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/he/-/he-1.2.0.tgz" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +hls.js@^1.4.0: + version "1.4.8" + resolved "https://registry.yarnpkg.com/hls.js/-/hls.js-1.4.8.tgz#6fedcb5224d7361e4f38046ffd45286d8a645df8" + integrity sha512-wYL7W49M6oKv0+P4RW50YkJaxDzgnHMMrN+YoLpow07hVgaedAdX9HfKkehTb04UEfeJhNSef5ucICYPsHOfqg== + +ieee754@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +immer@^10.0.2: + version "10.0.2" + resolved "https://registry.npmjs.org/immer/-/immer-10.0.2.tgz" + integrity sha512-Rx3CqeqQ19sxUtYV9CU911Vhy8/721wRFnJv3REVGWUmoAcIwzifTsdmJte/MV+0/XpM35LZdQMBGkRIoLPwQA== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.1, inherits@^2.0.3: + version "2.0.4" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +invert-kv@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz" + integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz" + integrity sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw== + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz" + integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-hex-prefixed@1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz" + integrity sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA== + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz" + integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ== + +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +js-base64@^3.7.2: + version "3.7.5" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-3.7.5.tgz#21e24cf6b886f76d6f5f165bfcd69cc55b9e3fca" + integrity sha512-3MEt5DTINKqfScXKfJFrRbxkrnk2AxPWGBL/ycjz4dK8iqiSJ06UxD8jh8xuh6p10TX4t2+7FsBYVxxQbMg+qA== + +js-yaml@4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +lcid@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz" + integrity sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA== + dependencies: + invert-kv "^2.0.0" + +livepeer@^2.5.8: + version "2.5.8" + resolved "https://registry.yarnpkg.com/livepeer/-/livepeer-2.5.8.tgz#afce72633bb1036d1fe3c837ad997a5dce957b54" + integrity sha512-V+VZVXjEo47A0hxUAB6HLGSBjEvksBXJyFTatkYqarfU6T8gMk+37RugEOsZn6dDj9up4+6A7xWygKoC1zu+ow== + dependencies: + "@livepeer/core" "^1.5.8" + "@stitches/core" "^1.2.8" + core-js "^3.27.2" + cross-fetch "^3.1.5" + hls.js "^1.4.0" + ms "^3.0.0-canary.1" + multiformats "9.9.0" + tus-js-client "^3.0.1" + zustand "^4.3.2" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz" + integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA== + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash._baseiteratee@~4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/lodash._baseiteratee/-/lodash._baseiteratee-4.7.0.tgz#34a9b5543572727c3db2e78edae3c0e9e66bd102" + integrity sha512-nqB9M+wITz0BX/Q2xg6fQ8mLkyfF7MU7eE+MNBNjTHFKeKaZAPEzEg+E8LWxKWf1DQVflNEn9N49yAuqKh2mWQ== + dependencies: + lodash._stringtopath "~4.8.0" + +lodash._basetostring@~4.12.0: + version "4.12.0" + resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-4.12.0.tgz#9327c9dc5158866b7fa4b9d42f4638e5766dd9df" + integrity sha512-SwcRIbyxnN6CFEEK4K1y+zuApvWdpQdBHM/swxP962s8HIxPO3alBH5t3m/dl+f4CMUug6sJb7Pww8d13/9WSw== + +lodash._baseuniq@~4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8" + integrity sha512-Ja1YevpHZctlI5beLA7oc5KNDhGcPixFhcqSiORHNsp/1QTv7amAXzw+gu4YOvErqVlMVyIJGgtzeepCnnur0A== + dependencies: + lodash._createset "~4.0.0" + lodash._root "~3.0.0" + +lodash._createset@~4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26" + integrity sha512-GTkC6YMprrJZCYU3zcqZj+jkXkrXzq3IPBcF/fIPpNEAB4hZEtXU8zp/RwKOvZl43NUmwDbyRk3+ZTbeRdEBXA== + +lodash._root@~3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" + integrity sha512-O0pWuFSK6x4EXhM1dhZ8gchNtG7JMqBtrHdoUFUWXD7dJnNSUze1GuyQr5sOs0aCvgGeI3o/OJW8f4ca7FDxmQ== + +lodash._stringtopath@~4.8.0: + version "4.8.0" + resolved "https://registry.yarnpkg.com/lodash._stringtopath/-/lodash._stringtopath-4.8.0.tgz#941bcf0e64266e5fc1d66fed0a6959544c576824" + integrity sha512-SXL66C731p0xPDC5LZg4wI5H+dJo/EO4KTqOMwLYCH3+FmmfAKJEZCm6ohGpI+T1xwsDsJCfL4OnhorllvlTPQ== + dependencies: + lodash._basetostring "~4.12.0" + +lodash.throttle@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" + integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ== + +lodash.uniqby@4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.uniqby/-/lodash.uniqby-4.5.0.tgz#a3a17bbf62eeb6240f491846e97c1c4e2a5e1e21" + integrity sha512-IRt7cfTtHy6f1aRVA5n7kT8rgN3N1nH6MOWLcHfpWG2SH19E3JksLK38MktLxZDhlAjCP9jpIXkOnRXlu6oByQ== + dependencies: + lodash._baseiteratee "~4.7.0" + lodash._baseuniq "~4.6.0" + +log-symbols@4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +loupe@^2.3.1: + version "2.3.6" + resolved "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz" + integrity sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA== + dependencies: + get-func-name "^2.0.0" + +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +map-age-cleaner@^0.1.1: + version "0.1.3" + resolved "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz" + integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== + dependencies: + p-defer "^1.0.0" + +mem@^4.0.0: + version "4.3.0" + resolved "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz" + integrity sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w== dependencies: - "map-age-cleaner" "^0.1.1" - "mimic-fn" "^2.0.0" - "p-is-promise" "^2.0.0" + map-age-cleaner "^0.1.1" + mimic-fn "^2.0.0" + p-is-promise "^2.0.0" -"mimic-fn@^2.0.0": - "integrity" "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" - "resolved" "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" - "version" "2.1.0" +mimic-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -"minimalistic-assert@^1.0.0", "minimalistic-assert@^1.0.1": - "integrity" "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" - "resolved" "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz" - "version" "1.0.1" +minimalistic-assert@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== -"minimalistic-crypto-utils@^1.0.1": - "integrity" "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" - "resolved" "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz" - "version" "1.0.1" - -"minimatch@^3.0.4": - "integrity" "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==" - "resolved" "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" - "version" "3.1.2" +minimatch@5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz" + integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== dependencies: - "brace-expansion" "^1.1.7" + brace-expansion "^2.0.1" -"minimatch@5.0.1": - "integrity" "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==" - "resolved" "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz" - "version" "5.0.1" - dependencies: - "brace-expansion" "^2.0.1" +minimatch@^3.0.4: + version "3.1.2" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" -"mocha-typescript@^1.1.17": - "integrity" "sha512-Ge6pCQkZumkkhxVNdAf3JxunskShgaynCb30HYD7TT1Yhog/7NW2+6w5RcRHI+nuQrCMTX6z1+qf2pD8qwCoQA==" - "resolved" "https://registry.npmjs.org/mocha-typescript/-/mocha-typescript-1.1.17.tgz" - "version" "1.1.17" +mocha-typescript@^1.1.17: + version "1.1.17" + resolved "https://registry.npmjs.org/mocha-typescript/-/mocha-typescript-1.1.17.tgz" + integrity sha512-Ge6pCQkZumkkhxVNdAf3JxunskShgaynCb30HYD7TT1Yhog/7NW2+6w5RcRHI+nuQrCMTX6z1+qf2pD8qwCoQA== dependencies: "@types/mocha" "^5.2.0" - "chalk" "^2.4.1" - "cross-spawn" "^6.0.5" - "yargs" "^11.0.0" - -"mocha@^10.2.0": - "integrity" "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==" - "resolved" "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz" - "version" "10.2.0" - dependencies: - "ansi-colors" "4.1.1" - "browser-stdout" "1.3.1" - "chokidar" "3.5.3" - "debug" "4.3.4" - "diff" "5.0.0" - "escape-string-regexp" "4.0.0" - "find-up" "5.0.0" - "glob" "7.2.0" - "he" "1.2.0" - "js-yaml" "4.1.0" - "log-symbols" "4.1.0" - "minimatch" "5.0.1" - "ms" "2.1.3" - "nanoid" "3.3.3" - "serialize-javascript" "6.0.0" - "strip-json-comments" "3.1.1" - "supports-color" "8.1.1" - "workerpool" "6.2.1" - "yargs" "16.2.0" - "yargs-parser" "20.2.4" - "yargs-unparser" "2.0.0" - -"ms@2.1.2": - "integrity" "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - "resolved" "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" - "version" "2.1.2" - -"ms@2.1.3": - "integrity" "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - "resolved" "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" - "version" "2.1.3" - -"nanoid@3.3.3": - "integrity" "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==" - "resolved" "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz" - "version" "3.3.3" - -"nice-try@^1.0.4": - "integrity" "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" - "resolved" "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz" - "version" "1.0.5" - -"normalize-path@^3.0.0", "normalize-path@~3.0.0": - "integrity" "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" - "resolved" "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" - "version" "3.0.0" - -"npm-run-path@^2.0.0": - "integrity" "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==" - "resolved" "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz" - "version" "2.0.2" - dependencies: - "path-key" "^2.0.0" - -"number-is-nan@^1.0.0": - "integrity" "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" - "resolved" "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz" - "version" "1.0.1" - -"once@^1.3.0", "once@^1.3.1", "once@^1.4.0": - "integrity" "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==" - "resolved" "https://registry.npmjs.org/once/-/once-1.4.0.tgz" - "version" "1.4.0" - dependencies: - "wrappy" "1" - -"openpgp@^5.5.0": - "integrity" "sha512-SpwcJnxrK9Y0HRM6KxSFqkAEOSWEabCH/c8dII/+y2e5f6KvuDG5ZE7JXaPBaVJNE4VUZZeTphxXDoZD0KOHrw==" - "resolved" "https://registry.npmjs.org/openpgp/-/openpgp-5.5.0.tgz" - "version" "5.5.0" - dependencies: - "asn1.js" "^5.0.0" - -"os-locale@^3.1.0": - "integrity" "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==" - "resolved" "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz" - "version" "3.1.0" - dependencies: - "execa" "^1.0.0" - "lcid" "^2.0.0" - "mem" "^4.0.0" - -"p-defer@^1.0.0": - "integrity" "sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==" - "resolved" "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz" - "version" "1.0.0" - -"p-finally@^1.0.0": - "integrity" "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==" - "resolved" "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz" - "version" "1.0.0" - -"p-is-promise@^2.0.0": - "integrity" "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==" - "resolved" "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz" - "version" "2.1.0" - -"p-limit@^1.1.0": - "integrity" "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==" - "resolved" "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz" - "version" "1.3.0" - dependencies: - "p-try" "^1.0.0" - -"p-limit@^3.0.2": - "integrity" "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==" - "resolved" "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" - "version" "3.1.0" - dependencies: - "yocto-queue" "^0.1.0" - -"p-locate@^2.0.0": - "integrity" "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==" - "resolved" "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz" - "version" "2.0.0" - dependencies: - "p-limit" "^1.1.0" - -"p-locate@^5.0.0": - "integrity" "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==" - "resolved" "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz" - "version" "5.0.0" - dependencies: - "p-limit" "^3.0.2" - -"p-try@^1.0.0": - "integrity" "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==" - "resolved" "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz" - "version" "1.0.0" - -"path-exists@^3.0.0": - "integrity" "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==" - "resolved" "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz" - "version" "3.0.0" - -"path-exists@^4.0.0": - "integrity" "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" - "resolved" "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" - "version" "4.0.0" - -"path-is-absolute@^1.0.0": - "integrity" "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" - "resolved" "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" - "version" "1.0.1" - -"path-key@^2.0.0", "path-key@^2.0.1": - "integrity" "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==" - "resolved" "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz" - "version" "2.0.1" - -"pathval@^1.1.1": - "integrity" "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==" - "resolved" "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz" - "version" "1.1.1" - -"picomatch@^2.0.4", "picomatch@^2.2.1": - "integrity" "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" - "resolved" "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" - "version" "2.3.1" - -"pump@^3.0.0": - "integrity" "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==" - "resolved" "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz" - "version" "3.0.0" - dependencies: - "end-of-stream" "^1.1.0" - "once" "^1.3.1" - -"queue-microtask@^1.2.3": - "integrity" "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" - "resolved" "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" - "version" "1.2.3" - -"randombytes@^2.1.0": - "integrity" "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==" - "resolved" "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" - "version" "2.1.0" - dependencies: - "safe-buffer" "^5.1.0" - -"readable-stream@^3.6.0": - "integrity" "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==" - "resolved" "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz" - "version" "3.6.2" - dependencies: - "inherits" "^2.0.3" - "string_decoder" "^1.1.1" - "util-deprecate" "^1.0.1" - -"readdirp@~3.6.0": - "integrity" "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==" - "resolved" "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" - "version" "3.6.0" - dependencies: - "picomatch" "^2.2.1" - -"require-directory@^2.1.1": - "integrity" "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" - "resolved" "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" - "version" "2.1.1" - -"require-main-filename@^1.0.1": - "integrity" "sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug==" - "resolved" "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz" - "version" "1.0.1" - -"safe-buffer@^5.1.0", "safe-buffer@~5.2.0": - "integrity" "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - "resolved" "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" - "version" "5.2.1" - -"safer-buffer@^2.1.0": - "integrity" "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - "resolved" "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" - "version" "2.1.2" - -"scrypt-js@3.0.1": - "integrity" "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==" - "resolved" "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz" - "version" "3.0.1" - -"semver@^5.5.0": - "integrity" "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - "resolved" "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz" - "version" "5.7.1" - -"serialize-javascript@6.0.0": - "integrity" "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==" - "resolved" "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz" - "version" "6.0.0" - dependencies: - "randombytes" "^2.1.0" - -"set-blocking@^2.0.0": - "integrity" "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" - "resolved" "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz" - "version" "2.0.0" - -"shebang-command@^1.2.0": - "integrity" "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==" - "resolved" "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz" - "version" "1.2.0" - dependencies: - "shebang-regex" "^1.0.0" - -"shebang-regex@^1.0.0": - "integrity" "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==" - "resolved" "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz" - "version" "1.0.0" - -"signal-exit@^3.0.0": - "integrity" "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - "resolved" "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" - "version" "3.0.7" - -"simple-peer@^9.11.1": - "integrity" "sha512-D1SaWpOW8afq1CZGWB8xTfrT3FekjQmPValrqncJMX7QFl8YwhrPTZvMCANLtgBwwdS+7zURyqxDDEmY558tTw==" - "resolved" "https://registry.npmjs.org/simple-peer/-/simple-peer-9.11.1.tgz" - "version" "9.11.1" - dependencies: - "buffer" "^6.0.3" - "debug" "^4.3.2" - "err-code" "^3.0.1" - "get-browser-rtc" "^1.1.0" - "queue-microtask" "^1.2.3" - "randombytes" "^2.1.0" - "readable-stream" "^3.6.0" - -"string_decoder@^1.1.1": - "integrity" "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==" - "resolved" "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" - "version" "1.3.0" - dependencies: - "safe-buffer" "~5.2.0" - -"string-width@^1.0.1": - "integrity" "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==" - "resolved" "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz" - "version" "1.0.2" - dependencies: - "code-point-at" "^1.0.0" - "is-fullwidth-code-point" "^1.0.0" - "strip-ansi" "^3.0.0" - -"string-width@^2.0.0", "string-width@^2.1.1": - "integrity" "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==" - "resolved" "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz" - "version" "2.1.1" - dependencies: - "is-fullwidth-code-point" "^2.0.0" - "strip-ansi" "^4.0.0" - -"string-width@^4.1.0", "string-width@^4.2.0": - "integrity" "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==" - "resolved" "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" - "version" "4.2.3" - dependencies: - "emoji-regex" "^8.0.0" - "is-fullwidth-code-point" "^3.0.0" - "strip-ansi" "^6.0.1" - -"strip-ansi@^3.0.0", "strip-ansi@^3.0.1": - "integrity" "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==" - "resolved" "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz" - "version" "3.0.1" - dependencies: - "ansi-regex" "^2.0.0" - -"strip-ansi@^4.0.0": - "integrity" "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==" - "resolved" "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz" - "version" "4.0.0" - dependencies: - "ansi-regex" "^3.0.0" + chalk "^2.4.1" + cross-spawn "^6.0.5" + yargs "^11.0.0" + +mocha@^10.2.0: + version "10.2.0" + resolved "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz" + integrity sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg== + dependencies: + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.5.3" + debug "4.3.4" + diff "5.0.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "7.2.0" + he "1.2.0" + js-yaml "4.1.0" + log-symbols "4.1.0" + minimatch "5.0.1" + ms "2.1.3" + nanoid "3.3.3" + serialize-javascript "6.0.0" + strip-json-comments "3.1.1" + supports-color "8.1.1" + workerpool "6.2.1" + yargs "16.2.0" + yargs-parser "20.2.4" + yargs-unparser "2.0.0" + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3: + version "2.1.3" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +ms@^3.0.0-canary.1: + version "3.0.0-canary.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-3.0.0-canary.1.tgz#c7b34fbce381492fd0b345d1cf56e14d67b77b80" + integrity sha512-kh8ARjh8rMN7Du2igDRO9QJnqCb2xYTJxyQYK7vJJS4TvLLmsbyhiKpSW+t+y26gyOyMd0riphX0GeWKU3ky5g== + +multiformats@9.9.0: + version "9.9.0" + resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-9.9.0.tgz#c68354e7d21037a8f1f8833c8ccd68618e8f1d37" + integrity sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg== + +nanoid@3.3.3: + version "3.3.3" + resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz" + integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== + +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + +node-fetch@^2.6.12: + version "2.6.12" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.12.tgz#02eb8e22074018e3d5a83016649d04df0e348fba" + integrity sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g== + dependencies: + whatwg-url "^5.0.0" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz" + integrity sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw== + dependencies: + path-key "^2.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz" + integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ== + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +openpgp@^5.5.0: + version "5.5.0" + resolved "https://registry.npmjs.org/openpgp/-/openpgp-5.5.0.tgz" + integrity sha512-SpwcJnxrK9Y0HRM6KxSFqkAEOSWEabCH/c8dII/+y2e5f6KvuDG5ZE7JXaPBaVJNE4VUZZeTphxXDoZD0KOHrw== + dependencies: + asn1.js "^5.0.0" + +os-locale@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz" + integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q== + dependencies: + execa "^1.0.0" + lcid "^2.0.0" + mem "^4.0.0" + +p-defer@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz" + integrity sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw== + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz" + integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== + +p-is-promise@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz" + integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg== + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz" + integrity sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg== + dependencies: + p-limit "^1.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz" + integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww== + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz" + integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^2.0.0, path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz" + integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== + +pathval@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== + +picomatch@^2.0.4, picomatch@^2.2.1: + version "2.3.1" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +proper-lockfile@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-4.1.2.tgz#c8b9de2af6b2f1601067f98e01ac66baa223141f" + integrity sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA== + dependencies: + graceful-fs "^4.2.4" + retry "^0.12.0" + signal-exit "^3.0.2" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +querystringify@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" + integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== + +queue-microtask@^1.2.3: + version "1.2.3" + resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +readable-stream@^3.6.0: + version "3.6.2" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz" + integrity sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug== + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + +retry@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== + +safe-buffer@^5.1.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safer-buffer@^2.1.0: + version "2.1.2" + resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +semver@^5.5.0: + version "5.7.1" + resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +serialize-javascript@6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== + dependencies: + randombytes "^2.1.0" + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz" + integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz" + integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== + +signal-exit@^3.0.0, signal-exit@^3.0.2: + version "3.0.7" + resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +simple-peer@^9.11.1: + version "9.11.1" + resolved "https://registry.npmjs.org/simple-peer/-/simple-peer-9.11.1.tgz" + integrity sha512-D1SaWpOW8afq1CZGWB8xTfrT3FekjQmPValrqncJMX7QFl8YwhrPTZvMCANLtgBwwdS+7zURyqxDDEmY558tTw== + dependencies: + buffer "^6.0.3" + debug "^4.3.2" + err-code "^3.0.1" + get-browser-rtc "^1.1.0" + queue-microtask "^1.2.3" + randombytes "^2.1.0" + readable-stream "^3.6.0" + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz" + integrity sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw== + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +string-width@^2.0.0, string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.3" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz" + integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz" + integrity sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow== + dependencies: + ansi-regex "^3.0.0" -"strip-ansi@^6.0.0", "strip-ansi@^6.0.1": - "integrity" "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==" - "resolved" "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" - "version" "6.0.1" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: - "ansi-regex" "^5.0.1" - -"strip-eof@^1.0.0": - "integrity" "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==" - "resolved" "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz" - "version" "1.0.0" + ansi-regex "^5.0.1" + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz" + integrity sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q== -"strip-hex-prefix@1.0.0": - "integrity" "sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==" - "resolved" "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz" - "version" "1.0.0" +strip-hex-prefix@1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz" + integrity sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A== dependencies: - "is-hex-prefixed" "1.0.0" + is-hex-prefixed "1.0.0" + +strip-json-comments@3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -"strip-json-comments@3.1.1": - "integrity" "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" - "resolved" "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" - "version" "3.1.1" - -"supports-color@^5.3.0": - "integrity" "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==" - "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" - "version" "5.5.0" +supports-color@8.1.1: + version "8.1.1" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== dependencies: - "has-flag" "^3.0.0" - -"supports-color@^7.1.0": - "integrity" "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==" - "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" - "version" "7.2.0" + has-flag "^4.0.0" + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: - "has-flag" "^4.0.0" + has-flag "^3.0.0" -"supports-color@8.1.1": - "integrity" "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==" - "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" - "version" "8.1.1" +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== dependencies: - "has-flag" "^4.0.0" + has-flag "^4.0.0" -"to-regex-range@^5.0.1": - "integrity" "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==" - "resolved" "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" - "version" "5.0.1" +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== dependencies: - "is-number" "^7.0.0" + is-number "^7.0.0" + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== -"ts-node@^10.9.1": - "integrity" "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==" - "resolved" "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz" - "version" "10.9.1" +ts-node@^10.9.1: + version "10.9.1" + resolved "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz" + integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== dependencies: "@cspotcode/source-map-support" "^0.8.0" "@tsconfig/node10" "^1.0.7" "@tsconfig/node12" "^1.0.7" "@tsconfig/node14" "^1.0.0" "@tsconfig/node16" "^1.0.2" - "acorn" "^8.4.1" - "acorn-walk" "^8.1.1" - "arg" "^4.1.0" - "create-require" "^1.1.0" - "diff" "^4.0.1" - "make-error" "^1.1.1" - "v8-compile-cache-lib" "^3.0.1" - "yn" "3.1.1" - -"tweetnacl-util@^0.15.1": - "integrity" "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==" - "resolved" "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz" - "version" "0.15.1" - -"tweetnacl@^1.0.3": - "integrity" "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" - "resolved" "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz" - "version" "1.0.3" - -"type-detect@^4.0.0", "type-detect@^4.0.5": - "integrity" "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" - "resolved" "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz" - "version" "4.0.8" - -"typescript@^5.0.2", "typescript@>=2.7": - "integrity" "sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==" - "resolved" "https://registry.npmjs.org/typescript/-/typescript-5.0.2.tgz" - "version" "5.0.2" - -"util-deprecate@^1.0.1": - "integrity" "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - "resolved" "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" - "version" "1.0.2" - -"v8-compile-cache-lib@^3.0.1": - "integrity" "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" - "resolved" "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz" - "version" "3.0.1" - -"which-module@^2.0.0": - "integrity" "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==" - "resolved" "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz" - "version" "2.0.0" - -"which@^1.2.9": - "integrity" "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==" - "resolved" "https://registry.npmjs.org/which/-/which-1.3.1.tgz" - "version" "1.3.1" - dependencies: - "isexe" "^2.0.0" - -"workerpool@6.2.1": - "integrity" "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==" - "resolved" "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz" - "version" "6.2.1" - -"wrap-ansi@^2.0.0": - "integrity" "sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw==" - "resolved" "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz" - "version" "2.1.0" - dependencies: - "string-width" "^1.0.1" - "strip-ansi" "^3.0.1" - -"wrap-ansi@^7.0.0": - "integrity" "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==" - "resolved" "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" - "version" "7.0.0" - dependencies: - "ansi-styles" "^4.0.0" - "string-width" "^4.1.0" - "strip-ansi" "^6.0.0" - -"wrappy@1": - "integrity" "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - "resolved" "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" - "version" "1.0.2" - -"ws@7.4.6": - "integrity" "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==" - "resolved" "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz" - "version" "7.4.6" - -"y18n@^3.2.1": - "integrity" "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==" - "resolved" "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz" - "version" "3.2.2" - -"y18n@^5.0.5": - "integrity" "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" - "resolved" "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" - "version" "5.0.8" - -"yargs-parser@^20.2.2", "yargs-parser@20.2.4": - "integrity" "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==" - "resolved" "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz" - "version" "20.2.4" - -"yargs-parser@^9.0.2": - "integrity" "sha512-CswCfdOgCr4MMsT1GzbEJ7Z2uYudWyrGX8Bgh/0eyCzj/DXWdKq6a/ADufkzI1WAOIW6jYaXJvRyLhDO0kfqBw==" - "resolved" "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz" - "version" "9.0.2" - dependencies: - "camelcase" "^4.1.0" - -"yargs-unparser@2.0.0": - "integrity" "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==" - "resolved" "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz" - "version" "2.0.0" - dependencies: - "camelcase" "^6.0.0" - "decamelize" "^4.0.0" - "flat" "^5.0.2" - "is-plain-obj" "^2.1.0" - -"yargs@^11.0.0": - "integrity" "sha512-PRU7gJrJaXv3q3yQZ/+/X6KBswZiaQ+zOmdprZcouPYtQgvNU35i+68M4b1ZHLZtYFT5QObFLV+ZkmJYcwKdiw==" - "resolved" "https://registry.npmjs.org/yargs/-/yargs-11.1.1.tgz" - "version" "11.1.1" - dependencies: - "cliui" "^4.0.0" - "decamelize" "^1.1.1" - "find-up" "^2.1.0" - "get-caller-file" "^1.0.1" - "os-locale" "^3.1.0" - "require-directory" "^2.1.1" - "require-main-filename" "^1.0.1" - "set-blocking" "^2.0.0" - "string-width" "^2.0.0" - "which-module" "^2.0.0" - "y18n" "^3.2.1" - "yargs-parser" "^9.0.2" - -"yargs@16.2.0": - "integrity" "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==" - "resolved" "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz" - "version" "16.2.0" - dependencies: - "cliui" "^7.0.2" - "escalade" "^3.1.1" - "get-caller-file" "^2.0.5" - "require-directory" "^2.1.1" - "string-width" "^4.2.0" - "y18n" "^5.0.5" - "yargs-parser" "^20.2.2" - -"yn@3.1.1": - "integrity" "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==" - "resolved" "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz" - "version" "3.1.1" - -"yocto-queue@^0.1.0": - "integrity" "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" - "resolved" "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" - "version" "0.1.0" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + +tus-js-client@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/tus-js-client/-/tus-js-client-3.1.0.tgz#20af57d06c23823fbe108ccb3a3dcb7503968cb4" + integrity sha512-Hfpc8ho4C9Lhs/OflPUA/nHUHZJUrKD5upoPBq7dYJJ9DQhWocsjJU2RZYfN16Y5n19j9dFDszwCvVZ5sfcogw== + dependencies: + buffer-from "^1.1.2" + combine-errors "^3.0.3" + is-stream "^2.0.0" + js-base64 "^3.7.2" + lodash.throttle "^4.1.1" + proper-lockfile "^4.1.2" + url-parse "^1.5.7" + +tweetnacl-util@^0.15.1: + version "0.15.1" + resolved "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz" + integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw== + +tweetnacl@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz" + integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== + +type-detect@^4.0.0, type-detect@^4.0.5: + version "4.0.8" + resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +typescript@^5.0.2: + version "5.0.2" + resolved "https://registry.npmjs.org/typescript/-/typescript-5.0.2.tgz" + integrity sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw== + +url-parse@^1.5.7: + version "1.5.10" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" + integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== + dependencies: + querystringify "^2.1.1" + requires-port "^1.0.0" + +use-sync-external-store@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" + integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== + +util-deprecate@^1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + +video-stream-merger@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/video-stream-merger/-/video-stream-merger-4.0.1.tgz#b0061251bd211121d1256ccf9e2be9477e59d5cb" + integrity sha512-VazYSr8tk6S/zkOq5jpR/ryy1HnGxm5XCw+d2Ejpqy1m6d71oZpyFG82dUkgAo7dg/lk3k4TqvJPtuRUtR8URA== + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz" + integrity sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q== + +which@^1.2.9: + version "1.3.1" + resolved "https://registry.npmjs.org/which/-/which-1.3.1.tgz" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +workerpool@6.2.1: + version "6.2.1" + resolved "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz" + integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== + +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz" + integrity sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw== + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +y18n@^3.2.1: + version "3.2.2" + resolved "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz" + integrity sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yargs-parser@20.2.4, yargs-parser@^20.2.2: + version "20.2.4" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + +yargs-parser@^9.0.2: + version "9.0.2" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz" + integrity sha512-CswCfdOgCr4MMsT1GzbEJ7Z2uYudWyrGX8Bgh/0eyCzj/DXWdKq6a/ADufkzI1WAOIW6jYaXJvRyLhDO0kfqBw== + dependencies: + camelcase "^4.1.0" + +yargs-unparser@2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@16.2.0: + version "16.2.0" + resolved "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yargs@^11.0.0: + version "11.1.1" + resolved "https://registry.npmjs.org/yargs/-/yargs-11.1.1.tgz" + integrity sha512-PRU7gJrJaXv3q3yQZ/+/X6KBswZiaQ+zOmdprZcouPYtQgvNU35i+68M4b1ZHLZtYFT5QObFLV+ZkmJYcwKdiw== + dependencies: + cliui "^4.0.0" + decamelize "^1.1.1" + find-up "^2.1.0" + get-caller-file "^1.0.1" + os-locale "^3.1.0" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^2.0.0" + which-module "^2.0.0" + y18n "^3.2.1" + yargs-parser "^9.0.2" + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zustand@^4.3.2: + version "4.3.9" + resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.3.9.tgz#a7d4332bbd75dfd25c6848180b3df1407217f2ad" + integrity sha512-Tat5r8jOMG1Vcsj8uldMyqYKC5IZvQif8zetmLHs9WoZlntTHmIoNM8TpLRY31ExncuUvUOXehd0kvahkuHjDw== + dependencies: + use-sync-external-store "1.2.0" diff --git a/packages/uiweb/package.json b/packages/uiweb/package.json index b83e10a1e..8764c656e 100644 --- a/packages/uiweb/package.json +++ b/packages/uiweb/package.json @@ -5,16 +5,16 @@ "registry": "https://registry.npmjs.org/" }, "dependencies": { + "@livepeer/react": "^2.6.0", "@pushprotocol/socket": "^0.5.0", "date-fns": "^2.28.0", "emoji-picker-react": "^3.5.1", "html-react-parser": "^1.4.13" }, "peerDependencies": { - "react": ">=16.8.0", - "styled-components": "^5.3.5", "@pushprotocol/restapi": "^1.2.15", - "@pushprotocol/socket": "^0.5.0" + "@pushprotocol/socket": "^0.5.0", + "react": ">=16.8.0", + "styled-components": "^5.3.5" } } - diff --git a/packages/uiweb/src/lib/components/index.ts b/packages/uiweb/src/lib/components/index.ts index 1f6eaf4d3..e80bfb4d7 100644 --- a/packages/uiweb/src/lib/components/index.ts +++ b/packages/uiweb/src/lib/components/index.ts @@ -1,4 +1,5 @@ export * from './notification'; export * from './parsetext'; export * from './subscribemodal'; -export * from './chat'; \ No newline at end of file +export * from './chat'; +export * from './space'; \ No newline at end of file diff --git a/packages/uiweb/src/lib/components/space/SpaceBanner/SpaceBanner.tsx b/packages/uiweb/src/lib/components/space/SpaceBanner/SpaceBanner.tsx new file mode 100644 index 000000000..7bc1f19ff --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceBanner/SpaceBanner.tsx @@ -0,0 +1,238 @@ +import React from 'react'; +import styled from 'styled-components'; + +import { SpaceBannerLoadingSkeleton } from './SpaceBannerLoadingSkeleton'; + +import { ISpacesTheme } from '../theme'; +import { ThemeContext } from '../theme/ThemeProvider'; +import { getDateAndTime } from '../helpers/date'; +import { getSpaceStatus } from '../helpers/space'; +import { ParticipantContainer } from '../reusables/ParticipantContainer'; +import { HostPfpContainer } from '../reusables'; + +import live from './../../../icons/live.svg'; +import scheduled from './../../../icons/scheduled.svg'; +import { useGetSpaceInfo } from './../../../hooks'; + +export interface ISpaceBannerProps { + spaceId: string; + orientation?: 'maximized' | 'minimized' | 'pill'; + isInvite?: boolean; + onBannerClick?: (arg: string) => void; + onJoin?: any; +} + +/** + * @interface IThemeProps + * this interface is used for defining the props for styled components + */ +interface IThemeProps { + theme?: ISpacesTheme; + orientation?: string; + status?: string; + clickable?: boolean; +} + +export const SpaceBanner: React.FC = ({ + spaceId, + orientation, + isInvite, + onBannerClick, + onJoin, +}) => { + const theme = React.useContext(ThemeContext); + const spaceData = useGetSpaceInfo(spaceId); + + const spaceStatus = getSpaceStatus(spaceData?.status); + + const handleClick = () => { + if (onBannerClick) { + onBannerClick(spaceData?.spaceId || ''); + } + }; + + // Check if the spaceData is not available, show the skeleton loading effect + if (!spaceData) { + return ; + } + + return ( + + {orientation === 'maximized' && ( + + )} + {orientation === 'maximized' ? null : ( + + )} + + {orientation === 'pill' + ? `${spaceData?.spaceName.slice(0, 20)}...` + : spaceData?.spaceName} + + + + + + {isInvite === true && spaceStatus === 'Live' ? ( + Join this space + ) : isInvite === true && + spaceStatus === 'Scheduled' ? ( + Remind Me + ) : null} + + ); +}; + +// Styling +const Container = styled.div` + display: flex; + flex-direction: ${(props) => + props.orientation === 'maximized' ? 'column' : 'row'}; + justify-content: ${(props) => + props.orientation === 'maximized' ? 'space-between' : 'space-between'}; + align-items: ${(props) => + props.orientation === 'maximized' ? 'flex-start' : 'center'}; + padding: ${(props) => + props.orientation === 'maximized' + ? '16px' + : props.orientation === 'minimized' + ? '0 20px' + : '0 11px'}; + gap: ${(props) => (props.orientation === 'maximized' ? '16px' : '8px')}; + width: ${(props) => + props.orientation === 'maximized' + ? 'inherit' + : props.orientation === 'minimized' + ? 'inherit' + : 'fit-content'}; + height: ${(props) => + props.orientation === 'maximized' + ? 'auto' + : props.orientation === 'minimized' + ? '40px' + : '63px'}; + background: ${(props) => + props.status === 'Live' + ? props.theme.titleBg + : props.theme.bgColorSecondary}; + border-radius: ${(props) => + props.orientation === 'maximized' + ? '17px' + : props.orientation === 'minimized' + ? '12px' + : '24px'}; + color: ${(props) => (props.status === 'Live' ? '#f5f5f5' : '#1E1E1E')}; + min-width: 0; + text-overflow: ellipsis; + overflow: hidden; + cursor: ${props => props.clickable && 'pointer'}; +`; + +const Title = styled.div<{ orientation?: string }>` + display: flex; + flex-direction: row; + justify-content: flex-start; + align-items: center; + font-family: Strawford; + font-weight: ${(props) => + props.orientation === 'maximized' ? '700' : '500'}; + font-size: ${(props) => + props.orientation === 'maximized' + ? '20px' + : props.orientation === 'minimized' + ? '16px' + : '12px'}; + line-height: 130%; + width: 90%; + line-clamp: ${(props) => (props.orientation === 'maximized' ? '3' : '2')}; + + @media (max-width: 425px) { + width: 95%; + } +`; + +const Status = styled.div` + display: flex; + flex-direction: row; + width: ${(props) => + props.orientation === 'maximized' ? '100%' : 'fit-content'}; + justify-content: space-between; + align-items: center; +`; + +const Time = styled.div<{ orientation?: string }>` + display: ${(props) => (props.orientation === 'maximized' ? 'flex' : 'none')}; + flex-direction: row; + justify-content: center; + align-items: center; +`; + +const Icon = styled.img` + height: 24px; + width: 24px; + padding: 0 11px 0 0; + align-self: center; +`; + +const TimeText = styled.div<{ status?: string }>` + font-weight: 500; + font-size: 14px; + line-height: 150%; + color: ${(props) => (props.status === 'Live' ? '#fff' : '#71717A')}; +`; + +const InviteButton = styled.button<{ status?: string }>` + display: flex; + justify-content: center; + align-items: center; + height: 36px; + width: 100%; + color: ${(props) => (props.status === 'Live' ? '#FFF' : '#8B5CF6')}; + border-radius: 8px; + border: ${(props) => + props.status === 'Live' ? '1px solid #FFF' : '1px solid #8B5CF6'}; + background: transparent; + cursor: pointer; +`; diff --git a/packages/uiweb/src/lib/components/space/SpaceBanner/SpaceBannerLoadingSkeleton.tsx b/packages/uiweb/src/lib/components/space/SpaceBanner/SpaceBannerLoadingSkeleton.tsx new file mode 100644 index 000000000..013d43705 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceBanner/SpaceBannerLoadingSkeleton.tsx @@ -0,0 +1,137 @@ +import React from 'react'; +import styled from 'styled-components'; + +export const SpaceBannerLoadingSkeleton: React.FC = () => { + return ( + + + + + + + + + + + + + + + + + + + ); +}; + +const SkeletonContainer = styled.div` + display: flex; + flex-direction: column; + gap: 24px; + padding: 16px; + background-color: #f1f1f1; + border-radius: 17px; + border: 1px solid lightgrey; + position: relative; + + &:after { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + border-radius: 17px; + background-color: #f1f1f1; + opacity: 0.5; + transition: opacity 0.8s ease-in-out infinite alternate; + } + + &:hover:after { + opacity: 0.3; + } +`; + +const SkeletonContent = styled.div` + display: flex; + align-items: center; + gap: 10px; +`; + +const SkeletonProfilePic = styled.div` + width: 48px; + height: 48px; + border-radius: 50%; + border: 1px solid lightgrey; + background-color: #d9d9d9; + transition: opacity 0.8s ease-in-out infinite alternate; + + &:hover { + opacity: 0.5; + } +`; + +const SkeletonProfileInfo = styled.div` + display: flex; + flex-direction: column; + gap: 5px; + width: 100%; +`; + +const SkeletonText = styled.div` + width: 100%; + height: 18px; + background-color: #d9d9d9; + border-radius: 8px; + border: 1px solid lightgrey; + transition: opacity 0.8s ease-in-out infinite alternate; + + &:hover { + opacity: 0.5; + } +`; + +const SkeletonName = styled(SkeletonText)` + width: 30%; +`; + +const SkeletonHandle = styled(SkeletonText)` + width: 40%; +`; + +const SkeletonSpaceInfo = styled(SkeletonText)` + width: 100%; + height: 30px; +`; + +const SkeletonLine = styled.div` + display: flex; + align-items: center; + width: 100%; +`; + +const SkeletonLeftSquare = styled(SkeletonText)` + width: 10%; + height: 32px; +`; + +const SkeletonOverlap = styled.div` + display: flex; + align-items: flex-start; + justify-content: right; + width: 100%; + margin-top: 8px; +`; + +const SkeletonOverlapProfilePic = styled(SkeletonProfilePic)` + height: 48px; + border: 1px solid lightgrey; + margin-left: -24px; + transition: opacity 0.8s ease-in-out infinite alternate; + &:nth-child(2) { + margin-left: -24px; + } + &:nth-child(3) { + margin-left: -24px; + } +`; diff --git a/packages/uiweb/src/lib/components/space/SpaceBanner/index.ts b/packages/uiweb/src/lib/components/space/SpaceBanner/index.ts new file mode 100644 index 000000000..72fd7241f --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceBanner/index.ts @@ -0,0 +1 @@ +export * from "./SpaceBanner"; \ No newline at end of file diff --git a/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWButton/SCWButton.tsx b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWButton/SCWButton.tsx new file mode 100644 index 000000000..ee1244992 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWButton/SCWButton.tsx @@ -0,0 +1,57 @@ +import React, { MouseEventHandler, useContext } from 'react' +import styled from 'styled-components'; + +import { ISpacesTheme } from '../../theme'; +import { ThemeContext } from '../../theme/ThemeProvider'; + +export interface ISCWButtonProps { // Space Creation Widget Button Interface + btnText?: string; + customStyle?: any; + theme?: ISpacesTheme; + onCreate?: MouseEventHandler; +} + +const defaultProps: ISCWButtonProps = { + btnText: 'Create your Space', + customStyle: { + padding: '20px', + borderRadius: '12px', + border: '0px solid transparent', + fontSize: '1rem', + }, +} + +export const SCWButton: React.FC = (props) => { + const { btnText, customStyle, onCreate } = props; + + const theme = useContext(ThemeContext); + + return ( +
+ + {btnText} + +
+ ) +} + +/* styling */ +const CreateButton = styled.button` + padding: ${props => props.customStyle.padding}; + border-radius: ${props => props.customStyle.borderRadius}; + border: ${props => props.customStyle.border}; + font-size: ${props => props.customStyle.fontSize}; + + background-image: ${(props) => props.theme.titleBg}; + color: ${(props) => props.theme.titleTextColor}; + + cursor: pointer; +`; + +SCWButton.defaultProps = defaultProps; + +export default SCWButton; diff --git a/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWButton/index.ts b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWButton/index.ts new file mode 100644 index 000000000..905744434 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWButton/index.ts @@ -0,0 +1 @@ +export * from './SCWButton'; \ No newline at end of file diff --git a/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWCreateModal/SCWCreateModal.tsx b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWCreateModal/SCWCreateModal.tsx new file mode 100644 index 000000000..976c5d117 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWCreateModal/SCWCreateModal.tsx @@ -0,0 +1,90 @@ +import React, { MouseEventHandler } from 'react' +import styled from 'styled-components' + +import { Modal } from '../../reusables/Modal' +import { Button } from '../../reusables/Button'; +import { ModalHeader } from '../../reusables/ModalHeader'; +import { TextInputWithCounter } from '../../reusables/TextInput'; + +import { CalendarPurple } from '../../../../icons/CalendarPurple'; + +export interface ISCWCModalProps { // Space Creation Widget Create Modal Interface + isInviteVisible?: any; + closeCreateModal?: MouseEventHandler; + handleNameChange?: any; + handleDescriptionChange?: any; + nameValue?: any; + descriptionValue?: any; + isDescriptionEnabled: boolean; + isScheduleVisible?: any; + onClose: () => void; +} + +export const SCWCreateModal: React.FC = (props) => { + const { + isInviteVisible, closeCreateModal, handleNameChange, + handleDescriptionChange, nameValue, descriptionValue, + isDescriptionEnabled, isScheduleVisible, onClose, + } = props; + + const secBtn = { + background: 'transparent', + borderColor: '#8b5cf6' + } + + return ( + + + + + + { + isDescriptionEnabled ? + + : null + } + + + + +
+ +
+
+
+ ) +} + +/* styling */ +const ButtonContainer = styled.div` + display: flex; + justify-content: space-between; + width: 100%; +`; \ No newline at end of file diff --git a/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWCreateModal/index.ts b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWCreateModal/index.ts new file mode 100644 index 000000000..aae6e3038 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWCreateModal/index.ts @@ -0,0 +1 @@ +export * from './SCWCreateModal' diff --git a/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWInviteModal/SCWInviteModal.tsx b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWInviteModal/SCWInviteModal.tsx new file mode 100644 index 000000000..7843ac871 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWInviteModal/SCWInviteModal.tsx @@ -0,0 +1,367 @@ +/* eslint-disable no-prototype-builtins */ +import React, { useState, MouseEventHandler, useContext } from 'react' +import styled from 'styled-components' +import * as PushAPI from '@pushprotocol/restapi'; + +import { ModalHeader } from '../../reusables/ModalHeader'; +import { Modal } from '../../reusables/Modal'; +import { Button } from '../../reusables/Button'; +import { SearchInput } from '../../reusables/SearchInput'; +import { ProfileContainer } from '../../reusables/ProfileContainer'; +import { ThemeContext } from '../../theme/ThemeProvider'; +import { Spinner } from '../../reusables/Spinner'; + +import CircularProgressSpinner from '../../../loader/loader'; + +import { useSpaceData } from '../../../../hooks'; +import SettingsIcon from '../../../../icons/settingsBlack.svg'; +import { Image } from '../../../../config'; + +export interface ISCWIModalProps { // Space Creation Widget Create Modal Interface + closeInviteModal?: MouseEventHandler; + makeScheduleVisible?: MouseEventHandler; + createSpace?: MouseEventHandler; + isLoading?: boolean; + invitedMembersList?: any; + setInvitedMembersList?: any; + invitedAddressList?: any; + setInvitedAddressList?: any; + adminsList?: any; + setAdminsList?: any; + adminsAddressList?: any; + setAdminsAddressList?: any; + onClose: () => void; +} + +interface User { + handle: string; + name: string; +} + +export const SCWInviteModal: React.FC = (props) => { + const { + closeInviteModal, makeScheduleVisible, createSpace, isLoading, + invitedMembersList, + setInvitedMembersList, + invitedAddressList, + setInvitedAddressList, + adminsList, + setAdminsList, + adminsAddressList, + setAdminsAddressList, + onClose + } = props; + + const { env } = useSpaceData(); + + const theme = useContext(ThemeContext); + + const [invitedMember, setInvitedMember] = useState('') + const [loadingAccount, setLoadingAccount] = useState(false) + + const [searchedUser, setSearchedUser]= useState({}); + const [errorMsg, setErrorMsg] = useState(''); + + const searchMember = async (event: any) => { + setInvitedMember(event.target.value) + + try { + setLoadingAccount(true); + const response = await PushAPI.user.get({ + account: event.target.value, + env, + }); + + if(response === null) { + const nullUser = { + walletAddress: event.target.value, + name: event.target.value, + image: tempImageUrl, + }; + setSearchedUser(nullUser) + } else { + setSearchedUser(response); + } + setErrorMsg(''); + } catch (e:any) { + console.error(e.message); + setSearchedUser({}); + setErrorMsg(e.message); + } finally { + setLoadingAccount(false); + } + } + + const clearInput = () => { + setInvitedMember(''); + setSearchedUser({}); + setErrorMsg(''); + } + + const handleInviteMember = (user: any) => { + if (user.did) { + setInvitedAddressList([...invitedAddressList, user.did.substring(7)]) + setInvitedMembersList([...invitedMembersList, user]); + } else { + setInvitedAddressList([...invitedAddressList, user.walletAddress]) + setInvitedMembersList([...invitedMembersList, user]); + } + + clearInput(); + } + + const handlePromoteToAdmin = (user: any) => { + if (user.did) { + setAdminsList([...adminsList, user]) + setAdminsAddressList([...adminsAddressList, user.did.substring(7)]); + } else { + setAdminsList([...adminsList, user]) + setAdminsAddressList([...adminsAddressList, user.walletAddress]); + } + + const updatedArray = invitedMembersList.filter((item: any) => item !== user) + setInvitedMembersList(updatedArray); + + if (user.did) { + const updateAddressArray = invitedAddressList.filter((item: string) => item !== user.did.substring(7)) + setInvitedAddressList(updateAddressArray); + } else { + const updateAddressArray = invitedAddressList.filter((item: string) => item !== user.walletAddress) + setInvitedAddressList(updateAddressArray); + } + + clearInput(); + } + + const handleDeleteInvitedUser = (user: any) => { + const updatedArray = invitedMembersList.filter((item: any) => item !== user) + setInvitedMembersList(updatedArray); + }; + + const tempImageUrl = "https://imgv3.fotor.com/images/blog-richtext-image/10-profile-picture-ideas-to-make-you-stand-out.jpg"; + + return ( +
+ + + + + {errorMsg} + + + {loadingAccount && } + { + Object.keys(searchedUser).length === 0 ? + null + : searchedUser.hasOwnProperty('walletAddress') ? + Add +} + btnCallback={() => handleInviteMember(searchedUser)} + border + /> + : Add +} + btnCallback={() => handleInviteMember(searchedUser)} + border + /> + } + + + { + invitedMembersList.length ? + + Invited Members {invitedMembersList.length} + { + invitedMembersList.map((item: any) => { + if (item.hasOwnProperty('walletAddress')) { + return + Settings icon + + } + // btnCallback={() => handleDeleteInvitedUser(item)} + removeCallback={() => handleDeleteInvitedUser(item)} + promoteCallback={() => handlePromoteToAdmin(item)} + border + /> + } else { + return + Settings icon + + } + // btnCallback={() => handleDeleteInvitedUser(item)} + removeCallback={() => handleDeleteInvitedUser(item)} + promoteCallback={() => handlePromoteToAdmin(item)} + border + /> + } + }) + } + + : null + } + + { + adminsList.length ? + + Speakers {adminsList.length} + { + adminsList.map((item: any) => { + if (item.hasOwnProperty('walletAddress')) { + return + Settings icon + + } + // btnCallback={() => handleDeleteInvitedUser(item)} + removeCallback={() => handleDeleteInvitedUser(item)} + promoteCallback={() => handlePromoteToAdmin(item)} + border + /> + } else { + return + Settings icon + + } + // btnCallback={() => handleDeleteInvitedUser(item)} + removeCallback={() => handleDeleteInvitedUser(item)} + // promoteCallback={() => handlePromoteToAdmin(item)} + border + /> + } + }) + } + + : null + } + + + +
+ ) +} + + +const MembersList = styled.div` + width: 100%; + display: flex; + flex-direction: column; + gap: 8px; +`; + +const InvitedList = styled.div` + width: 100%; + display: flex; + flex-direction: column; + gap: 8px; + + margin-top: 28px; +`; + +const Heading = styled.div` + display: flex; + align-items: center; +`; + +const PendingCount = styled.div` + background: ${(props => props.theme.btnColorPrimary)}; + border-radius: 8px; + padding: 4px 10px; + margin-left: 6px; + font-size: 13px; + color: ${(props => props.theme.titleTextColor)}; +`; + +const SettingsCont = styled.div` + display: flex; + justify-content: center; + align-items: center; + + cursor: pointer; +`; + +const ContBtn = styled.button` + display: flex; + flex-direction: row; + align-items: center; + margin-left: 8px; + line-height: 18px; + width: max-content; + background: transparent; + color: #8B5CF6; + border-radius: 6px; + font-weight: 500; + font-size: 12px; + padding: 4px 8px; + border-radius: 8px; + border: 1px solid #8B5CF6; + cursor: pointer; +`; \ No newline at end of file diff --git a/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWInviteModal/index.ts b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWInviteModal/index.ts new file mode 100644 index 000000000..ce11a56b2 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWInviteModal/index.ts @@ -0,0 +1 @@ +export * from './SCWInviteModal'; diff --git a/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWScheduleModal/SCWScheduleModal.tsx b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWScheduleModal/SCWScheduleModal.tsx new file mode 100644 index 000000000..063d2222d --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWScheduleModal/SCWScheduleModal.tsx @@ -0,0 +1,59 @@ +import React, { MouseEventHandler } from 'react' +import styled from 'styled-components'; + +import DateTimePicker from '../../reusables/DateTimePicker'; + +import { Modal } from '../../reusables/Modal'; +import { ModalHeader } from '../../reusables/ModalHeader'; +import { Button } from '../../reusables/Button'; + +export interface ISCWSModalProps { // Space Creation Widget Schedule Modal Interface + closeScheduleModal?: MouseEventHandler; + makeCreateVisible?: MouseEventHandler; + makeInviteVisible?: MouseEventHandler; + + dateValue?: any; + onDateChange?: any; + timeValue?: any; + onTimeChange?: any; + + onClose: () => void; +} + +export const SCWScheduleModal: React.FC = (props) => { + + const { closeScheduleModal, makeCreateVisible, makeInviteVisible, dateValue, timeValue, onDateChange, onTimeChange, onClose } = props; + + return ( + + + + + + + + + + ) +} + +const ButtonContainer = styled.div` + display: flex; + justify-content: space-between; + width: 100%; +`; diff --git a/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWScheduleModal/index.ts b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWScheduleModal/index.ts new file mode 100644 index 000000000..9b907490d --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SCWScheduleModal/index.ts @@ -0,0 +1 @@ +export * from './SCWScheduleModal'; diff --git a/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SpaceCreationWidget.tsx b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SpaceCreationWidget.tsx new file mode 100644 index 000000000..26baa118c --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/SpaceCreationWidget.tsx @@ -0,0 +1,174 @@ +import { useState } from 'react' +import styled from 'styled-components'; +import * as PushAPI from '@pushprotocol/restapi'; + +import { SCWCreateModal } from './SCWCreateModal/SCWCreateModal' +import { SCWScheduleModal } from './SCWScheduleModal/SCWScheduleModal'; +import { SCWInviteModal } from './SCWInviteModal/SCWInviteModal'; +import { SCWButton } from './SCWButton'; + +import { useSpaceData } from '../../../hooks'; + +export interface ISpaceCreateWidgetProps { + CustomComponent?: any; +} + +export const SpaceCreationWidget:React.FC = (props) => { + const { CustomComponent } = props; + + const [isCreateModalVisible, setIsCreateModalVisible] = useState(false); + const [isScheduleModalVisible, setIsScheduleModalVisible] = useState(false); + const [isInviteModalVisible, setIsInviteModalVisible] = useState(false); + + const [invitedMembersList, setInvitedMembersList] = useState([]) + const [invitedAddressList, setInvitedAddressList] = useState([]) + console.log("🚀 ~ file: SpaceCreationWidget.tsx:25 ~ invitedAddressList:", invitedAddressList) + const [adminsList, setAdminsList] = useState([]) + const [adminsAddressList, setAdminsAddressList] = useState([]) + console.log("🚀 ~ file: SpaceCreationWidget.tsx:27 ~ adminsAddressList:", adminsAddressList) + + const [isLoading, setLoading] = useState(false); + + const [spaceState, setSpaceState] = useState({ + spaceName: '', + spaceDescription: '', + date: new Date(), + time: new Date(), + }) + + const { signer } = useSpaceData(); + + const handleNameChange = (event: any) => { + setSpaceState((prevState) => ({...prevState, spaceName: event.target.value})) + }; + + const handleDescriptionChange = (event: any) => { + setSpaceState((prevState) => ({...prevState, spaceDescription: event.target.value})) + }; + + const onDateChange = (dateValue: any) => { + setSpaceState((prevState) => ({...prevState, date: dateValue})) + }; + + const onTimeChange = (timeValue: any) => { + setSpaceState((prevState) => ({...prevState, time: timeValue})) + }; + + const showCreateSpace = () => { + setIsCreateModalVisible(!isCreateModalVisible); + setIsScheduleModalVisible(false); + setIsInviteModalVisible(false); + } + + const showScheduleSpace = () => { + setIsScheduleModalVisible(!isScheduleModalVisible); + setIsCreateModalVisible(false); + setIsInviteModalVisible(false); + } + + const showInviteSpace = () => { + setIsInviteModalVisible(!isInviteModalVisible); + setIsScheduleModalVisible(false); + setIsCreateModalVisible(false); + } + + const closeCreateModal = () => { + setIsCreateModalVisible(false); + } + + const closeScheduleModal = () => { + setIsScheduleModalVisible(false); + } + + const closeInviteModal = () => { + setIsInviteModalVisible(false); + } + + const testCreateSpace = async () => { + const spaceCreate = { + spaceName: spaceState.spaceName, + spaceDescription: 'Push Space', + members: invitedAddressList, + spaceImage: 'asd', + admins: adminsAddressList, + isPublic: true, + scheduleAt: new Date(spaceState.time), + signer: signer as PushAPI.SignerType, + } + + try { + setLoading(true); + const response = await PushAPI.space.create(spaceCreate); + + console.log(response); + } catch (e:any) { + console.error(e.message); + } finally { + setLoading(false); + closeInviteModal(); + } + }; + + return ( + + { + CustomComponent + ? + + : + + } + + {isCreateModalVisible && + + } + + {isScheduleModalVisible && + + } + + {isInviteModalVisible && + + } + + ) +} + +const SCWContainer = styled.div` + font-family: 'Strawford'; // update to fontFamily theme +`; \ No newline at end of file diff --git a/packages/uiweb/src/lib/components/space/SpaceCreationWidget/index.ts b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/index.ts new file mode 100644 index 000000000..7f6d6d24e --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceCreationWidget/index.ts @@ -0,0 +1 @@ +export * from './SpaceCreationWidget'; diff --git a/packages/uiweb/src/lib/components/space/SpaceFeed/SpaceFeed.tsx b/packages/uiweb/src/lib/components/space/SpaceFeed/SpaceFeed.tsx new file mode 100644 index 000000000..1cb55ff6f --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceFeed/SpaceFeed.tsx @@ -0,0 +1,478 @@ +import React, { useState } from 'react'; +import styled from 'styled-components'; + +import { SpaceIFeeds } from '@pushprotocol/restapi'; + +import { SpaceBanner } from '../SpaceBanner'; + +import { Spinner } from '../reusables/Spinner'; + +import { + useSpaceData, + useFeedScroll, + useMySpaces, + usePopularSpaces, + useSpaceRequests, +} from '../../../hooks'; + +import { ISpacePaginationData } from '../../../context/spacesContext'; +import spacesIcon from '../../../icons/Spaces.svg'; + +enum OrientationEnums { + Horizontal = 'horizontal', + Vertical = 'vertical', +} + +enum Tabs { + ForYou = 'For You', + Popular = 'Popular', + HostedByYou = 'Hosted by you', +} + +enum FilterEnums { + All = 'All', + Live = 'Live', + Scheduled = 'Scheduled', +} +export interface ISpaceFeedProps { + orientation?: 'horizontal' | 'vertical'; + height?: number; + width?: number; + sortingOrder?: string[]; + showTabs?: boolean; + filter?: FilterEnums.All | FilterEnums.Live | FilterEnums.Scheduled; + showFilter?: boolean; + onBannerClickHandler?: (arg: string) => void; +} + +export const SpaceFeed: React.FC = ({ + orientation = 'veritcal', + height, + width, + sortingOrder = [Tabs.Popular, Tabs.ForYou, Tabs.HostedByYou], + showTabs = true, + filter = FilterEnums.All, + showFilter = true, + onBannerClickHandler, +}) => { + const [tab, setTab] = useState(sortingOrder[0]); + const [filterTab, setFilterTab] = useState(filter); + + const { + account, + mySpaces, + setMySpaces, + popularSpaces, + setPopularSpaces, + spaceRequests, + setSpaceRequests, + } = useSpaceData(); + + const listInnerRef = useFeedScroll(mySpaces.apiData?.length); + + const handleTabChange = (tab: string) => { + setTab(tab); + }; + + const handleFilterData = (spacesList: SpaceIFeeds[]) => { + if (filterTab === FilterEnums.All) { + return spacesList; + } else if (filterTab === FilterEnums.Live) { + return spacesList.filter( + (space: SpaceIFeeds) => space.spaceInformation?.status === 'ACTIVE' + ); + } else if (filterTab === FilterEnums.Scheduled) { + return spacesList.filter( + (space: SpaceIFeeds) => space.spaceInformation?.status === 'PENDING' + ); + } else { + return spacesList; + } + }; + + const handleMySpacesFilter = (spacesList: SpaceIFeeds[]) => { + if (tab === Tabs.HostedByYou) { + return spacesList.filter( + (space: SpaceIFeeds) => + space.spaceInformation?.spaceCreator.slice(7).toUpperCase() === + account?.toUpperCase() + ); + } + if (tab === Tabs.ForYou) { + return spacesList.filter( + (space: SpaceIFeeds) => + space.spaceInformation?.spaceCreator.slice(7).toUpperCase() !== + account?.toUpperCase() + ); + } else { + return handleFilterData(spacesList); + } + }; + + const handleClick = (spaceId: string) => { + if (onBannerClickHandler) { + return onBannerClickHandler(spaceId || ''); + } + }; + + const incrementSpacePage = async (spaces: ISpacePaginationData) => { + if ( + loading === false && + spaces.currentPage && + spaces.lastPage && + spaces.currentPage < spaces.lastPage + ) { + if (spaces === mySpaces) + spaces.currentPage && + console.log('spaces.currentPage', spaces.currentPage, Date.now()); + setMySpaces({ + currentPage: spaces.currentPage + 1, + lastPage: spaces.lastPage + 1, + }); + if (spaces === popularSpaces) + spaces.currentPage && + setPopularSpaces({ + currentPage: spaces.currentPage + 1, + lastPage: spaces.lastPage + 1, + }); + if (spaces === spaceRequests) + spaces.currentPage && + setSpaceRequests({ + currentPage: spaces.currentPage + 1, + lastPage: spaces.lastPage + 1, + }); + } else { + return; + } + }; + + const loadMoreData = async () => { + if (tab === Tabs.ForYou) { + incrementSpacePage(mySpaces); + } + if (tab === Tabs.Popular) { + incrementSpacePage(popularSpaces); + } + if (tab === Tabs.HostedByYou) { + incrementSpacePage(spaceRequests); + } + }; + + console.log(account); + + const onScroll = () => { + if (listInnerRef.current) { + const { scrollTop } = listInnerRef.current; + const { offsetHeight } = listInnerRef.current; + const { scrollHeight } = listInnerRef.current; + + if (scrollTop + offsetHeight + 1 >= scrollHeight) { + loadMoreData(); + } + } + }; + + //API calls + + const mySpaceLoading = useMySpaces(account); + const popularSpaceLoading = usePopularSpaces(); + const spaceRequestsLoading = useSpaceRequests(account); + const { loading } = + mySpaceLoading || popularSpaceLoading || spaceRequestsLoading; + + return ( +
+ {orientation === OrientationEnums.Horizontal ? ( + + {orientation === OrientationEnums.Horizontal + ? mySpaces && + mySpaces.apiData?.map((space: SpaceIFeeds) => { + return ( + + ); + }) + : mySpaces && + mySpaces.apiData?.map((space: SpaceIFeeds) => { + return ( + + ); + })} + + ) : ( + <> + + + {sortingOrder.map((tabName: string) => { + return ( + handleTabChange(tabName)} + > + {tabName} + + ); + })} + + + + setFilterTab(FilterEnums.All)} + > + All + + setFilterTab(FilterEnums.Live)} + > + Live + + setFilterTab(FilterEnums.Scheduled)} + > + Scheduled + + + + + {tab === Tabs.ForYou ? ( + + {mySpaces.apiData && + (handleFilterData( + handleMySpacesFilter(mySpaces.apiData as SpaceIFeeds[]) + ).length === 0 ? ( + + + Join a space + + Get started by joining a space + + + ) : ( + handleFilterData( + handleMySpacesFilter(mySpaces.apiData as SpaceIFeeds[]) + ).map((space: SpaceIFeeds) => { + return ( + + ); + }) + ))} + + ) : tab === Tabs.Popular ? ( + + Popular Spaces + {popularSpaces && + handleFilterData( + popularSpaces.apiData as SpaceIFeeds[] + ).map((space: SpaceIFeeds) => { + return ( + + ); + })} + + ) : ( + + {mySpaces.apiData && + (handleFilterData( + handleMySpacesFilter(mySpaces.apiData as SpaceIFeeds[]) + ).length === 0 ? ( + + + Create a space + + Get started by creating a space + + + ) : ( + handleFilterData( + handleMySpacesFilter(mySpaces.apiData as SpaceIFeeds[]) + ).map((space: SpaceIFeeds) => { + return ( + + ); + }) + ))} + + )} + {loading && } + + + + )} +
+ ); +}; + +//Styling +const ScrollContainer = styled.div<{ height?: number; width?: number }>` + width: ${(props) => (props.width ? `${props.width}px` : 'inherit')}; + height: ${(props) => (props.height ? `${props.height}px` : 'auto')}; + overflow-y: auto; +}`; +const Container = styled.div` + display: flex; + flex-direction: column; + align-items: center; + background: #ffffff; + border: 1px solid #dcdcdf; + border-radius: 12px; + padding: 24px 32px; +}`; + +const Navigation = styled.div<{ + showTabs?: boolean; + showFilter?: boolean; + width?: number; +}>` + display: ${(props) => (props.showTabs ? 'flex' : 'none')}; + flex-direction: row; + justify-content: space-between; + align-items: center; + width: ${(props) => (props.width ? `${props.width}px` : 'inherit')}; + border-bottom: 1px solid #DCDCDF; + margin-bottom: ${(props) => (props.showFilter ? '0' : '27px')}; +}`; + +const NavButtonWrapper = styled.div` + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; +}`; + +const NavButton = styled.button<{ active?: boolean }>` + padding: 10px 30px; + font-weight: 450; + font-size: 14px; + border: none; + border-bottom: ${(props) => (props.active ? '2px solid #8B5CF6' : 'none')}; + background: none; + color : ${(props) => (props.active ? '#000000' : '#71717A')}; + + &:hover { + cursor: pointer; + } +}`; + +const Spaces = styled.div<{ orientation?: string }>` + display: flex; + flex-direction: ${(props) => + props.orientation === 'horizontal' ? 'row' : 'column'}; + justify-content: flex-start; + align-items: center; + background: #ffffff; + width: ${(props) => + props.orientation === 'horizontal' ? 'inherit' : '100%'}; + height: auto; + gap: 16px; +}`; + +const PopularSpaces = styled.div` + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: center; + background: #ffffff; + width: 100%; + height: auto; + gap: 16px; +}`; + +const Text = styled.div` + width: 100%; + text-align: left; + font-family: 'Strawford'; + font-weight: 450; + font-size: 18px; +}`; + +const Filter = styled.div<{ showFilter?: boolean }>` + display: ${(props) => (props.showFilter ? 'flex' : 'none')}; + flex-direction: row; + justify-content: flex-start; + align-items: center; + background: #ffffff; + width: 100%; + margin: 22px 0; +}`; + +const FilterButton = styled.button<{ active: boolean }>` + display: inline-flex; + height: 30px; + padding: 0px 16px; + justify-content: center; + align-items: center; + border-radius: 99px; + border: 1px solid #C4B5FD; + background: ${(props) => (props.active ? '#8B5CF6' : '#EDE9FE')}; + color: ${(props) => (!props.active ? '#8B5CF6' : '#FFF')}; + margin-right: 8px; + font-size: 14px; + + &:hover { + cursor: pointer; + } +}`; + +const NoSpaces = styled.div` + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + margin: 130px 0; +}`; + +const SpacesIcon = styled.img` + width: 36px; + height: 36px; +}`; + +const NoSpacesTextV1 = styled.div` + font-family: 'Strawford'; + font-weight: 450; + font-size: 16px; + color: #000; +}`; + +const NoSpacesTextV2 = styled.div` + font-family: 'Strawford'; + font-weight: 450; + color: #71717A; + font-size: 14px; +}`; diff --git a/packages/uiweb/src/lib/components/space/SpaceFeed/index.ts b/packages/uiweb/src/lib/components/space/SpaceFeed/index.ts new file mode 100644 index 000000000..506cf05f5 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceFeed/index.ts @@ -0,0 +1 @@ +export * from "./SpaceFeed"; \ No newline at end of file diff --git a/packages/uiweb/src/lib/components/space/SpaceInvites/SpaceInvites.tsx b/packages/uiweb/src/lib/components/space/SpaceInvites/SpaceInvites.tsx new file mode 100644 index 000000000..ecc07676e --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceInvites/SpaceInvites.tsx @@ -0,0 +1,144 @@ +import React, { useState } from 'react'; +import styled from 'styled-components'; +import { Modal } from '../reusables/Modal'; +import { Spinner } from '../reusables/Spinner'; +import { ModalHeader } from '../reusables/ModalHeader'; +import { useFeedScroll, useSpaceData, useSpaceRequests } from '../../../hooks'; +import { SpaceBanner } from '../SpaceBanner'; + +export interface ISpaceInvitesProps { + account?: string; + children?: React.ReactNode; +} + +export const SpaceInvites: React.FC = ({ + account = '0x04bE5701AB5b2f2117332b4748020737B29a2e1D', + children, +}: ISpaceInvitesProps) => { + const [modalOpen, setModalOpen] = useState(false); + const { spaceRequests, setSpaceRequests } = useSpaceData(); + + const containerRef = useFeedScroll(spaceRequests.apiData?.length); + + const [playBackUrl, setPlayBackUrl] = useState(''); + const { spacesObjectRef, spaceObjectData, initSpaceObject, setSpaceWidgetId } = useSpaceData(); + + const handleJoinSpace = async (space: any) => { + await initSpaceObject(space?.spaceId as string); + await spacesObjectRef?.current?.join(); + const playBackUrl = spaceObjectData.spaceDescription; + setPlayBackUrl(playBackUrl); + handleCloseModal(); + setSpaceWidgetId(space?.spaceId as string) + console.log('Space Joined'); + }; + + const handleOpenModal = () => { + setModalOpen(true); + }; + + const handleCloseModal = () => { + setModalOpen(false); + }; + + const loadMoreData = () => { + if ( + loading === false && + spaceRequests.currentPage && + spaceRequests.lastPage && + spaceRequests.currentPage < spaceRequests.lastPage + ) { + console.log('Load More Data'); + setSpaceRequests({ + currentPage: spaceRequests.currentPage + 1, + lastPage: spaceRequests.lastPage + 1, + }); + } + }; + + const onScrollContainer = () => { + if (containerRef.current) { + const { scrollTop, scrollHeight, clientHeight } = containerRef.current; + if (scrollTop + clientHeight >= scrollHeight) { + loadMoreData(); + } + } + }; + + const { loading } = useSpaceRequests(account); + return ( + <> + {!children && } + + {children &&
{children}
} + + {modalOpen && ( + + 0 + ? spaceRequests.apiData?.length + : undefined + } + closeCallback={handleCloseModal} + /> + + + {spaceRequests.apiData + ? spaceRequests.apiData.map((space: any) => { + return ( + handleJoinSpace(space)} + /> + ); + }) + : null} + {loading ? : null} + + + + )} + + ); +}; + +const Button = styled.button` + padding: 8px 16px; + background-color: #8b5cf6; + color: #fff; + border: none; + border-radius: 4px; + cursor: pointer; +`; + +const ScrollContainer = styled.div` + max-height: 400px; + width: inherit; + margin-top: 24px; + overflow-y: scroll; + + &::-webkit-scrollbar{ + margin-left: 10px; + width: 8px; + height: 8px; + } + + &::-webkit-scrollbar-thumb{ + -webkit-appearance: none; + width: 4px; + height: auto; + background:#8B5CF6; + border-radius: 99px; + } +`; + +const InviteContainer = styled.div` + display: flex; + flex-direction: column; + gap: 16px; + margin: 0 10px; +`; diff --git a/packages/uiweb/src/lib/components/space/SpaceInvites/index.ts b/packages/uiweb/src/lib/components/space/SpaceInvites/index.ts new file mode 100644 index 000000000..43c623f28 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceInvites/index.ts @@ -0,0 +1 @@ +export * from "./SpaceInvites"; \ No newline at end of file diff --git a/packages/uiweb/src/lib/components/space/SpaceWidget/LiveSpaceProfileContainer.tsx b/packages/uiweb/src/lib/components/space/SpaceWidget/LiveSpaceProfileContainer.tsx new file mode 100644 index 000000000..c7cf15281 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceWidget/LiveSpaceProfileContainer.tsx @@ -0,0 +1,90 @@ +import { IMediaStream } from '@pushprotocol/restapi'; +import { Image, Item, Text } from '../../../config'; + +import HandIcon from '../../../icons/hand.svg'; +import MicOffIcon from '../../../icons/micoff.svg'; +import { VideoPlayer } from './VideoPlayer'; + +export interface ILiveSpaceProfileContainerProps { + wallet: string; + isHost?: boolean; + isSpeaker?: boolean; + image: string; + requested?: boolean; + mic?: boolean; + stream?: IMediaStream; +} + +export const LiveSpaceProfileContainer = ( + options: ILiveSpaceProfileContainerProps +) => { + const { + wallet, + isHost, + isSpeaker, + image, + requested = false, + mic = true, + stream, + } = options || {}; + + return ( + + Profile pic + + {wallet.slice(7, 12).concat('...')} + {stream && } + + {requested ? ( + + + Requested + + Hand Icon + + ) : ( + + + {isHost ? 'Host' : isSpeaker ? 'Speaker' : 'Listener'} + + {!mic && ( + Mic Off Icon + )} + + )} + + ); +}; diff --git a/packages/uiweb/src/lib/components/space/SpaceWidget/LiveWidgetContent.tsx b/packages/uiweb/src/lib/components/space/SpaceWidget/LiveWidgetContent.tsx new file mode 100644 index 000000000..bf630ce96 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceWidget/LiveWidgetContent.tsx @@ -0,0 +1,174 @@ +import React, { useEffect, useState } from 'react'; +import styled from 'styled-components'; + +import { LiveSpaceProfileContainer } from './LiveSpaceProfileContainer'; +import { SpaceMembersSectionModal } from './SpaceMembersSectionModal'; + +import { Button, Image, Item, Text } from '../../../config'; +import MicOnIcon from '../../../icons/micon.svg'; +import MicEngagedIcon from '../../../icons/MicEngage.svg'; +import MuteIcon from '../../../icons/Muted.svg'; +import ShareIcon from '../../../icons/Share.svg'; +import MembersIcon from '../../../icons/Members.svg'; +import { SpaceDTO } from '@pushprotocol/restapi'; + +import { useSpaceData } from '../../../hooks'; + +import { Player } from '@livepeer/react'; + +interface LiveWidgetContentProps { + spaceData?: SpaceDTO; + // temp props only for testing demo purpose for now + isHost?: boolean; + isJoined?: boolean; + isSpeaker?: boolean; +} +export const LiveWidgetContent: React.FC = ({ + spaceData, + isJoined, + isHost, + isSpeaker, +}) => { + const tempImageUrl = + 'https://imgv3.fotor.com/images/blog-richtext-image/10-profile-picture-ideas-to-make-you-stand-out.jpg'; + const [showMembersModal, setShowMembersModal] = useState(false); + const [isMicOn, setIsMicOn] = useState(true); + const [playBackUrl, setPlayBackUrl] = useState(''); + const { spacesObjectRef, spaceObjectData, initSpaceObject } = useSpaceData(); + + const handleJoinSpace = async () => { + // await initSpaceObject(spaceData?.spaceId as string); + await spacesObjectRef?.current?.join(); + const playBackUrl = spaceObjectData.spaceDescription; + setPlayBackUrl(playBackUrl); + console.log('Space Joined'); + }; + console.log('spaceObjectData', spaceObjectData); + + return ( + <> + + {spaceObjectData.connectionData.incoming.map( + (profile) => ( + ( + + ) + ) + )} + + + {isJoined ? ( + + + isHost || isSpeaker ? setIsMicOn(!isMicOn) : null + } + > + Mic Icon + + {isHost || isSpeaker + ? isMicOn + ? 'Speaking' + : 'Muted' + : 'Request'} + + + + setShowMembersModal(true)} + alt="Members Icon" + /> + Share Icon + + + + + ) : ( + + )} + {showMembersModal ? ( + setShowMembersModal(false)} + /> + ) : null} + + + ); +}; + +const PeerPlayer = styled(Player)` + width: 0; + height: 0; +}`; diff --git a/packages/uiweb/src/lib/components/space/SpaceWidget/ScheduledWidgetContent.tsx b/packages/uiweb/src/lib/components/space/SpaceWidget/ScheduledWidgetContent.tsx new file mode 100644 index 000000000..29af80161 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceWidget/ScheduledWidgetContent.tsx @@ -0,0 +1,215 @@ +import styled from 'styled-components'; + +import { Button, Container, Image, Item, Text } from '../../../config'; +import { formatDate } from '../../../helpers'; + +import SpacesIcon from '../../../icons/Spaces.svg'; +import TwitterIcon from '../../../icons/twitterVector.svg'; +import CopyIcon from '../../../icons/copyVector.svg'; +import AtIcon from '../../../icons/atVector.svg'; +import { SpaceDTO } from '@pushprotocol/restapi'; +import { useSpaceData } from '../../../hooks'; +import { useEffect } from 'react'; + +interface ScheduledWidgetContentProps { + account?: string; + spaceData?: SpaceDTO; + shareUrl?: string; + + // temp props only for testing demo purpose for now + isHost?: boolean; + isTimeToStartSpace?: boolean; + isMember?: boolean; +} +export const ScheduledWidgetContent: React.FC = ({ + account, + spaceData, + shareUrl, + isHost, + isMember, +}: ScheduledWidgetContentProps) => { + const isTimeToStartSpace = true; + const { spacesObjectRef, initSpaceObject, spaceObjectData } = useSpaceData(); + + //Initialize the space object + + const handleStartSpace = async () => { + await initSpaceObject(spaceData?.spaceId as string); + await spacesObjectRef.current.createAudioStream(); + // Start the space by calling the start method on the space object + + console.log('Space Started'); + }; + + const handleShareTweet = () => { + if (!shareUrl) return; + const url = shareUrl; + const tweetText = 'Join this Space:'; // Replace with your desired tweet text + + const tweetUrl = `https://twitter.com/intent/tweet?text=${encodeURIComponent( + tweetText + )}&url=${encodeURIComponent(url)}`; + + window.open(tweetUrl, '_blank'); + }; + + const handleCopyLink = async () => { + try { + if (!shareUrl) return; + const url = shareUrl; + await navigator.clipboard.writeText(url); + // add a success toast here + console.log('URL copied to clipboard:', url); + } catch (error) { + console.error('Failed to copy URL:', error); + } + }; + + useEffect(() => { + async function startSpace() { + if (!spaceObjectData?.connectionData?.local.stream) return; + await spacesObjectRef.current.start({ + livepeerApiKey: '2638ace1-0a3a-4853-b600-016e6125b9bc', + }); + } + startSpace(); + }, [spaceObjectData?.connectionData?.local.stream]); + + return ( + + Spaces Icon + {isHost ? ( + isTimeToStartSpace ? ( + It’s time to start your space + ) : ( + + Your space is scheduled.
Share and let people know when to + join! +
+ ) + ) : ( + + This space will go live on{' '} + {formatDate((spaceData?.scheduleAt as any) || new Date())} + + )} + {isHost && isTimeToStartSpace && ( + + )} + {!isHost && !isMember && ( + + )} + {!isHost && isMember && ( + + )} + {(!isHost || (isHost && !isTimeToStartSpace)) && shareUrl && ( + + + + Twitter Icon + + + Twitter + + + + + Copy Icon + + + Copy Link + + + + + At Icon + + + Email + + + + )} +
+ ); +}; + +const SpaceInfoText = styled.span` + font-size: 18px; + font-weight: 600; + text-align: center; +`; + +const ShareLinkItem = styled.div` + display: flex; + flex-direction: column; + gap: 8px; + align-items: center; +`; + +const ShareLinkButton = styled.button` + background: #e4e4e7; + border-radius: 14px; + padding: 16px; + border: none; + cursor: pointer; +`; diff --git a/packages/uiweb/src/lib/components/space/SpaceWidget/SpaceMembersSectionModal.tsx b/packages/uiweb/src/lib/components/space/SpaceWidget/SpaceMembersSectionModal.tsx new file mode 100644 index 000000000..a1c43966b --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceWidget/SpaceMembersSectionModal.tsx @@ -0,0 +1,256 @@ +import React, { ReactNode, useState } from 'react'; +import styled from 'styled-components'; + +import { Modal } from '../reusables/Modal'; +import { ModalHeader } from '../reusables/ModalHeader'; +import { ProfileContainer } from '../reusables/ProfileContainer'; + +import { Button, Container, Image, Text } from '../../../config'; +import SettingsIcon from '../../../icons/settingsBlack.svg'; + +const tempImageUrl = "https://imgv3.fotor.com/images/blog-richtext-image/10-profile-picture-ideas-to-make-you-stand-out.jpg"; +const Requests: React.FC = () => { + return ( + + + + + ) +} + +const Speakers: React.FC = () => { + return ( + + + + + Settings icon + + + + + + Settings icon + + + + ) +} + +const CoHosts: React.FC = () => { + return ( + + + + + Settings icon + + + + + + Settings icon + + + + ) +} + +const Listeners: React.FC = () => { + return ( + + + + + Settings icon + + + + + + Settings icon + + + + ) +} + +interface ISpaceMembersModalProps { + onClose: () => void; +} +enum MemberTabsEnum { + CoHost = 'Co-Host', + Speakers = 'Speakers', + Requests = 'Requests', + Listeners = 'Listeners', +} + +export const SpaceMembersSectionModal: React.FC = ({ onClose }: ISpaceMembersModalProps) => { + + const [activeTab, setActiveTab] = useState(MemberTabsEnum.CoHost); + + const handleTabClick = (index: MemberTabsEnum) => { + setActiveTab(index); + }; + + const renderTabs = (): ReactNode => { + return Object.values(MemberTabsEnum).map((tab) => ( + handleTabClick(tab)} + > + {tab} + + )); + }; + + return ( + + + + + + + + {renderTabs()} + + + {activeTab === MemberTabsEnum.CoHost && } + {activeTab === MemberTabsEnum.Speakers && } + {activeTab === MemberTabsEnum.Requests && } + {activeTab === MemberTabsEnum.Listeners && } + + + + + + ) +} + +/* styling */ +// const ButtonContainer = styled.div` +// display: flex; +// justify-content: space-between; +// width: 100%; +// `; +const SpacesMembersContainer = styled.div` + color: black; + display: flex; + flex-direction: column; + margin-top: 28px; + gap: 16px; + width: 100%; +`; + +const ProfileWithSettingsContainer = styled.div` + display: flex; + justify-content: space-between; +`; + +const SettingsIconContainer = styled.div` + display: flex; + margin: 0px 16px; + align-items: center; + cursor: pointer; +` + +const TabContainer = styled.div` + display: flex; + padding: 0px 10px; +`; + +const Tab = styled.div<{active: boolean}>` + flex: 1; + padding: 10px; + text-align: center; + border-bottom: ${(props) => + props.active ? '1px solid #8B5CF6' : '1px solid #82828A26'}; + cursor: pointer; + color: ${(props) => (props.active ? '#8B5CF6' : '#82828A')}; +`; diff --git a/packages/uiweb/src/lib/components/space/SpaceWidget/SpaceWidget.tsx b/packages/uiweb/src/lib/components/space/SpaceWidget/SpaceWidget.tsx new file mode 100644 index 000000000..67e1e1487 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceWidget/SpaceWidget.tsx @@ -0,0 +1,142 @@ +import React, { MouseEventHandler, useEffect, useState } from 'react'; +import styled from 'styled-components'; +import { SpaceDTO } from '@pushprotocol/restapi'; +import * as PushAPI from '@pushprotocol/restapi'; + +import { WidgetContent } from './WidgetContent'; +import { WidgetHeader } from './WidgetHeader'; + +import { ISpaceWidgetProps } from '../exportedTypes'; +import { isLiveSpace, isHostOfSpace, isMemberOfSpace } from './helpers/utils'; + +import { useSpaceData } from '../../../hooks'; + +const DEFAULT_OFFSET = 16; +const DEFAULT_MAXWIDTH = 415; + +export const SpaceWidget: React.FC = ( + options: ISpaceWidgetProps +) => { + const { + bottomOffset = DEFAULT_OFFSET, + rightOffset = DEFAULT_OFFSET, + width, + zIndex = 1000, + spaceId, + shareUrl, + onClose = (() => { + /** */ + }) as MouseEventHandler, + isJoined, + isTimeToStartSpace, + } = options || {}; + const [widgetHidden, setWidgetHidden] = useState(!spaceId); + const { account, spaceObjectData, initSpaceObject, env } = useSpaceData(); + + const [isMinimized, setIsMinimized] = useState(false); + const { getSpaceInfo, setSpaceInfo } = useSpaceData(); + const [spaceData, setSpaceData] = useState(); + + useEffect(() => { + if (!spaceId) { + return; + } + setWidgetHidden(!spaceId); + const fetchData = async () => { + try { + if (getSpaceInfo(spaceId)) { + setSpaceData(getSpaceInfo(spaceId)); + return; + } + const response = await PushAPI.space.get({ spaceId, env }); + setSpaceInfo(spaceId, response); + setSpaceData(response); + } catch (error) { + console.error(error); + } + }; + + fetchData(); + }, [spaceId]); + + useEffect(() => { + (async () => { + if (!spaceData) { + return; + } + if (isLiveSpace(spaceData as SpaceDTO)) { + await initSpaceObject(spaceData?.spaceId as string); + } + })(); + }, [spaceData]); + + const isLive = isLiveSpace(spaceData as SpaceDTO); + const isHost = isHostOfSpace(account, spaceData as SpaceDTO); + const isMember = isMemberOfSpace(account, spaceData as SpaceDTO); + + const toggleWidgetVisibility = () => { + setWidgetHidden(!widgetHidden); + }; + + // Implement the SpaceWidget component + return ( + + ); +}; + +interface WidgetContainerProps { + bottomOffset: number; + rightOffset: number; + width?: number; + zIndex?: number; + hidden: boolean; +} + +const Container = styled.div` + font-family: 'Strawford'; // update to fontFamily theme + border-radius: 12px; // update acc to theme + border: 1px solid #dcdcdf; // update acc to theme + display: flex; + flex-direction: column; + width: ${(props) => (props.width ? `${props.width}px` : 'auto')}; + max-width: ${(props) => + props.width ? `${props.width}px` : `${DEFAULT_MAXWIDTH}px`}; + min-width: 320px; + background: white; + justify-content: flex-start; + position: fixed; + bottom: ${(props) => props.bottomOffset}px; + right: ${(props) => props.rightOffset}px; + visibility: ${(props) => (props.hidden ? 'hidden' : 'visible')}; + opacity: ${(props) => (props.hidden ? 0 : 1)}; + transition: opacity 0.3s ease; + z-index: ${(props) => props.zIndex ?? '1000'}; + overflow: hidden; +`; diff --git a/packages/uiweb/src/lib/components/space/SpaceWidget/SpacesInfo.tsx b/packages/uiweb/src/lib/components/space/SpaceWidget/SpacesInfo.tsx new file mode 100644 index 000000000..15a363597 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceWidget/SpacesInfo.tsx @@ -0,0 +1,124 @@ +import React, { useContext, MouseEventHandler } from 'react' +import styled from 'styled-components'; + +import { Modal } from '../reusables/Modal' +import { ModalHeader } from '../reusables/ModalHeader' +import { IThemeProviderProps, ThemeContext } from '../theme/ThemeProvider'; +import { Button } from '../reusables/Button'; +import { ProfileContainer } from '../reusables/ProfileContainer'; +import Accordion from '../reusables/Accordion'; + +export interface ISpacesInfoProps { + closeSpacesInfo: MouseEventHandler; +} + +interface IThemeProps { + theme: IThemeProviderProps; +} + +export const SpacesInfo: React.FC = (props) => { + const tempImageUrl = "https://imgv3.fotor.com/images/blog-richtext-image/10-profile-picture-ideas-to-make-you-stand-out.jpg"; + + const theme = useContext(ThemeContext); + + const customStyle = { + color: theme.textColorPrimary, + background: theme.bgColorPrimary, + borderColor: theme.borderColor, + fontWeight: '500', + padding: '14px', + } + + const TEMP_MEMBERS = [ + { + handle: 's4m4', + name: 'Samarendra' + }, + { + handle: 'aamsa', + name: 'Aam Saltman' + }, + { + handle: 's4m4', + name: 'Samarendra' + }, + { + handle: 'aamsa', + name: 'Aam Saltman' + }, + ] + + return ( + + + + + + + + larryscruff's space + Ac orci quam cras in placerat. Sollicitudin tristique sed nisi proin duis. + + + + + + { + TEMP_MEMBERS.map((item) => { + return + }) + } + + + + + + + ) +} + + +/** styling */ +const SpacesInfoContainer = styled.div` + color: black; +`; + +const SpacesDetailsContainer = styled.div` + padding: 0 16px; + margin: 24px 0; +`; + +const Title = styled.div` + font-weight: 500; +`; + +const Description = styled.div` + color: ${(props => props.theme.textColorSecondary)}; +`; \ No newline at end of file diff --git a/packages/uiweb/src/lib/components/space/SpaceWidget/VideoPlayer.tsx b/packages/uiweb/src/lib/components/space/SpaceWidget/VideoPlayer.tsx new file mode 100644 index 000000000..3156b2065 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceWidget/VideoPlayer.tsx @@ -0,0 +1,25 @@ +import { IMediaStream } from '@pushprotocol/restapi'; +import React, { useEffect, useRef } from 'react'; +import styled from 'styled-components'; + +export interface IVideoPlayerProps { + videoCallData: IMediaStream; +} + +export const VideoPlayer: React.FC = ({ videoCallData }) => { + const incomingVideoRef = useRef(null); + + useEffect(() => { + if (!incomingVideoRef.current) return; + const video = incomingVideoRef.current; + video.srcObject = videoCallData; + video.play(); + }, [incomingVideoRef, videoCallData]); + + return ; +}; + +const Video = styled.video` + height:0; + width:0; +}`; diff --git a/packages/uiweb/src/lib/components/space/SpaceWidget/WidgetContent.tsx b/packages/uiweb/src/lib/components/space/SpaceWidget/WidgetContent.tsx new file mode 100644 index 000000000..50e9d5ce7 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceWidget/WidgetContent.tsx @@ -0,0 +1,75 @@ +import React from 'react'; +import styled from 'styled-components'; + +import { LiveWidgetContent } from './LiveWidgetContent'; +import { ScheduledWidgetContent } from './ScheduledWidgetContent'; +import { SpaceDTO } from '@pushprotocol/restapi'; + +const LIVE_WIDGET_CONTENT_FIXED_HEIGHT = '485px'; +const SCHEDULED_WIDGET_CONTENT_FIXED_HEIGHT = '350px'; + +interface WidgetContentProps { + account?: string; //Temp Prop to Test Host functionality + spaceData?: SpaceDTO; + shareUrl?: string; + isMinimized: boolean; + + // temp props only for testing demo purpose for now + isHost?: boolean; + isLive?: boolean; + isJoined?: boolean; + isTimeToStartSpace?: boolean; + isMember?: boolean; +} +export const WidgetContent: React.FC = ({ + account, + spaceData, + shareUrl, + isLive, + isHost, + isJoined, + isTimeToStartSpace, + isMember, + isMinimized, +}: WidgetContentProps) => { + return ( + + {isLive ? ( + + ) : ( + + )} + + ); +}; + +//styles +const Container = styled.div<{ height: string; isMinimized: boolean }>` + display: flex; + flex-direction: column; + border-bottom: ${(props) => props.theme.border}; + + height: ${(props) => (props.isMinimized ? '0' : props.height)}; + transition: height 200ms ease-out; + overflow: hidden; + + align-items: center; + justify-content: space-between; +`; diff --git a/packages/uiweb/src/lib/components/space/SpaceWidget/WidgetHeader.tsx b/packages/uiweb/src/lib/components/space/SpaceWidget/WidgetHeader.tsx new file mode 100644 index 000000000..49a50b71e --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceWidget/WidgetHeader.tsx @@ -0,0 +1,211 @@ +import React, { useState, MouseEventHandler, useContext } from 'react'; +import styled from 'styled-components'; + +import { Item, Text } from '../../../config'; +import { formatDate } from '../../../helpers'; + +import SettingsIcon from '../../../icons/settings.svg'; +import CaretDownIcon from '../../../icons/CaretDown.svg'; +import CaretUpIcon from '../../../icons/CaretUp.svg'; +import CalendarIcon from '../../../icons/calendar.svg'; +import LiveIcon from '../../../icons/live.svg'; +import { CloseSvg } from '../../../icons/CloseSvg'; +import { HostPfpContainer, ParticipantContainer } from '../reusables'; +import { SpacesInfo } from './SpacesInfo'; +import { ThemeContext } from '../theme/ThemeProvider'; + +export interface IWidgetHeaderProps { + onClose: MouseEventHandler; + spaceData?: any; + isMinimized: boolean; + setIsMinimized: React.Dispatch>; + toggleWidgetVisibility: () => void; + + // temp props + isLive?: boolean; + isHost?: boolean; +} + +export const WidgetHeader: React.FC = ({ + onClose, + isMinimized, + isHost, + isLive, + setIsMinimized, + toggleWidgetVisibility, + spaceData, +}: IWidgetHeaderProps) => { + const theme = useContext(ThemeContext); + + const tempImageUrl = + 'https://imgv3.fotor.com/images/blog-richtext-image/10-profile-picture-ideas-to-make-you-stand-out.jpg'; + + const [isSpacesInfoVisible, setIsSpacesInfoVisible] = useState(false); + const handleCloseWidget: React.MouseEventHandler = ( + event + ) => { + // Call for hiding the widget + toggleWidgetVisibility(); + + // Call for running onClose handler from prop + onClose(event); + }; + + const showSpacesInfo = () => { + setIsSpacesInfoVisible(!isSpacesInfoVisible); + console.log(isSpacesInfoVisible); + }; + + const closeSpacesInfo = () => { + setIsSpacesInfoVisible(false); + }; + + return ( + + {!isLive && ( +
+ + + + + {isHost && } + + Settings icon + + + setIsMinimized(!isMinimized)} + src={isMinimized ? CaretUpIcon : CaretDownIcon} + alt="Maximize/Minimize icon" + /> + + + + + +
+ )} +
+ + {spaceData?.spaceName || 'Test Space'} + + {isLive && ( + + + Settings icon + + + setIsMinimized(!isMinimized)} + src={isMinimized ? CaretUpIcon : CaretDownIcon} + alt="Maximize/Minimize icon" + /> + + + + + + )} +
+ {!isLive && ( + + Calendar Icon + + {formatDate(spaceData?.scheduleAt || new Date())} + + + )} + {isLive && ( +
+ + Calendar Icon + + Live + + + + + + + {/* + +190 Listeners + */} + +
+ )} + {isSpacesInfoVisible ? ( + + ) : null} +
+ ); +}; + +//styles +const Container = styled.div` + display: flex; + flex-direction: column; + color: ${(props) => props.theme.titleTextColor}; + padding: 16px 24px; + background: ${(props) => props.theme.titleBg}; +`; + +const Image = styled.img` + display: flex; + max-height: initial; + vertical-align: middle; + overflow: initial; + cursor: pointer; + height: ${(props: any): string => props.height || '24px'}; + width: ${(props: any): string => props.width || '20px'}; + align-self: center; +`; + +const Section = styled.div<{ marginTop?: string }>` + display: flex; + justify-content: space-between; + margin-top: ${(props) => props.marginTop}; +`; + +const Button = styled.button<{ + padding?: string; + color?: string; +}>` + padding: ${(props) => props.padding ?? '0px'}; + color: ${(props) => props.color ?? 'inherit'}; + margin-left: 10px; + background: rgba(255, 255, 255, 0.2); + border-radius: 6px; + border: none; + cursor: pointer; +`; diff --git a/packages/uiweb/src/lib/components/space/SpaceWidget/helpers/utils.ts b/packages/uiweb/src/lib/components/space/SpaceWidget/helpers/utils.ts new file mode 100644 index 000000000..bc518b603 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceWidget/helpers/utils.ts @@ -0,0 +1,31 @@ +import { SpaceDTO } from '@pushprotocol/restapi'; +import { getSpaceStatus } from '../../helpers/space'; + +export const isHostOfSpace = (account: string, spaceData: SpaceDTO) => { + return ( + account.toUpperCase() === spaceData?.spaceCreator.slice(7).toUpperCase() + ); +}; + +export const isMemberOfSpace = (account: string, spaceData: SpaceDTO) => { + const isMemberArr = spaceData?.members.filter( + (member) => member.wallet.slice(7).toUpperCase() === account.toUpperCase() + ); + return isMemberArr?.length > 0; +}; + +export const isLiveSpace = (spaceData: SpaceDTO) => { + return getSpaceStatus(spaceData?.status) === 'Live'; +}; + +export const isTimeToStart = (spaceData: SpaceDTO, now: Date) => { + const isScheduled = spaceData?.status === 'PENDING'; + const scheduledTime = spaceData?.scheduleAt as Date; + + //true 15 min before scheduledTime + if (scheduledTime && isScheduled) { + return now.getTime() >= new Date(scheduledTime).getTime() - 15 * 60 * 1000; + } else { + return false; + } +}; diff --git a/packages/uiweb/src/lib/components/space/SpaceWidget/index.ts b/packages/uiweb/src/lib/components/space/SpaceWidget/index.ts new file mode 100644 index 000000000..06fa7de30 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpaceWidget/index.ts @@ -0,0 +1 @@ +export * from "./SpaceWidget"; \ No newline at end of file diff --git a/packages/uiweb/src/lib/components/space/SpacesUI.tsx b/packages/uiweb/src/lib/components/space/SpacesUI.tsx new file mode 100644 index 000000000..0db6e0989 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/SpacesUI.tsx @@ -0,0 +1,78 @@ +import React, { useEffect, useState } from 'react'; + +import { ISpaceBannerProps, SpaceBanner } from './SpaceBanner'; +import { SpaceWidget } from './SpaceWidget'; +import { ISpaceFeedProps, SpaceFeed } from './SpaceFeed'; +import { ISpaceInvitesProps, SpaceInvites } from './SpaceInvites'; +import { SpaceCreationWidget } from './SpaceCreationWidget'; + +import { SignerType } from '../../types'; +import { ENV } from '../../config'; +import { useSpaceData } from '../../hooks'; +import { ISpacesUIProps, ISpaceWidgetProps } from './exportedTypes'; + +export class SpacesUI { + public account: string; + public signer: SignerType; + public pgpPrivateKey: string; + public env: ENV; + + constructor(props: ISpacesUIProps) { + this.account = props.account; + this.signer = props.signer; + this.pgpPrivateKey = props.pgpPrivateKey; + this.env = props.env; + } + + SpaceBanner: React.FC = (options: ISpaceBannerProps) => { + const { spaceInfo, setSpaceInfo } = useSpaceData(); + + // Use spaceBannerData and setSpaceBannerData in your component + + return ; + }; + + SpaceWidget: React.FC = (options: ISpaceWidgetProps) => { + const { spaceId } = options; + const { spaceWidgetId } = useSpaceData(); + const [SpaceId, setSpaceId] = useState(spaceId); + + useEffect(() => { + setSpaceId(spaceId); + }, [spaceId, setSpaceId]); + + useEffect(() => { + setSpaceId(spaceWidgetId); + }, [spaceWidgetId, setSpaceId]); + + return ; + } + + SpaceFeed: React.FC = (options: ISpaceFeedProps) => { + return ; + }; + + SpaceInvites: React.FC = (options: ISpaceInvitesProps) => { + return ; + }; + + SpaceCreationButtonWidget = () => { + return + } + + connectToSockets = () => { + // Connect to sockets and listen for events + // Update spaceBannerData or trendingListData based on events + const { setSpaceInfo, setTrendingListData } = useSpaceData(); + + // Example of updating spaceBannerData + //setSpaceBannerData(); + }; + + init = () => { + // Initialization logic + + // Call connectToSockets or any other initialization tasks + this.connectToSockets(); + }; +} diff --git a/packages/uiweb/src/lib/components/space/exportedTypes.ts b/packages/uiweb/src/lib/components/space/exportedTypes.ts new file mode 100644 index 000000000..9c4aaf140 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/exportedTypes.ts @@ -0,0 +1,30 @@ +import { MouseEventHandler } from "react"; + +import { ENV } from "../../config"; +import { SignerType } from "../../types"; + +export interface ISpacesUIProps { + account: string; + signer: SignerType; + pgpPrivateKey: string; + env: ENV; +} + +export interface ISpaceWidgetProps { + // Add props specific to the SpaceWidget class method + account?: string; + bottomOffset?: number; + rightOffset?: number; + zIndex?: number; + spaceId?: string; + width?: number; + shareUrl?: string; + onClose?: MouseEventHandler; + + // props only for testing demo purpose for now + isHost?: boolean; + isLive?: boolean; + isJoined?: boolean; + isTimeToStartSpace? :boolean; + isMember?: boolean; +} diff --git a/packages/uiweb/src/lib/components/space/helpers/date.ts b/packages/uiweb/src/lib/components/space/helpers/date.ts new file mode 100644 index 000000000..fc9bcd62a --- /dev/null +++ b/packages/uiweb/src/lib/components/space/helpers/date.ts @@ -0,0 +1,48 @@ +/** + * Get Date and Time in Day. + * @param {string | Date} datestring - The JavaScript Date String or Date Object. + * @returns {string} - The Date and Time in Day, DD Month at HH:MM AM format. + */ + +export function getDateAndTime(datestring: string | Date) { + const date = new Date(datestring); + + //Day of Week + const dayOfWeek = date.getDay(); + const weekdays = [ + 'Sunday', + 'Monday', + 'Tuesday', + 'Wednesday', + 'Thursday', + 'Friday', + 'Saturday', + ]; + const weekday = weekdays[dayOfWeek]; + + //Date + const day = date.getDate(); + const monthIndex = date.getMonth(); + const months = [ + 'January', + 'February', + 'March', + 'April', + 'May', + 'June', + 'July', + 'August', + 'September', + 'October', + 'November', + 'December', + ]; + const month = months[monthIndex]; + + //Time + const amOrPm = date.getHours() >= 12 ? 'PM' : 'AM'; + const hour = amOrPm === 'PM' ? date.getHours() % 12 : date.getHours(); + const minute = date.getMinutes(); + + return `${weekday}, ${day} ${month} at ${hour}:${minute} ${amOrPm}`; + } diff --git a/packages/uiweb/src/lib/components/space/helpers/space.ts b/packages/uiweb/src/lib/components/space/helpers/space.ts new file mode 100644 index 000000000..57eb76703 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/helpers/space.ts @@ -0,0 +1,12 @@ +/** + * Get Status of the Space. + * @param {string | Date} datestring - The JavaScript Date String or Date Object. + * @returns {string} - The Status of the Space. + */ + +export type ISpaceStatus = 'Live' | 'Scheduled' | 'Ended'; +export function getSpaceStatus(status: any): ISpaceStatus { + if (status === 'ACTIVE') return 'Live'; + if (status === 'PENDING') return 'Scheduled'; + return 'Ended'; +} diff --git a/packages/uiweb/src/lib/components/space/index.ts b/packages/uiweb/src/lib/components/space/index.ts new file mode 100644 index 000000000..6d9bc714a --- /dev/null +++ b/packages/uiweb/src/lib/components/space/index.ts @@ -0,0 +1,15 @@ +import { ISpaceBannerProps } from "./SpaceBanner"; +import { ISpaceFeedProps } from "./SpaceFeed"; +import { SpacesUI } from "./SpacesUI"; +import { ISpaceInvitesProps } from "./SpaceInvites"; +import { ISpaceCreateWidgetProps } from "./SpaceCreationWidget"; + +export { + SpacesUI, + ISpaceBannerProps, + ISpaceFeedProps, + ISpaceInvitesProps, + ISpaceCreateWidgetProps +} + +export * from './exportedTypes'; diff --git a/packages/uiweb/src/lib/components/space/reusables/Accordion.tsx b/packages/uiweb/src/lib/components/space/reusables/Accordion.tsx new file mode 100644 index 000000000..d962d5fdd --- /dev/null +++ b/packages/uiweb/src/lib/components/space/reusables/Accordion.tsx @@ -0,0 +1,89 @@ +import React, { useState, useContext } from 'react'; +import styled from 'styled-components'; + +import CaretDownIcon from '../../../icons/CaretDownGrey.svg'; +import CaretUpIcon from '../../../icons/CaretUpGrey.svg'; +import { ThemeContext } from '../theme/ThemeProvider'; + +interface IAccordionProps { + title: string; + items?: number; + children: React.ReactNode; +} + +const Accordion: React.FC = ({ title, items, children }) => { + const theme = useContext(ThemeContext) + + const [isOpen, setIsOpen] = useState(true); + + const toggleAccordion = () => { + setIsOpen((prevIsOpen) => !prevIsOpen); + }; + + return ( + + + + <div>{title}</div> + { items ? <PendingCount theme={theme}>{items}</PendingCount> : null } + + Maximize/Minimize icon + + {children} + + ); +}; + +export default Accordion; + +/* styling */ +const AccordionParent = styled.div` + border: 1px solid #E4E4E7; + border-radius: 8px; + padding: 6.5px 0; + margin: 16px 0; +`; + +const AccordionBody = styled.div<{ isOpen: boolean }>` + overflow-y: scroll; + max-height: ${({ isOpen }) => (isOpen ? '200px' : '0')}; + transition: max-height 200ms ease-out; +`; + +const AccordionTitle = styled.div` + display: flex; + justify-content: space-between; + align-items: center; + + padding: 8px 16px; + + cursor: pointer; +`; + +const Title = styled.div` + display: flex; + align-items: center; +`; + +const PendingCount = styled.div` + background: ${(props => props.theme.btnColorPrimary)}; + border-radius: 8px; + padding: 4px 10px; + margin-left: 6px; + font-size: 13px; + color: ${(props => props.theme.titleTextColor)}; +`; + +const Image = styled.img` + display: flex; + max-height: initial; + vertical-align: middle; + overflow: initial; + cursor: pointer; + height: ${(props: any): string => props.height || '24px'}; + width: ${(props: any): string => props.width || '20px'}; + align-self: center; +`; \ No newline at end of file diff --git a/packages/uiweb/src/lib/components/space/reusables/Button.tsx b/packages/uiweb/src/lib/components/space/reusables/Button.tsx new file mode 100644 index 000000000..8ae710ad7 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/reusables/Button.tsx @@ -0,0 +1,82 @@ +/** + * @file Button + * generic button component for spaces + * Represents the props for the Button component. + * @interface IButtonProps + * @property {string} [width] - The width of the button. Optional. + * @property {React.ReactNode} children - The content of the button. + * @property {React.MouseEventHandler} [onClick] - The click event handler for the button. Optional. + * @property {ISpacesTheme} [theme] - The theme for the button. Optional. + * @property {any} [customStyle] - Custom styles for the button. Optional. + */ + +import { MouseEventHandler, useContext } from 'react' +import styled from 'styled-components'; + +import { ISpacesTheme } from '../theme'; +import { ThemeContext } from '../theme/ThemeProvider'; + +export interface IButtonProps { + width?: string; + height?: string; + children: any; + onClick?: MouseEventHandler; + theme?: ISpacesTheme; + customStyle?: any; +} + +/** + * A button component. + * @function Button + * @param {IButtonProps} props - The props for the Button component. + * @returns {JSX.Element} The rendered Button component. + */ +export const Button: React.FC = (props) => { + const theme = useContext(ThemeContext); + + const { onClick, width, height, customStyle } = props; + + return ( + + { props.children } + + ) +} + +/* styling */ +const SpacesButton = styled.button` + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + padding: ${(props => props.customStyle ? props.customStyle.padding : '10px 16px')}; + margin-top: 12px; + + background: ${(props => props.customStyle ? props.customStyle.background : props.theme.btnColorPrimary)}; + border: 2px solid ${(props => props.customStyle ? props.customStyle.borderColor : props.theme.btnOutline)}; + color: ${(props => props.customStyle ? props.customStyle.color : props.theme.titleTextColor)}; + border-radius: 8px; + font-size: 14px; + font-weight: ${(props => props.customStyle ? props.customStyle.fontWeight : '700')}; + font-family: 'Strawford'; // update to fontFamily theme + + /* Inside auto layout */ + flex: none; + order: 0; + flex-grow: 0; + + transition: 150ms ease-in-out; + + &:hover { + cursor: pointer; + } + + width: ${(props => props.width ? props.width : '100%')}; + height: ${(props => props.height ? props.height : '100%')}; +`; \ No newline at end of file diff --git a/packages/uiweb/src/lib/components/space/reusables/Checkbox.tsx b/packages/uiweb/src/lib/components/space/reusables/Checkbox.tsx new file mode 100644 index 000000000..6bfb07c13 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/reusables/Checkbox.tsx @@ -0,0 +1,18 @@ +export const Checkbox = (props: { + id: string; + label: string; + value?: boolean; + onChange: () => void; +}) => { + return ( +
+ + +
+ ); +}; diff --git a/packages/uiweb/src/lib/components/space/reusables/DateTimePicker.tsx b/packages/uiweb/src/lib/components/space/reusables/DateTimePicker.tsx new file mode 100644 index 000000000..4160b807b --- /dev/null +++ b/packages/uiweb/src/lib/components/space/reusables/DateTimePicker.tsx @@ -0,0 +1,148 @@ +/* eslint-disable prefer-const */ +import React, { useContext, useState, useEffect } from 'react'; +import styled from 'styled-components'; + +import { ThemeContext } from '../theme/ThemeProvider'; + +interface DateTimePickerProps { + propsDate: Date; + propsTime: string; + onDateChange?: any; + onTimeChange?: any; +} + +const DateTimePicker: React.FC = (props) => { + const { + propsDate, onDateChange, onTimeChange, + } = props; + const theme = useContext(ThemeContext); + + const [selectedHours, setSelectedHours] = useState('1'); + const [selectedMinutes, setSelectedMinutes] = useState('0'); + const [selectedAMPM, setSelectedAMPM] = useState('AM'); + const [timeHumanReadable, setTimeHumanReadable] = useState(0); + + const handleDateChange = (event: React.ChangeEvent) => { + const date = new Date(event.target.value); + onDateChange(date); + }; + + const getTime = (hours: number, minutes: number, ampm: string, propsDate: Date) => { + let totalMinutes = hours * 60 + minutes; + + if (ampm === 'PM' && hours !== 12) { + totalMinutes += 12 * 60; + } else if (ampm === 'AM' && hours === 12) { + totalMinutes -= 12 * 60; + } + + const date = new Date(propsDate); + date.setHours(0, 0, 0, 0); + date.setMinutes(totalMinutes); + + return date.getTime(); + }; + + useEffect(() => { + const hours = parseInt(selectedHours, 10); + const minutes = parseInt(selectedMinutes, 10); + const ampm = selectedAMPM; + + const newTimeEpoch = getTime(hours, minutes, ampm, propsDate); + setTimeHumanReadable(newTimeEpoch); + + onTimeChange(newTimeEpoch) + }, [selectedHours, selectedMinutes, selectedAMPM, propsDate]); + + return ( + +
Select date and time
+ + + + + + +
+ ); +}; + +const DateTimeCont = styled.div` + display: flex; + flex-direction: column; + + margin-top: 24px; +`; + +const Input = styled.input` + padding: 16px; + margin-top: 12px; + + width: 330px; + + background: #FFFFFF; + border: 1px solid ${(props => props.theme.btnOutline)}; + box-shadow: -1px -1px 2px ${(props => props.theme.btnOutline)}, 1px 1px 2px ${(props => props.theme.btnOutline)}; + border-radius: 12px; + + font-size: 16px; + font-family: 'Strawford'; +`; + +const TimeContainer = styled.div` + display: flex; + width: 100%; + gap: 12px; +`; + +const Select = styled.select<{ width?: string }>` + padding: 16px; + margin-top: 12px; + + background: #FFFFFF; + border: 1px solid ${(props => props.theme.btnOutline)}; + box-shadow: -1px -1px 2px ${(props => props.theme.btnOutline)}, 1px 1px 2px ${(props => props.theme.btnOutline)}; + border-radius: 12px; + + font-size: 16px; + font-family: 'Strawford'; + width: ${(props => props.width ? props.width : '100%')}; +`; + +export default DateTimePicker; diff --git a/packages/uiweb/src/lib/components/space/reusables/HostPfpContainer.tsx b/packages/uiweb/src/lib/components/space/reusables/HostPfpContainer.tsx new file mode 100644 index 000000000..3c410a760 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/reusables/HostPfpContainer.tsx @@ -0,0 +1,111 @@ +import React from 'react'; +import styled from 'styled-components'; + +export interface IHostPfpContainerProps { + name?: string; + handle?: string; + imageUrl?: string; + statusTheme: "Live" | "Scheduled" | "Ended"; + imageHeight?: string; +} + +export const HostPfpContainer: React.FC = ({ + name = "Host Name", + handle = "Host Handle", + imageUrl = "", + statusTheme, + imageHeight, +}: IHostPfpContainerProps) => { + return ( + + + + + + + {name} + Host + + {handle && + + {/* Fetch the handle from Lenster */}@{handle} + + } + + + ); +}; + +const ProfileContainer = styled.div` + display: flex; + flex-direction: row; + justify-content: space-between; + width: 100%; + align-items: center; +`; + +const PfpContainer = styled.div` + display: flex; +`; + +const Pfp = styled.img<{ imageHeight?: string }>` + height: ${(props) => (props.imageHeight ?? '32px')}; + width: ${(props) => (props.imageHeight ?? '32px')};; + border-radius: 50%; +`; + +const HostContainer = styled.div` + display: flex; + flex-direction: column; + justify-content: center; + align-items: flex-start; + padding-left: 8px; + width: 100%; + overflow: hidden; + text-overflow: ellipsis; +`; + +const HostName = styled.div` + display: flex; + flex-direction: row; + font-weight: 600; + font-size: 15px; + width: 100%; +`; + +const Name = styled.span` + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +`; + +const Host = styled.div<{ statusTheme?: string }>` + display: flex; + flex-direction: row; + align-items: center; + padding: 2px 8px; + margin-left: 8px; + line-height: 18px; + width: max-content; + height: 19px; + background: ${(props) => + props.statusTheme === 'Live' + ? 'rgba(255, 255, 255, 0.2);' + : 'rgba(139, 92, 246, 0.2)'}; + color: ${(props) => (props.statusTheme === 'Live' ? 'inherit' : '#8B5CF6')}; + border-radius: 6px; + font-weight: 500; + font-size: 10px; +`; + +const HostHandle = styled.div<{ statusTheme?: string }>` + color: ${(props) => (props.statusTheme === 'Live' ? '#F5F5F5E5' : '#71717A')}; + padding: 0; + font-weight: 450; + font-size: 14px; + line-height: 130%; + width: 100%; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +`; diff --git a/packages/uiweb/src/lib/components/space/reusables/Modal.tsx b/packages/uiweb/src/lib/components/space/reusables/Modal.tsx new file mode 100644 index 000000000..b45a54949 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/reusables/Modal.tsx @@ -0,0 +1,83 @@ +/** + * @file Modal + * generic modal component for spaces UI + * does not handle any business logic, acts only as a container + */ +import { useRef, useContext } from 'react'; +import styled from 'styled-components' + +import { ThemeContext } from '../theme/ThemeProvider'; + +import { useClickAway } from '../../../hooks'; + +interface IModalProps { + width?: string; + clickawayClose?: () => void; + children: any; +} + +const ClickawayCloseModal = ({ children, clickawayClose, width }: IModalProps) => { + const modalRef = useRef(null); + const theme = useContext(ThemeContext) + + useClickAway(modalRef, () => { + if (clickawayClose) { + clickawayClose(); + } + }); + + return ( + + {children} + + ); +}; + +export const Modal = ({ clickawayClose, children, width }: IModalProps) => { + const theme = useContext(ThemeContext) + return ( + + {clickawayClose ? ( + {children} + ) : ( + + { children } + + )} + + ); +}; + +/* styling */ + +const ModalOverlay = styled.div` + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.4); /* Black with 40% opacity */ + display: flex; + justify-content: center; + align-items: center; +`; + +const ModalParent = styled.div` + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + + display: flex; + flex-direction: column; + align-items: center; + padding: 24px 20px; + + background: ${(props => props.theme.bgColorPrimary)}; + border-radius: 12px; + + width: ${(props => props.width ? props.width : 'auto')}; +`; \ No newline at end of file diff --git a/packages/uiweb/src/lib/components/space/reusables/ModalHeader.tsx b/packages/uiweb/src/lib/components/space/reusables/ModalHeader.tsx new file mode 100644 index 000000000..e6df966a6 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/reusables/ModalHeader.tsx @@ -0,0 +1,101 @@ +import { MouseEventHandler } from 'react'; +import styled from 'styled-components'; + +import { CloseSvg } from '../../../icons/CloseSvg'; +import { ArrowLeft } from '../../../icons/ArrowLeft'; + +export interface IModalHeaderProps { + heading: string; + headingBadgeNumber?: number; + backCallback?: MouseEventHandler; + closeCallback?: MouseEventHandler; +} + +export const ModalHeader = (props: IModalHeaderProps) => { + return ( +
+
+ {props.backCallback ? ( + + + + ) : null} + + + {props.heading} + {props.headingBadgeNumber && {props.headingBadgeNumber}} + + + {props.closeCallback ? ( + + + + ) : null} +
+
+ ); +}; + +/* styling */ +const Header = styled.div` + display: flex; + align-items: center; + width: 100%; + + margin-bottom: 24px; +`; + +const BackBtn = styled.button` + position: absolute; + top: 0; + left: 0; + margin: 1.5rem; + + border: none; + background: transparent; + + &:hover { + cursor: pointer; + } +`; + +const CloseBtn = styled.button` + position: absolute; + top: 0; + right: 0; + margin: 1.5rem; + + border: none; + background: transparent; + + &:hover { + cursor: pointer; + } +`; + +const CenterText = styled.div` + position: absolute; + top: 0; + left: 50%; + transform: translateX(-50%); + margin: 1.5rem 0; + + display: flex; + flex-direction: row; + align-items: center; + + font-weight: 500; +`; + +const NumberBadge = styled.div` + display: flex; + justify-content: center; + align-items: center; + background:#8B5CF6; + color: #fff; + border-radius: 8px; + margin-left: 8px; + padding: 4px 8px; + font-size: 13px; + font-weight: 500; +}`; diff --git a/packages/uiweb/src/lib/components/space/reusables/ParticipantContainer.tsx b/packages/uiweb/src/lib/components/space/reusables/ParticipantContainer.tsx new file mode 100644 index 000000000..789f016ce --- /dev/null +++ b/packages/uiweb/src/lib/components/space/reusables/ParticipantContainer.tsx @@ -0,0 +1,98 @@ +import React from 'react'; +import styled from 'styled-components'; + +export interface IParticipantContainerProps { + participants: any[]; + orientation?: 'maximized' | 'minimized' | 'pill'; + imageHeight?: any; +} + +export const ParticipantContainer: React.FC = ({ + participants, + orientation, + imageHeight, +}) => { + return ( + + + {orientation === 'pill' + ? participants && + participants.map( + (person, index) => + index < 2 && ( + + ) + ) + : participants && + participants.map( + (person, index) => + index < 3 && ( + + ) + )} + + + {orientation === 'pill' + ? participants && (participants.length as number) - 3 > 0 + ? `+${(participants.length as number) - 3}` + : null + : participants && (participants.length as number) - 3 > 0 + ? `+${(participants.length as number) - 3}` + : null} + + + ); +}; + +const Participants = styled.div` + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; +}`; + +const ParticipantsIconContainer = styled.div<{ orientation?: string }>` + display: grid; + grid-template-columns: repeat(5, 1fr); + width: ${(props) => (props.orientation === 'pill' ? '46.5px' : '62px')}; + padding: 0 4px; +}`; + +const ParticipantsIcon = styled.img<{ imageHeight?: any }>` + height: ${(props) => (props.imageHeight ? props.imageHeight : '31px')}; + border-radius: 50%; + + &.index0 { + position: relative; + top: 0; + left: 0; + z-index: 3; + } + &.index1 { + position: relative; + top: 0; + left: -50%; + z-index: 2; + } + &.index2 { + position: relative; + top: 0; + left: -100%; + z-index: 1; + } +}`; + +const ParticipantsText = styled.div` + display: flex; + justify-content: center; + align-items: center; + width: auto; +}`; diff --git a/packages/uiweb/src/lib/components/space/reusables/ProfileContainer.tsx b/packages/uiweb/src/lib/components/space/reusables/ProfileContainer.tsx new file mode 100644 index 000000000..3a0efab98 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/reusables/ProfileContainer.tsx @@ -0,0 +1,194 @@ +import React, { useContext, useState } from 'react'; +import styled from 'styled-components'; +import { ThemeContext } from '../theme/ThemeProvider'; + +export interface IProfileContainerProps { + name?: string; + handle?: string; + imageUrl?: string; + tag?: string; + imageHeight?: string; + border?: boolean; + contBtn?: any; + btnCallback?: any; + removeCallback?: any; + promoteCallback?: any; +} + +export const ProfileContainer: React.FC = ({ + name = "Host Name", + handle = "Host Handle", + imageUrl = "", + tag, + imageHeight, + border = false, + contBtn, + btnCallback, + removeCallback, + promoteCallback, +}: IProfileContainerProps) => { + const theme = useContext(ThemeContext); + + const [isDDOpen, setIsDDOpen] = useState(false) + + const handleDDState = () => { + setIsDDOpen(!isDDOpen) + } + + return ( + + + + + + + + {name} + + {handle && + + {/* Fetch the handle from Lenster */}@{handle} + + } + + { tag ? {tag} : null } + { contBtn ?
{contBtn}
: null } +
+ + { + isDDOpen ? + + + Remove + + + + Make Admin + + + + Close
This Dropdown +
+
+ : null + } +
+ ); +}; + +const ParentContainer = styled.div<{ border?: boolean }>` + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + + position: relative; + + padding: 8px 16px; + + border: ${(props => props.border ? '1px solid #E4E4E7' : 'none')}; + border-radius: 16px; +`; + +const PfpContainer = styled.div` + display: flex; +`; + +const Pfp = styled.img<{ imageHeight?: string }>` + height: ${(props) => (props.imageHeight ?? '32px')}; + width: ${(props) => (props.imageHeight ?? '32px')};; + border-radius: 50%; +`; + +const HostContainer = styled.div` + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + padding-left: 8px; + width: 100%; + overflow: hidden; + text-overflow: ellipsis; +`; + +const ProfileDetails = styled.div` + display: flex; + flex-direction: column; + + flex-grow: 1; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + + width: 200px; +`; + +const HostName = styled.div` + display: flex; + flex-direction: row; + font-weight: 600; + font-size: 15px; + width: 100%; +`; + +const Name = styled.span` + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +`; + +const Host = styled.div` + display: flex; + flex-direction: row; + align-items: center; + margin-left: 8px; + line-height: 18px; + width: max-content; + background: rgba(139, 92, 246, 0.2); + color: #8B5CF6; + border-radius: 6px; + font-weight: 500; + font-size: 12px; + padding: 6px 10px; + border-radius: 8px; +`; + +const HostHandle = styled.div<{ theme?: any }>` + background: ${(props => props.theme.textGradient)}; + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + padding: 0; + font-weight: 450; + font-size: 14px; + line-height: 130%; + width: 100%; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +`; + +const DropDown = styled.div<{ theme?: any }>` + position: absolute; + top: 0px; + right: 0px; + + display: flex; + flex-direction: column; + gap: 12px; + + justify-content: center; + align-items: start; + + padding: 16px; + background: ${(props => props.theme.bgColorPrimary)}; + color: ${(props => props.theme.textColorPrimary)}; + border-radius: 16px; + + border: 1px solid ${(props => props.theme.borderColor)}; +`; + +const DDItem = styled.div` + cursor: pointer; +`; \ No newline at end of file diff --git a/packages/uiweb/src/lib/components/space/reusables/SearchInput.tsx b/packages/uiweb/src/lib/components/space/reusables/SearchInput.tsx new file mode 100644 index 000000000..5f44c25e2 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/reusables/SearchInput.tsx @@ -0,0 +1,76 @@ +import { ChangeEvent, useContext } from 'react'; +import styled from 'styled-components'; + +import { ISpacesTheme } from '../theme'; +import { ThemeContext } from '../theme/ThemeProvider'; + +import { CloseSvg } from '../../../icons/CloseSvg'; + +export interface ISearchInputProps { + labelName?: string; + inputValue?: string; + onInputChange?: any; + clearInput?: any; +} + +export const SearchInput = (props: ISearchInputProps) => { + const theme = useContext(ThemeContext); + + const handleChange = (event: ChangeEvent) => { + props.onInputChange(event); + }; + + return ( + + + + + + + + + + + + ); +}; + +/* styling */ +const InputContainer = styled.div` + display: flex; + flex-direction: column; + + margin: 16px 0; + + font-family: 'Strawford'; // update to fontFamily theme +`; + +const LabelContainer = styled.div` + display: flex; + justify-content: space-between; + + font-weight: 500; +`; + +const Input = styled.input` + padding: 16px; + margin-top: 12px; + + width: 330px; + + background: #FFFFFF; + border: 1px solid ${(props => props.theme.btnOutline)}; + box-shadow: -1px -1px 2px ${(props => props.theme.btnOutline)}, 1px 1px 2px ${(props => props.theme.btnOutline)}; + border-radius: 12px; +`; + +const InputWrapper = styled.div` + position: relative; +`; + +const CloseBtn = styled.div` + position: absolute; + right: 0; + top: 0; + padding: 1.75rem 0.75rem; +`; \ No newline at end of file diff --git a/packages/uiweb/src/lib/components/space/reusables/Spinner.tsx b/packages/uiweb/src/lib/components/space/reusables/Spinner.tsx new file mode 100644 index 000000000..d635de040 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/reusables/Spinner.tsx @@ -0,0 +1,35 @@ +import React, { useContext } from 'react'; +import styled, { keyframes } from 'styled-components'; +import { SpinnerSvg } from '../../../icons/SpinnerSvg'; + +type SpinnerPropType = { + size?: string; +}; + +type SpinLoaderPropType = { + width?: string; +}; + +export const Spinner: React.FC = ({ size = 42 }) => { + return ( + + + + ); +}; + +//styles +const spinAnimation = keyframes` + from { transform:rotate(0deg); } + to { transform:rotate(360deg); } +`; +const SpinLoader = styled.div` + display: flex; + flex: initial; + align-self: center; + width: ${(props) => props.width}; + animation-name: ${spinAnimation}; + animation-duration: 2500ms; + animation-iteration-count: infinite; + animation-timing-function: linear; +`; diff --git a/packages/uiweb/src/lib/components/space/reusables/TextInput.tsx b/packages/uiweb/src/lib/components/space/reusables/TextInput.tsx new file mode 100644 index 000000000..d87d90a2d --- /dev/null +++ b/packages/uiweb/src/lib/components/space/reusables/TextInput.tsx @@ -0,0 +1,71 @@ +import React, { ChangeEvent, useContext } from 'react'; +import styled from 'styled-components'; + +import { ISpacesTheme } from '../theme'; +import { ThemeContext } from '../theme/ThemeProvider'; + +export interface ITextInputProps { + charCount: number; + labelName?: string; + inputValue: string; + onInputChange: any; +} + +export const TextInputWithCounter = (props: ITextInputProps) => { + const theme = useContext(ThemeContext); + + const handleChange = (event: ChangeEvent) => { + const newText = event.target.value; + const count = newText.length; + + if (count <= props.charCount) { + props.onInputChange(event); + } + }; + + return ( + + + + {props.inputValue.length} / {props.charCount} + + + + ); +}; + +/* styling */ +const InputContainer = styled.div` + display: flex; + flex-direction: column; + + margin: 16px 0; + + font-family: 'Strawford'; // update to fontFamily theme +`; + +const LabelContainer = styled.div` + display: flex; + justify-content: space-between; + + font-weight: 500; +`; + +const Input = styled.input` + padding: 16px; + margin-top: 12px; + + width: 330px; + + background: #FFFFFF; + border: 1px solid ${(props => props.theme.btnOutline)}; + box-shadow: -1px -1px 2px ${(props => props.theme.btnOutline)}, 1px 1px 2px ${(props => props.theme.btnOutline)}; + border-radius: 12px; + + font-family: 'Strawford'; // update to fontFamily theme + font-size: 14px; +`; + +const CharCounter = styled.div` + color: ${(props => props.theme.textColorSecondary)}; +`; \ No newline at end of file diff --git a/packages/uiweb/src/lib/components/space/reusables/index.ts b/packages/uiweb/src/lib/components/space/reusables/index.ts new file mode 100644 index 000000000..b9a75a085 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/reusables/index.ts @@ -0,0 +1,2 @@ +export * from './HostPfpContainer'; +export * from './ParticipantContainer'; diff --git a/packages/uiweb/src/lib/components/space/theme/ThemeProvider.tsx b/packages/uiweb/src/lib/components/space/theme/ThemeProvider.tsx new file mode 100644 index 000000000..999c6e8d1 --- /dev/null +++ b/packages/uiweb/src/lib/components/space/theme/ThemeProvider.tsx @@ -0,0 +1,19 @@ +/** + * @file ThemeProvider.tsx: This acts as the custom theme provider for the entire app. + */ +import { createContext } from 'react'; + +import { ISpacesTheme, lightTheme } from './index'; + +/** + * @param theme optional: light or dark theme. defaults to light + * @param customTheme optional: custom colors/theme + * @param children children to be wrapped with ThemeProvider + */ +export interface IThemeProviderProps { + theme?: 'light' | 'dark'; + customTheme?: Partial; + children: any; +} + +export const ThemeContext = createContext(lightTheme); diff --git a/packages/uiweb/src/lib/components/space/theme/index.ts b/packages/uiweb/src/lib/components/space/theme/index.ts new file mode 100644 index 000000000..99c70253e --- /dev/null +++ b/packages/uiweb/src/lib/components/space/theme/index.ts @@ -0,0 +1,58 @@ +/** + * @file theme file: all the predefined themes are defined here + */ + +export interface ISpacesTheme { + titleBg?: string; + titleTextColor?: string; + bgColorPrimary?: string; + bgColorSecondary?: string; + textColorPrimary?: string; + textColorSecondary?: string; + textGradient?: string; + btnColorPrimary?: string; + btnOutline?: string; + borderColor?: string; + borderRadius?: string; + containerBorderRadius?: string; + statusColorError?: string; + statusColorSuccess?: string; + iconColorPrimary?: string; + fontFamily?: string; +} + +export const lightTheme: ISpacesTheme = { + titleBg: 'linear-gradient(87.17deg, #EA4EE4 0%, #D23CDF 0.01%, #8B5CF6 100%)', + titleTextColor: '#fff', + bgColorPrimary: '#fff', + bgColorSecondary: '#EDE9FE', + textColorPrimary: '#000', + textColorSecondary: '#71717A', + textGradient: 'linear-gradient(45deg, #B6A0F5, #F46EF6, #FFDED3, #FFCFC5)', + btnColorPrimary: '#8B5CF6', + btnOutline: '#8B5CF6', + borderColor: '#DCDCDF', + borderRadius: '17px', + containerBorderRadius: '12px', + statusColorError: '#E93636', + statusColorSuccess: '#30CC8B', + iconColorPrimary: '#82828A' +}; + +export const darkTheme: ISpacesTheme = { + titleBg: 'linear-gradient(87.17deg, #EA4EE4 0%, #D23CDF 0.01%, #8B5CF6 100%)', + titleTextColor: '#fff', + bgColorPrimary: '#000', + bgColorSecondary: '#292344', + textColorPrimary: '#fff', + textColorSecondary: '#71717A', + textGradient: 'linear-gradient(45deg, #B6A0F5, #F46EF6, #FFDED3, #FFCFC5)', + btnColorPrimary: '#8B5CF6', + btnOutline: '#8B5CF6', + borderColor: '#3F3F46', + borderRadius: '17px', + containerBorderRadius: '12px', + statusColorError: '#E93636', + statusColorSuccess: '#30CC8B', + iconColorPrimary: '#71717A' +}; diff --git a/packages/uiweb/src/lib/config/index.ts b/packages/uiweb/src/lib/config/index.ts index c53ff8b53..6068abaca 100644 --- a/packages/uiweb/src/lib/config/index.ts +++ b/packages/uiweb/src/lib/config/index.ts @@ -1,2 +1,3 @@ export * from './constants'; -export * from './themisation'; \ No newline at end of file +export * from './themisation'; +export * from './styles'; \ No newline at end of file diff --git a/packages/uiweb/src/lib/config/styles.tsx b/packages/uiweb/src/lib/config/styles.tsx new file mode 100644 index 000000000..7bbce9aa6 --- /dev/null +++ b/packages/uiweb/src/lib/config/styles.tsx @@ -0,0 +1,75 @@ +import React from 'react'; +import styled, { css } from 'styled-components'; + +interface CommonStyles extends React.CSSProperties { + // Add any additional custom style properties here + customProperty?: string; // random for now +} + +const commonStyle = css` + display: ${(props) => props.display}; + position: ${(props) => props.position}; + background: ${(props) => props.background}; + color: ${(props) => props.color}; + cursor: ${(props) => props.cursor}; + flex: ${(props) => props.flex}; + flex-direction: ${(props) => props.flexDirection}; + flex-wrap: ${(props) => props.flexWrap}; + gap: ${(props) => props.gap}; + align-self: ${(props) => props.alignSelf}; + align-items: ${(props) => props.alignItems}; + align-content: ${(props) => props.alignContent}; + justify-content: ${(props) => props.justifyContent}; + padding: ${(props) => props.padding}; + margin: ${(props) => props.margin}; + margin-top: ${(props) => props.marginTop}; + margin-left: ${(props) => props.marginLeft}; + margin-right: ${(props) => props.marginRight}; + margin-bottom: ${(props) => props.marginBottom}; + min-width: ${(props) => props.minWidth}; + max-width: ${(props) => props.maxWidth}; + overflow-y: ${(props) => props.overflowY}; + font-size: ${(props) => props.fontSize}; + font-weight: ${(props) => props.fontWeight}; + text-align: ${(props) => props.textAlign}; + filter: ${(props) => props.filter}; + box-shadow: ${(props) => props.boxShadow}; + top: ${(props) => props.top}; + bottom: ${(props) => props.bottom}; + left: ${(props) => props.left}; + right: ${(props) => props.right}; + width: ${(props) => props.width}; + height: ${(props) => props.height}; + border: ${(props) => props.border}; + border-radius: ${(props) => props.borderRadius}; + overflow: ${(props) => props.overflow}; + z-index: ${(props) => props.zIndex}; +`; + +export const Item = styled.div` + ${commonStyle} +`; + +export const Anchor = styled.a` + ${commonStyle} +`; + +export const Container = styled.div` + ${commonStyle} +`; + +export const Image = styled.img` + ${commonStyle} +`; + +export const Heading = styled.h1` + ${commonStyle} +`; + +export const Button = styled.button` + ${commonStyle} +`; + +export const Text = styled.span` + ${commonStyle} +`; \ No newline at end of file diff --git a/packages/uiweb/src/lib/context/index.ts b/packages/uiweb/src/lib/context/index.ts index 5b023c5a2..38bc1f881 100644 --- a/packages/uiweb/src/lib/context/index.ts +++ b/packages/uiweb/src/lib/context/index.ts @@ -1,7 +1,9 @@ import ChatPropsContext from "./chatPropsContext"; import ChatMainStateContext from "./chatMainStateContext"; +import { SpaceDataContext } from "./spacesContext"; export { ChatPropsContext, - ChatMainStateContext + ChatMainStateContext, + SpaceDataContext }; \ No newline at end of file diff --git a/packages/uiweb/src/lib/context/spacesContext.ts b/packages/uiweb/src/lib/context/spacesContext.ts new file mode 100644 index 000000000..285fdfb2a --- /dev/null +++ b/packages/uiweb/src/lib/context/spacesContext.ts @@ -0,0 +1,113 @@ +import React, { createContext } from 'react'; +import * as PushAPI from '@pushprotocol/restapi'; +import { SpaceDTO, SpaceIFeeds } from '@pushprotocol/restapi'; +import { SignerType } from '../types'; +import { ENV } from '../config'; + +export interface ISpaceInfo { + [key: string]: SpaceDTO; +} + +export interface ISpacePaginationData { + apiData?: SpaceIFeeds[]; + currentPage?: number; + lastPage?: number; +} + +export interface ISpaceDataContextValues { + account: string; + setAccount: React.Dispatch>; + signer: SignerType | undefined; + setSigner: React.Dispatch>; + pgpPrivateKey: string; + setPgpPrivateKey: React.Dispatch>; + env: ENV; + setEnv: React.Dispatch>; + trendingListData: any; + setTrendingListData: React.Dispatch>; + spaceInfo: ISpaceInfo; + setSpaceInfo: (key: string, value: SpaceDTO) => void; + getSpaceInfo: (key: string) => SpaceDTO | undefined; + spaceWidgetId: string; + setSpaceWidgetId: React.Dispatch>; + mySpaces: ISpacePaginationData; + setMySpaces: (paginationData: ISpacePaginationData) => void; + popularSpaces: ISpacePaginationData; + setPopularSpaces: (paginationData: ISpacePaginationData) => void; + spaceRequests: ISpacePaginationData; + setSpaceRequests: (paginationData: ISpacePaginationData) => void; + spaceObjectData: PushAPI.SpaceData; + setSpaceObjectData: (data: any) => void; + initSpaceObject: (data: any) => Promise; + spacesObjectRef: React.MutableRefObject; +} + +export const initialSpaceDataContextValues: ISpaceDataContextValues = { + account: '', + setAccount: () => { + /**/ + }, + signer: undefined, + setSigner: () => { + /**/ + }, + pgpPrivateKey: '', + setPgpPrivateKey: () => { + /**/ + }, + env: ENV.DEV, + setEnv: () => { + /**/ + }, + trendingListData: null, + setTrendingListData: () => { + /**/ + }, + spaceInfo: {} as ISpaceInfo, + setSpaceInfo: () => { + /**/ + }, + getSpaceInfo: () => undefined, + spaceWidgetId: '', + setSpaceWidgetId: () => { + /**/ + }, + mySpaces: { + apiData: [] as SpaceIFeeds[], + currentPage: 1, + lastPage: 2, + } as ISpacePaginationData, + setMySpaces: () => { + /**/ + }, + popularSpaces: { + apiData: [] as SpaceIFeeds[], + currentPage: 1, + lastPage: 2, + } as ISpacePaginationData, + setPopularSpaces: () => { + /**/ + }, + spaceRequests: { + apiData: [] as SpaceIFeeds[], + currentPage: 1, + lastPage: 2, + } as ISpacePaginationData, + setSpaceRequests: () => { + /**/ + }, + spaceObjectData: {} as PushAPI.SpaceData, + setSpaceObjectData: () => { + /**/ + }, + initSpaceObject: async () => { + /**/ + }, + spacesObjectRef: { + current: null, + } as React.MutableRefObject, +}; + +export const SpaceDataContext = createContext( + initialSpaceDataContextValues +); diff --git a/packages/uiweb/src/lib/dataProviders/SpaceDataProvider.tsx b/packages/uiweb/src/lib/dataProviders/SpaceDataProvider.tsx new file mode 100644 index 000000000..4ea53ea27 --- /dev/null +++ b/packages/uiweb/src/lib/dataProviders/SpaceDataProvider.tsx @@ -0,0 +1,222 @@ +import { useEffect, useRef, useState } from 'react'; +import { SignerType, SpaceDTO, SpaceIFeeds } from '@pushprotocol/restapi'; + +import { SpacesUI } from '../components'; +import { ThemeContext } from '../components/space/theme/ThemeProvider'; +import { ISpacesTheme, lightTheme } from '../components/space/theme'; +import { + ISpaceDataContextValues, + ISpaceInfo, + ISpacePaginationData, + SpaceDataContext, +} from '../context/spacesContext'; +import { ENV } from '../config'; + +import * as PushAPI from '@pushprotocol/restapi'; +import { useSpaceNotificationSocket } from '../hooks'; + +export interface ISpacesUIProviderProps { + spaceUI: SpacesUI; + theme: ISpacesTheme; + children: React.ReactNode; +} + +export const SpacesUIProvider = ({ + spaceUI, + theme, + children, +}: ISpacesUIProviderProps) => { + const spacesObjectRef = useRef({} as PushAPI.space.Space); + const [account, setAccount] = useState(spaceUI.account); + const [signer, setSigner] = useState(spaceUI.signer); + const [pgpPrivateKey, setPgpPrivateKey] = useState( + spaceUI.pgpPrivateKey + ); + const [env, setEnv] = useState(spaceUI.env); + const [spaceWidgetId, setSpaceWidgetId] = useState(''); + + const [trendingListData, setTrendingListData] = useState(null); + const [spaceInfo, setSpaceInfo] = useState({} as ISpaceInfo); + const [spaceObjectData, setSpaceObjectData] = useState( + PushAPI.space.initSpaceData + ); + + const [mySpaces, setMySpaces] = useState({ + apiData: [] as SpaceIFeeds[], + currentPage: 1, + lastPage: 2, + } as ISpacePaginationData); + + const [popularSpaces, setPopularSpaces] = useState({ + apiData: [] as SpaceIFeeds[], + currentPage: 1, + lastPage: 2, + } as ISpacePaginationData); + + const [spaceRequests, setSpaceRequests] = useState({ + apiData: [] as SpaceIFeeds[], + currentPage: 1, + lastPage: 2, + } as ISpacePaginationData); + + const setSpaceInfoItem = (key: string, value: SpaceDTO): void => { + setSpaceInfo((prevState) => ({ + ...prevState, + [key]: value, + })); + }; + + const initSpaceObject = async (spaceId: string) => { + spacesObjectRef.current = new PushAPI.space.Space({ + signer, + pgpPrivateKey, + address: account, + chainId: 5, // TODO: Make this dynamic + env, + setSpaceData: setSpaceObjectData, + }); + await spacesObjectRef.current.initialize({ spaceId }); + }; + + const getSpaceInfo = (spaceId: string): SpaceDTO | undefined => { + return spaceInfo[spaceId]; + }; + + const setMySpacePaginationInfo = ( + paginationInfo: ISpacePaginationData + ): void => { + const { apiData, currentPage, lastPage } = paginationInfo; + setMySpaces((prevState) => { + if (apiData) { + const existingIds = new Set( + prevState.apiData?.map((space: SpaceIFeeds) => space.spaceId) + ); + console.log('Existing ID', existingIds); + const uniqueSpaces = apiData?.filter( + (space) => !existingIds.has(space.spaceId) + ); + console.log('Unique Spaces', uniqueSpaces); + return { + ...prevState, + ...(uniqueSpaces && + prevState.apiData && { + apiData: [...prevState.apiData, ...uniqueSpaces], + }), + }; + } + return { + ...prevState, + ...(currentPage && { currentPage }), + ...(lastPage && { lastPage }), + }; + }); + }; + + const setPopularSpacePaginationInfo = ( + paginationInfo: ISpacePaginationData + ): void => { + const { apiData, currentPage, lastPage } = paginationInfo; + setPopularSpaces((prevState) => { + if (apiData) { + const existingIds = new Set( + prevState.apiData?.map((space: SpaceIFeeds) => space.spaceId) + ); + console.log('Existing ID', existingIds); + const uniqueSpaces = apiData?.filter( + (space) => !existingIds.has(space.spaceId) + ); + console.log('Unique Spaces', uniqueSpaces); + return { + ...prevState, + ...(uniqueSpaces && + prevState.apiData && { + apiData: [...prevState.apiData, ...uniqueSpaces], + }), + }; + } + return { + ...prevState, + ...(currentPage && { currentPage }), + ...(lastPage && { lastPage }), + }; + }); + }; + + const setSpacesRequestPaginationInfo = ( + paginationInfo: ISpacePaginationData + ): void => { + const { apiData, currentPage, lastPage } = paginationInfo; + setSpaceRequests((prevState) => { + if (apiData) { + const existingIds = new Set( + prevState.apiData?.map((space: SpaceIFeeds) => space.spaceId) + ); + console.log('Existing ID', existingIds); + const uniqueSpaces = apiData?.filter( + (space) => !existingIds.has(space.spaceId) + ); + console.log('Unique Spaces', uniqueSpaces); + return { + ...prevState, + ...(uniqueSpaces && + prevState.apiData && { + apiData: [...prevState.apiData, ...uniqueSpaces], + }), + }; + } + return { + ...prevState, + ...(currentPage && { currentPage }), + ...(lastPage && { lastPage }), + }; + }); + }; + + const value: ISpaceDataContextValues = { + account, + setAccount, + signer, + setSigner, + pgpPrivateKey, + setPgpPrivateKey, + env, + setEnv, + trendingListData, + setTrendingListData, + spaceInfo, + setSpaceInfo: setSpaceInfoItem, + getSpaceInfo, + spaceWidgetId, + setSpaceWidgetId, + mySpaces, + setMySpaces: setMySpacePaginationInfo, + popularSpaces, + setPopularSpaces: setPopularSpacePaginationInfo, + spaceRequests, + setSpaceRequests: setSpacesRequestPaginationInfo, + spaceObjectData, + setSpaceObjectData, + initSpaceObject, + spacesObjectRef, + }; + + useEffect(() => { + setAccount(spaceUI.account); + setSigner(spaceUI.signer); + setEnv(spaceUI.env); + setPgpPrivateKey(spaceUI.pgpPrivateKey); + }, [spaceUI]); + + const PROVIDER_THEME = Object.assign({}, lightTheme, theme); + + spaceUI.init(); + useSpaceNotificationSocket({ account, env }); + + return ( + + + {children} + + + ); +}; diff --git a/packages/uiweb/src/lib/dataProviders/index.ts b/packages/uiweb/src/lib/dataProviders/index.ts new file mode 100644 index 000000000..bf7f090a8 --- /dev/null +++ b/packages/uiweb/src/lib/dataProviders/index.ts @@ -0,0 +1 @@ +export * from "./SpaceDataProvider"; \ No newline at end of file diff --git a/packages/uiweb/src/lib/helpers/apiHelper.ts b/packages/uiweb/src/lib/helpers/apiHelper.ts new file mode 100644 index 000000000..c33e9d6d5 --- /dev/null +++ b/packages/uiweb/src/lib/helpers/apiHelper.ts @@ -0,0 +1,9 @@ +export const pollAPI = async (fetchData: () => Promise, interval: number): Promise => { + try { + await fetchData(); + setTimeout(() => pollAPI(fetchData, interval), interval); + } catch (error) { + console.error('Error polling API:', error); + // Handle error if needed + } +}; diff --git a/packages/uiweb/src/lib/helpers/date.ts b/packages/uiweb/src/lib/helpers/date.ts new file mode 100644 index 000000000..c1a7357e5 --- /dev/null +++ b/packages/uiweb/src/lib/helpers/date.ts @@ -0,0 +1,6 @@ +import moment from 'moment'; + +export const formatDate = (date: number): string => { + const formattedDate = moment(date).format('Do MMM [at] h:mm A'); + return formattedDate; +} \ No newline at end of file diff --git a/packages/uiweb/src/lib/helpers/index.ts b/packages/uiweb/src/lib/helpers/index.ts index be1114040..c5872881b 100644 --- a/packages/uiweb/src/lib/helpers/index.ts +++ b/packages/uiweb/src/lib/helpers/index.ts @@ -1,2 +1,4 @@ export * from "./chat"; -export * from "./address"; \ No newline at end of file +export * from "./address"; +export * from "./apiHelper"; +export * from "./date"; \ No newline at end of file diff --git a/packages/uiweb/src/lib/hooks/index.ts b/packages/uiweb/src/lib/hooks/index.ts index d83772c74..52d121727 100644 --- a/packages/uiweb/src/lib/hooks/index.ts +++ b/packages/uiweb/src/lib/hooks/index.ts @@ -1,2 +1,3 @@ export * from './useClickAway'; -export * from './useChatScroll'; \ No newline at end of file +export * from './useChatScroll'; +export * from "./space"; \ No newline at end of file diff --git a/packages/uiweb/src/lib/hooks/space/index.ts b/packages/uiweb/src/lib/hooks/space/index.ts new file mode 100644 index 000000000..dc53136ff --- /dev/null +++ b/packages/uiweb/src/lib/hooks/space/index.ts @@ -0,0 +1,7 @@ +export * from './useSpaceData'; +export * from './useGetSpaceInfo'; +export * from './usePopularSpaces'; +export * from './useMySpaces'; +export * from './useSpaceRequests'; +export * from './useFeedScroll'; +export * from './useSpaceNotificationSocket'; diff --git a/packages/uiweb/src/lib/hooks/space/useFeedScroll.ts b/packages/uiweb/src/lib/hooks/space/useFeedScroll.ts new file mode 100644 index 000000000..b589f37c5 --- /dev/null +++ b/packages/uiweb/src/lib/hooks/space/useFeedScroll.ts @@ -0,0 +1,13 @@ +import React from 'react'; + +export const useFeedScroll = ( + dep: T, +): React.MutableRefObject => { + const ref = React.useRef(null); + React.useEffect(() => { + if (ref.current) { + ref.current.scrollTop = 0; + } + }, []); + return ref; +}; \ No newline at end of file diff --git a/packages/uiweb/src/lib/hooks/space/useGetSpaceInfo.ts b/packages/uiweb/src/lib/hooks/space/useGetSpaceInfo.ts new file mode 100644 index 000000000..1e50445c6 --- /dev/null +++ b/packages/uiweb/src/lib/hooks/space/useGetSpaceInfo.ts @@ -0,0 +1,37 @@ +import { useContext, useEffect, useState } from 'react'; +import * as PushAPI from '@pushprotocol/restapi'; +import { + ISpaceDataContextValues, + SpaceDataContext, +} from '../../context/spacesContext'; +import { SpaceDTO } from '@pushprotocol/restapi'; +import { ENV } from '../../config'; + +export const useGetSpaceInfo = (spaceId: string): SpaceDTO | undefined => { + const { getSpaceInfo, setSpaceInfo, env }: ISpaceDataContextValues = + useContext(SpaceDataContext); + const [spaceData, setSpaceDataState] = useState( + getSpaceInfo(spaceId) + ); + + useEffect(() => { + if (!spaceId) { + return; + } + const fetchData = async () => { + if (!spaceData) { + try { + const response = await PushAPI.space.get({ spaceId, env }); + setSpaceInfo(spaceId, response); + setSpaceDataState(response); + } catch (error) { + console.error(error); + } + } + }; + + fetchData(); + }, [spaceId, spaceData, getSpaceInfo, setSpaceInfo]); + + return spaceData; +}; diff --git a/packages/uiweb/src/lib/hooks/space/useMySpaces.ts b/packages/uiweb/src/lib/hooks/space/useMySpaces.ts new file mode 100644 index 000000000..d78de24ff --- /dev/null +++ b/packages/uiweb/src/lib/hooks/space/useMySpaces.ts @@ -0,0 +1,44 @@ +import { useSpaceData } from './useSpaceData'; +import { useEffect, useState } from 'react'; + +import * as PushAPI from '@pushprotocol/restapi'; + +export const useMySpaces = (account?: string) => { + const LIMIT = 10; + + const { mySpaces, setMySpaces, env } = useSpaceData(); + const [loading, setLoading] = useState(false); + + const fetchMySpaces = async () => { + if (!account) return; + setLoading(true); + try { + const res = await PushAPI.space.spaces({ + account: account, + page: mySpaces.currentPage, + limit: LIMIT, + env, + }); + + const newMySpaces = res; + + if (newMySpaces.length === 0) { + setMySpaces({ lastPage: -1 }); + setLoading(false); + return; + } + if (newMySpaces.length > 0) { + setMySpaces({ apiData: newMySpaces }); + } + } catch (error) { + console.error('Error while fetching Spaces For You:', error); + } + setLoading(false); + }; + + useEffect(() => { + fetchMySpaces(); + }, [mySpaces.currentPage]); + + return { loading }; +}; diff --git a/packages/uiweb/src/lib/hooks/space/usePopularSpaces.ts b/packages/uiweb/src/lib/hooks/space/usePopularSpaces.ts new file mode 100644 index 000000000..2f6fcb7b1 --- /dev/null +++ b/packages/uiweb/src/lib/hooks/space/usePopularSpaces.ts @@ -0,0 +1,41 @@ +import { useSpaceData } from './useSpaceData'; +import { useEffect, useState } from 'react'; + +import * as PushAPI from '@pushprotocol/restapi'; + +export const usePopularSpaces = () => { + const LIMIT = 10; + const { popularSpaces, setPopularSpaces, env } = useSpaceData(); + const [loading, setLoading] = useState(false); + + const fetchPopularSpaces = async () => { + setLoading(true); + try { + const res = await PushAPI.space.trending({ + page: popularSpaces.currentPage, + limit: LIMIT, + env + }); + + const newPopularSpaces = res; + + if (newPopularSpaces.length === 0) { + setPopularSpaces({ lastPage: -1 }); + setLoading(false); + return; + } + if (newPopularSpaces.length > 0) { + setPopularSpaces({ apiData: newPopularSpaces }); + } + } catch (error) { + console.error('Error while fetching popular spaces:', error); + } + setLoading(false); + }; + + useEffect(() => { + fetchPopularSpaces(); + }, [popularSpaces.currentPage]); + + return { loading }; +}; diff --git a/packages/uiweb/src/lib/hooks/space/useSpaceData.ts b/packages/uiweb/src/lib/hooks/space/useSpaceData.ts new file mode 100644 index 000000000..e1e00a93e --- /dev/null +++ b/packages/uiweb/src/lib/hooks/space/useSpaceData.ts @@ -0,0 +1,11 @@ +import { useContext } from "react"; +import { ISpaceDataContextValues } from "../../context/spacesContext"; +import { SpaceDataContext } from "../../context"; + +export const useSpaceData = (): ISpaceDataContextValues => { + const context = useContext(SpaceDataContext); + if (!context) { + throw new Error('useSpaceData must be used within a SpaceDataProvider'); + } + return context; +} \ No newline at end of file diff --git a/packages/uiweb/src/lib/hooks/space/useSpaceNotificationSocket.ts b/packages/uiweb/src/lib/hooks/space/useSpaceNotificationSocket.ts new file mode 100644 index 000000000..95ebe1cb1 --- /dev/null +++ b/packages/uiweb/src/lib/hooks/space/useSpaceNotificationSocket.ts @@ -0,0 +1,141 @@ +import { useCallback, useEffect, useState } from 'react'; +import { createSocketConnection, EVENTS } from '@pushprotocol/socket'; +import * as PushAPI from '@pushprotocol/restapi'; +import { useSpaceData } from './useSpaceData'; +import { ENV } from '../../config'; + +const NOTIFICATION_SOCKET_TYPE = 'notification'; + +export type SDKSocketHookOptions = { + account?: string | null; + env?: ENV; +}; + +export const useSpaceNotificationSocket = ({ + account, + env = ENV.PROD, +}: SDKSocketHookOptions) => { + const { spacesObjectRef } = useSpaceData(); + + const [notificationSocket, setNotificationSocket] = useState(null); + const [isNotificationSocketConnected, setIsNotificationSocketConnected] = + useState(false); + + const addSocketEvents = useCallback(() => { + notificationSocket?.on(EVENTS.CONNECT, () => { + setIsNotificationSocketConnected(true); + }); + + notificationSocket?.on(EVENTS.DISCONNECT, () => { + setIsNotificationSocketConnected(false); + }); + + notificationSocket?.on(EVENTS.USER_FEEDS, (feedItem: any) => { + const { payload } = feedItem; + + if ( + payload?.data?.additionalMeta?.type === + `${PushAPI.payloads.ADDITIONAL_META_TYPE.PUSH_VIDEO}+1` + ) { + const { + status, + callDetails, + senderAddress, + recipientAddress, + signalData, + chatId: spaceId, + }: PushAPI.video.VideoDataType = JSON.parse( + payload.data.additionalMeta.data + ); + + if (status === PushAPI.VideoCallStatus.INITIALIZED) { + if ( + callDetails?.type === + PushAPI.payloads.SPACE_REQUEST_TYPE.JOIN_SPEAKER + ) { + // @Nilesh + // host has started the space and is asking speakers to join in (real-time) + // we need to store the receivedSpaceData.signalData, chatId -> spaceId + // so that we can use then when the speaker wants to join the space from space invites + } + if ( + callDetails?.type === + PushAPI.payloads.SPACE_REQUEST_TYPE.ESTABLISH_MESH + ) { + spacesObjectRef.current?.acceptRequest({ + signalData, + senderAddress: recipientAddress, + recipientAddress: senderAddress, + chatId: spaceId, + }); + } + } + if (status === PushAPI.VideoCallStatus.RECEIVED) { + spacesObjectRef.current?.connect({ + signalData, + peerAddress: senderAddress, + }); + } + if (status === PushAPI.VideoCallStatus.DISCONNECTED) { + if(callDetails?.type === PushAPI.payloads.SPACE_DISCONNECT_TYPE.LEAVE){ + // later -> the 'senderAddress' has left the space + } + if(callDetails?.type === PushAPI.payloads.SPACE_DISCONNECT_TYPE.STOP){ + // later -> space has been ended by the host + } + } + } + }); + }, [notificationSocket]); + + const removeSocketEvents = useCallback(() => { + notificationSocket?.off(EVENTS.CONNECT); + notificationSocket?.off(EVENTS.DISCONNECT); + notificationSocket?.off(EVENTS.USER_FEEDS); + }, [notificationSocket]); + + useEffect(() => { + if (notificationSocket) { + addSocketEvents(); + } + + return () => { + if (notificationSocket) { + removeSocketEvents(); + } + }; + }, [addSocketEvents, notificationSocket, removeSocketEvents]); + + /** + * Whenever the requisite params to create a connection object change + * - disconnect the old connection + * - create a new connection object + */ + useEffect(() => { + if (account) { + if (notificationSocket) { + // console.log('=================>>> disconnection in the hook'); + notificationSocket?.disconnect(); + } + const main = async () => { + const connectionObject = createSocketConnection({ + user: account, + env, + socketType: NOTIFICATION_SOCKET_TYPE, + socketOptions: { autoConnect: true, reconnectionAttempts: 3 }, + }); + console.warn('new connection object: ', connectionObject); + + setNotificationSocket(connectionObject); + }; + main().catch((err) => console.error(err)); + } + + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [account, env]); + + return { + notificationSocket, + isNotificationSocketConnected, + }; +}; diff --git a/packages/uiweb/src/lib/hooks/space/useSpaceRequests.ts b/packages/uiweb/src/lib/hooks/space/useSpaceRequests.ts new file mode 100644 index 000000000..b9c67c0a7 --- /dev/null +++ b/packages/uiweb/src/lib/hooks/space/useSpaceRequests.ts @@ -0,0 +1,45 @@ +import { useSpaceData } from './useSpaceData'; +import { useEffect, useState } from 'react'; + +import * as PushAPI from '@pushprotocol/restapi'; + +export const useSpaceRequests = (account?: string) => { + const LIMIT = 2; + + const { spaceRequests, setSpaceRequests, env } = useSpaceData(); + const [loading, setLoading] = useState(false); + + const fetchSpaceRequests = async () => { + if (!account) return; + setLoading(true); + try { + const res = await PushAPI.space.requests({ + account: account, + page: spaceRequests.currentPage, + limit: LIMIT, + env, + + }); + + const newSpaceRequests = res; + + if (newSpaceRequests.length === 0) { + setSpaceRequests({ lastPage: -1 }); + setLoading(false); + return; + } + if (newSpaceRequests.length > 0) { + setSpaceRequests({ apiData: newSpaceRequests }); + } + } catch (error) { + console.error('Error while fetching spaces requests:', error); + } + setLoading(false); + }; + + useEffect(() => { + fetchSpaceRequests(); + }, [spaceRequests.currentPage]); + + return { loading }; +}; diff --git a/packages/uiweb/src/lib/hooks/useChatScroll.ts b/packages/uiweb/src/lib/hooks/useChatScroll.ts index d7f7a90ad..f02209c2c 100644 --- a/packages/uiweb/src/lib/hooks/useChatScroll.ts +++ b/packages/uiweb/src/lib/hooks/useChatScroll.ts @@ -6,7 +6,7 @@ export const useChatScroll = ( const ref = React.useRef(null); React.useEffect(() => { if (ref.current) { - ref.current.scrollTop = ref.current.scrollHeight; + ref.current.scrollTop = 0; } }, [dep]); return ref; diff --git a/packages/uiweb/src/lib/icons/ArrowLeft.svg b/packages/uiweb/src/lib/icons/ArrowLeft.svg new file mode 100644 index 000000000..de2987515 --- /dev/null +++ b/packages/uiweb/src/lib/icons/ArrowLeft.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/uiweb/src/lib/icons/ArrowLeft.tsx b/packages/uiweb/src/lib/icons/ArrowLeft.tsx new file mode 100644 index 000000000..54b4153aa --- /dev/null +++ b/packages/uiweb/src/lib/icons/ArrowLeft.tsx @@ -0,0 +1,9 @@ +export const ArrowLeft = () => { + return ( + + + + + ); + }; + \ No newline at end of file diff --git a/packages/uiweb/src/lib/icons/CalendarPurple.tsx b/packages/uiweb/src/lib/icons/CalendarPurple.tsx new file mode 100644 index 000000000..a3e4f8524 --- /dev/null +++ b/packages/uiweb/src/lib/icons/CalendarPurple.tsx @@ -0,0 +1,28 @@ +import React from 'react'; + +export const CalendarPurple = ({ height, width }: { height?: string, width?: string }) => { + return ( + < svg + width={width || "15"} + height={height || "14"} + viewBox = "0 0 15 14" + fill = "none" + xmlns = "http://www.w3.org/2000/svg" + > + + + + ); +}; diff --git a/packages/uiweb/src/lib/icons/CaretDown.svg b/packages/uiweb/src/lib/icons/CaretDown.svg new file mode 100644 index 000000000..6b3c3561b --- /dev/null +++ b/packages/uiweb/src/lib/icons/CaretDown.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/uiweb/src/lib/icons/CaretDownGrey.svg b/packages/uiweb/src/lib/icons/CaretDownGrey.svg new file mode 100644 index 000000000..a450775da --- /dev/null +++ b/packages/uiweb/src/lib/icons/CaretDownGrey.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/uiweb/src/lib/icons/CaretUp.svg b/packages/uiweb/src/lib/icons/CaretUp.svg new file mode 100644 index 000000000..852d9acae --- /dev/null +++ b/packages/uiweb/src/lib/icons/CaretUp.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/uiweb/src/lib/icons/CaretUpGrey.svg b/packages/uiweb/src/lib/icons/CaretUpGrey.svg new file mode 100644 index 000000000..43b353b05 --- /dev/null +++ b/packages/uiweb/src/lib/icons/CaretUpGrey.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/uiweb/src/lib/icons/CloseSvg.tsx b/packages/uiweb/src/lib/icons/CloseSvg.tsx index 2bf81b330..cf42abfe7 100644 --- a/packages/uiweb/src/lib/icons/CloseSvg.tsx +++ b/packages/uiweb/src/lib/icons/CloseSvg.tsx @@ -1,25 +1,25 @@ import React from 'react'; -export const CloseSvg = () => { +export const CloseSvg = ({ stroke, height, width }: { stroke?: string, height?: string, width?: string }) => { return ( + + + + + diff --git a/packages/uiweb/src/lib/icons/MicEngage.svg b/packages/uiweb/src/lib/icons/MicEngage.svg new file mode 100644 index 000000000..2118ce9d3 --- /dev/null +++ b/packages/uiweb/src/lib/icons/MicEngage.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/uiweb/src/lib/icons/Minimize.tsx b/packages/uiweb/src/lib/icons/Minimize.tsx new file mode 100644 index 000000000..cf42abfe7 --- /dev/null +++ b/packages/uiweb/src/lib/icons/Minimize.tsx @@ -0,0 +1,29 @@ +import React from 'react'; + +export const CloseSvg = ({ stroke, height, width }: { stroke?: string, height?: string, width?: string }) => { + return ( + + + + + ); +}; diff --git a/packages/uiweb/src/lib/icons/Muted.svg b/packages/uiweb/src/lib/icons/Muted.svg new file mode 100644 index 000000000..a68158636 --- /dev/null +++ b/packages/uiweb/src/lib/icons/Muted.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/uiweb/src/lib/icons/Share.svg b/packages/uiweb/src/lib/icons/Share.svg new file mode 100644 index 000000000..dd69beae1 --- /dev/null +++ b/packages/uiweb/src/lib/icons/Share.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/packages/uiweb/src/lib/icons/Spaces.svg b/packages/uiweb/src/lib/icons/Spaces.svg new file mode 100644 index 000000000..529ef17e0 --- /dev/null +++ b/packages/uiweb/src/lib/icons/Spaces.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/packages/uiweb/src/lib/icons/atVector.svg b/packages/uiweb/src/lib/icons/atVector.svg new file mode 100644 index 000000000..b4aa5c9bf --- /dev/null +++ b/packages/uiweb/src/lib/icons/atVector.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/uiweb/src/lib/icons/calendar.svg b/packages/uiweb/src/lib/icons/calendar.svg new file mode 100644 index 000000000..769c7e11c --- /dev/null +++ b/packages/uiweb/src/lib/icons/calendar.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/packages/uiweb/src/lib/icons/calendarPurple.svg b/packages/uiweb/src/lib/icons/calendarPurple.svg new file mode 100644 index 000000000..fde94df20 --- /dev/null +++ b/packages/uiweb/src/lib/icons/calendarPurple.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/uiweb/src/lib/icons/checkIcon.svg b/packages/uiweb/src/lib/icons/checkIcon.svg new file mode 100644 index 000000000..f8d7fc7cb --- /dev/null +++ b/packages/uiweb/src/lib/icons/checkIcon.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/uiweb/src/lib/icons/copyVector.svg b/packages/uiweb/src/lib/icons/copyVector.svg new file mode 100644 index 000000000..6f780bb22 --- /dev/null +++ b/packages/uiweb/src/lib/icons/copyVector.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/uiweb/src/lib/icons/filter.svg b/packages/uiweb/src/lib/icons/filter.svg new file mode 100644 index 000000000..2ac3e870f --- /dev/null +++ b/packages/uiweb/src/lib/icons/filter.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/uiweb/src/lib/icons/hand.svg b/packages/uiweb/src/lib/icons/hand.svg new file mode 100644 index 000000000..422d49f54 --- /dev/null +++ b/packages/uiweb/src/lib/icons/hand.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/packages/uiweb/src/lib/icons/live.svg b/packages/uiweb/src/lib/icons/live.svg new file mode 100644 index 000000000..5cf6ae8c8 --- /dev/null +++ b/packages/uiweb/src/lib/icons/live.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/packages/uiweb/src/lib/icons/micoff.svg b/packages/uiweb/src/lib/icons/micoff.svg new file mode 100644 index 000000000..ad6e4f143 --- /dev/null +++ b/packages/uiweb/src/lib/icons/micoff.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/uiweb/src/lib/icons/micon.svg b/packages/uiweb/src/lib/icons/micon.svg new file mode 100644 index 000000000..80cd7a2a1 --- /dev/null +++ b/packages/uiweb/src/lib/icons/micon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/packages/uiweb/src/lib/icons/scheduled.svg b/packages/uiweb/src/lib/icons/scheduled.svg new file mode 100644 index 000000000..63b3495d0 --- /dev/null +++ b/packages/uiweb/src/lib/icons/scheduled.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/packages/uiweb/src/lib/icons/settings.svg b/packages/uiweb/src/lib/icons/settings.svg new file mode 100644 index 000000000..9510b8a01 --- /dev/null +++ b/packages/uiweb/src/lib/icons/settings.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/packages/uiweb/src/lib/icons/settingsBlack.svg b/packages/uiweb/src/lib/icons/settingsBlack.svg new file mode 100644 index 000000000..0ffa8bc28 --- /dev/null +++ b/packages/uiweb/src/lib/icons/settingsBlack.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/packages/uiweb/src/lib/icons/twitterVector.svg b/packages/uiweb/src/lib/icons/twitterVector.svg new file mode 100644 index 000000000..4be66ead6 --- /dev/null +++ b/packages/uiweb/src/lib/icons/twitterVector.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/uiweb/src/lib/index.ts b/packages/uiweb/src/lib/index.ts index 816c837a9..85d2f4cb9 100644 --- a/packages/uiweb/src/lib/index.ts +++ b/packages/uiweb/src/lib/index.ts @@ -1,3 +1,4 @@ export * from './components' export * from './config'; +export * from './dataProviders'; export * from './types'; \ No newline at end of file diff --git a/packages/uiweb/yarn.lock b/packages/uiweb/yarn.lock index ee4c9abcb..cc99d5ead 100644 --- a/packages/uiweb/yarn.lock +++ b/packages/uiweb/yarn.lock @@ -2,11 +2,459 @@ # yarn lockfile v1 +"@babel/runtime@^7.13.10": + version "7.22.6" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.6.tgz#57d64b9ae3cff1d67eb067ae117dac087f5bd438" + integrity sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ== + dependencies: + regenerator-runtime "^0.13.11" + +"@floating-ui/core@^1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.3.1.tgz#4d795b649cc3b1cbb760d191c80dcb4353c9a366" + integrity sha512-Bu+AMaXNjrpjh41znzHqaz3r2Nr8hHuHZT6V2LBKMhyMl0FgKA62PNYbqnfgmzOhoWZj70Zecisbo4H1rotP5g== + +"@floating-ui/dom@^1.3.0": + version "1.4.4" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.4.4.tgz#cf859dde33995a4e7b6ded16c98cb73b2ebfffd0" + integrity sha512-21hhDEPOiWkGp0Ys4Wi6Neriah7HweToKra626CIK712B5m9qkdz54OP9gVldUg+URnBTpv/j/bi/skmGdstXQ== + dependencies: + "@floating-ui/core" "^1.3.1" + +"@floating-ui/react-dom@^2.0.0": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.0.1.tgz#7972a4fc488a8c746cded3cfe603b6057c308a91" + integrity sha512-rZtAmSht4Lry6gdhAJDrCp/6rKN7++JnL1/Anbr/DdeyYXQPxvg/ivrbYvJulbRf4vL8b212suwMM2lxbv+RQA== + dependencies: + "@floating-ui/dom" "^1.3.0" + +"@livepeer/core-react@^1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@livepeer/core-react/-/core-react-1.6.0.tgz#2a29789bd8acb551d81496cdc85376f165652971" + integrity sha512-6lsrWJ/iJSF9bL3y8O+gkvRJ17tT6g9z3l1/E7pf30tIlELjwFb4KklK/k3SFtuYYskkx8v5DvU2LaOd2yhQYA== + dependencies: + "@livepeer/core" "^1.6.0" + "@tanstack/query-async-storage-persister" "4.22.4" + "@tanstack/query-core" "4.22.4" + "@tanstack/react-query" "4.22.4" + "@tanstack/react-query-persist-client" "4.22.4" + use-sync-external-store "^1.2.0" + zustand "^4.3.2" + +"@livepeer/core@^1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@livepeer/core/-/core-1.6.0.tgz#1be05fc92b21f0cdebf28dd7243de6d8d0b8753c" + integrity sha512-MhyrtsXFrndnWn16GViavVG9UNjGroavw1FttgfstQ1IPWxrP2HEEvX52zATXF0JX/xfH5MCsfLNcVC9MF399g== + dependencies: + cross-fetch "^3.1.5" + ms "^3.0.0-canary.1" + multiformats "9.9.0" + tus-js-client "^3.0.1" + zustand "^4.3.2" + +"@livepeer/react@^2.6.0": + version "2.6.0" + resolved "https://registry.yarnpkg.com/@livepeer/react/-/react-2.6.0.tgz#6ddff6d1c9e8f4dccff76c95ece238bc77642e5b" + integrity sha512-CH5hpONn4eiL6Qqf3neVzduvMbEkYa9DP1wliEGTpq/rAb8kfdrKGVOeEKkx7GoIIdHNPf0GIwFIggiqu/l8yw== + dependencies: + "@livepeer/core-react" "^1.6.0" + "@radix-ui/react-dialog" "^1.0.4" + "@radix-ui/react-popover" "^1.0.6" + "@radix-ui/react-select" "^1.2.2" + "@stitches/react" "^1.2.8" + core-js "^3.27.2" + livepeer "2.6.0" + zustand "^4.3.2" + +"@pushprotocol/socket@^0.5.0": + version "0.5.1" + resolved "https://registry.yarnpkg.com/@pushprotocol/socket/-/socket-0.5.1.tgz#3ba128e6f58d62fabca0287efe049d6a52defcaa" + integrity sha512-nkF3tpSZc8a6IC2ypXfja8S8oF78aJG3oCEXUSmee3otN5bYZb+pBV2Ggiay/6NBx/wL1L7dngspe/7BhoLNcg== + dependencies: + socket.io-client "^4.5.2" + tslib "^2.3.0" + +"@radix-ui/number@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/number/-/number-1.0.1.tgz#644161a3557f46ed38a042acf4a770e826021674" + integrity sha512-T5gIdVO2mmPW3NNhjNgEP3cqMXjXL9UbO0BzWcXfvdBs+BohbQxvd/K5hSVKmn9/lbTdsQVKbUcP5WLCwvUbBg== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/primitive@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.0.1.tgz#e46f9958b35d10e9f6dc71c497305c22e3e55dbd" + integrity sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-arrow@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz#c24f7968996ed934d57fe6cde5d6ec7266e1d25d" + integrity sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-primitive" "1.0.3" + +"@radix-ui/react-collection@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.0.3.tgz#9595a66e09026187524a36c6e7e9c7d286469159" + integrity sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-context" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-slot" "1.0.2" + +"@radix-ui/react-compose-refs@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz#7ed868b66946aa6030e580b1ffca386dd4d21989" + integrity sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-context@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.0.1.tgz#fe46e67c96b240de59187dcb7a1a50ce3e2ec00c" + integrity sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-dialog@^1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.0.4.tgz#06bce6c16bb93eb36d7a8589e665a20f4c1c52c1" + integrity sha512-hJtRy/jPULGQZceSAP2Re6/4NpKo8im6V8P2hUqZsdFiSL8l35kYsw3qbRI6Ay5mQd2+wlLqje770eq+RJ3yZg== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.1" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-context" "1.0.1" + "@radix-ui/react-dismissable-layer" "1.0.4" + "@radix-ui/react-focus-guards" "1.0.1" + "@radix-ui/react-focus-scope" "1.0.3" + "@radix-ui/react-id" "1.0.1" + "@radix-ui/react-portal" "1.0.3" + "@radix-ui/react-presence" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-slot" "1.0.2" + "@radix-ui/react-use-controllable-state" "1.0.1" + aria-hidden "^1.1.1" + react-remove-scroll "2.5.5" + +"@radix-ui/react-direction@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.0.1.tgz#9cb61bf2ccf568f3421422d182637b7f47596c9b" + integrity sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-dismissable-layer@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.4.tgz#883a48f5f938fa679427aa17fcba70c5494c6978" + integrity sha512-7UpBa/RKMoHJYjie1gkF1DlK8l1fdU/VKDpoS3rCCo8YBJR294GwcEHyxHw72yvphJ7ld0AXEcSLAzY2F/WyCg== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.1" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-use-callback-ref" "1.0.1" + "@radix-ui/react-use-escape-keydown" "1.0.3" + +"@radix-ui/react-focus-guards@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.1.tgz#1ea7e32092216b946397866199d892f71f7f98ad" + integrity sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-focus-scope@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.3.tgz#9c2e8d4ed1189a1d419ee61edd5c1828726472f9" + integrity sha512-upXdPfqI4islj2CslyfUBNlaJCPybbqRHAi1KER7Isel9Q2AtSJ0zRBZv8mWQiFXD2nyAJ4BhC3yXgZ6kMBSrQ== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-use-callback-ref" "1.0.1" + +"@radix-ui/react-id@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.0.1.tgz#73cdc181f650e4df24f0b6a5b7aa426b912c88c0" + integrity sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-use-layout-effect" "1.0.1" + +"@radix-ui/react-popover@^1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@radix-ui/react-popover/-/react-popover-1.0.6.tgz#19bb81e7450482c625b8cd05bf4dcd1d2cd91a8b" + integrity sha512-cZ4defGpkZ0qTRtlIBzJLSzL6ht7ofhhW4i1+pkemjV1IKXm0wgCRnee154qlV6r9Ttunmh2TNZhMfV2bavUyA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.1" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-context" "1.0.1" + "@radix-ui/react-dismissable-layer" "1.0.4" + "@radix-ui/react-focus-guards" "1.0.1" + "@radix-ui/react-focus-scope" "1.0.3" + "@radix-ui/react-id" "1.0.1" + "@radix-ui/react-popper" "1.1.2" + "@radix-ui/react-portal" "1.0.3" + "@radix-ui/react-presence" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-slot" "1.0.2" + "@radix-ui/react-use-controllable-state" "1.0.1" + aria-hidden "^1.1.1" + react-remove-scroll "2.5.5" + +"@radix-ui/react-popper@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.1.2.tgz#4c0b96fcd188dc1f334e02dba2d538973ad842e9" + integrity sha512-1CnGGfFi/bbqtJZZ0P/NQY20xdG3E0LALJaLUEoKwPLwl6PPPfbeiCqMVQnhoFRAxjJj4RpBRJzDmUgsex2tSg== + dependencies: + "@babel/runtime" "^7.13.10" + "@floating-ui/react-dom" "^2.0.0" + "@radix-ui/react-arrow" "1.0.3" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-context" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-use-callback-ref" "1.0.1" + "@radix-ui/react-use-layout-effect" "1.0.1" + "@radix-ui/react-use-rect" "1.0.1" + "@radix-ui/react-use-size" "1.0.1" + "@radix-ui/rect" "1.0.1" + +"@radix-ui/react-portal@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.0.3.tgz#ffb961244c8ed1b46f039e6c215a6c4d9989bda1" + integrity sha512-xLYZeHrWoPmA5mEKEfZZevoVRK/Q43GfzRXkWV6qawIWWK8t6ifIiLQdd7rmQ4Vk1bmI21XhqF9BN3jWf+phpA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-primitive" "1.0.3" + +"@radix-ui/react-presence@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.0.1.tgz#491990ba913b8e2a5db1b06b203cb24b5cdef9ba" + integrity sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-use-layout-effect" "1.0.1" + +"@radix-ui/react-primitive@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz#d49ea0f3f0b2fe3ab1cb5667eb03e8b843b914d0" + integrity sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-slot" "1.0.2" + +"@radix-ui/react-select@^1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-select/-/react-select-1.2.2.tgz#caa981fa0d672cf3c1b2a5240135524e69b32181" + integrity sha512-zI7McXr8fNaSrUY9mZe4x/HC0jTLY9fWNhO1oLWYMQGDXuV4UCivIGTxwioSzO0ZCYX9iSLyWmAh/1TOmX3Cnw== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/number" "1.0.1" + "@radix-ui/primitive" "1.0.1" + "@radix-ui/react-collection" "1.0.3" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-context" "1.0.1" + "@radix-ui/react-direction" "1.0.1" + "@radix-ui/react-dismissable-layer" "1.0.4" + "@radix-ui/react-focus-guards" "1.0.1" + "@radix-ui/react-focus-scope" "1.0.3" + "@radix-ui/react-id" "1.0.1" + "@radix-ui/react-popper" "1.1.2" + "@radix-ui/react-portal" "1.0.3" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-slot" "1.0.2" + "@radix-ui/react-use-callback-ref" "1.0.1" + "@radix-ui/react-use-controllable-state" "1.0.1" + "@radix-ui/react-use-layout-effect" "1.0.1" + "@radix-ui/react-use-previous" "1.0.1" + "@radix-ui/react-visually-hidden" "1.0.3" + aria-hidden "^1.1.1" + react-remove-scroll "2.5.5" + +"@radix-ui/react-slot@1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.0.2.tgz#a9ff4423eade67f501ffb32ec22064bc9d3099ab" + integrity sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-compose-refs" "1.0.1" + +"@radix-ui/react-use-callback-ref@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz#f4bb1f27f2023c984e6534317ebc411fc181107a" + integrity sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-use-controllable-state@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.1.tgz#ecd2ced34e6330caf89a82854aa2f77e07440286" + integrity sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-use-callback-ref" "1.0.1" + +"@radix-ui/react-use-escape-keydown@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.3.tgz#217b840c250541609c66f67ed7bab2b733620755" + integrity sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-use-callback-ref" "1.0.1" + +"@radix-ui/react-use-layout-effect@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz#be8c7bc809b0c8934acf6657b577daf948a75399" + integrity sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-use-previous@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-previous/-/react-use-previous-1.0.1.tgz#b595c087b07317a4f143696c6a01de43b0d0ec66" + integrity sha512-cV5La9DPwiQ7S0gf/0qiD6YgNqM5Fk97Kdrlc5yBcrF3jyEZQwm7vYFqMo4IfeHgJXsRaMvLABFtd0OVEmZhDw== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-use-rect@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-1.0.1.tgz#fde50b3bb9fd08f4a1cd204572e5943c244fcec2" + integrity sha512-Cq5DLuSiuYVKNU8orzJMbl15TXilTnJKUCltMVQg53BQOF1/C5toAaGrowkgksdBQ9H+SRL23g0HDmg9tvmxXw== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/rect" "1.0.1" + +"@radix-ui/react-use-size@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-1.0.1.tgz#1c5f5fea940a7d7ade77694bb98116fb49f870b2" + integrity sha512-ibay+VqrgcaI6veAojjofPATwledXiSmX+C0KrBk/xgpX9rBzPV3OsfwlhQdUOFbh+LKQorLYT+xTXW9V8yd0g== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-use-layout-effect" "1.0.1" + +"@radix-ui/react-visually-hidden@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.0.3.tgz#51aed9dd0fe5abcad7dee2a234ad36106a6984ac" + integrity sha512-D4w41yN5YRKtu464TLnByKzMDG/JlMPHtfZgQAu9v6mNakUqGUI9vUrfQKz8NK41VMm/xbZbh76NUTVtIYqOMA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-primitive" "1.0.3" + +"@radix-ui/rect@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.0.1.tgz#bf8e7d947671996da2e30f4904ece343bc4a883f" + integrity sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ== + dependencies: + "@babel/runtime" "^7.13.10" + +"@socket.io/component-emitter@~3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553" + integrity sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg== + +"@stitches/core@^1.2.8": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@stitches/core/-/core-1.2.8.tgz#dce3b8fdc764fbc6dbea30c83b73bfb52cf96173" + integrity sha512-Gfkvwk9o9kE9r9XNBmJRfV8zONvXThnm1tcuojL04Uy5uRyqg93DC83lDebl0rocZCfKSjUv+fWYtMQmEDJldg== + +"@stitches/react@^1.2.8": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@stitches/react/-/react-1.2.8.tgz#954f8008be8d9c65c4e58efa0937f32388ce3a38" + integrity sha512-9g9dWI4gsSVe8bNLlb+lMkBYsnIKCZTmvqvDG+Avnn69XfmHZKiaMrx7cgTaddq7aTPPmXiTsbFcUy0xgI4+wA== + +"@tanstack/query-async-storage-persister@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@tanstack/query-async-storage-persister/-/query-async-storage-persister-4.22.4.tgz#60f846dbb2b0bad6911b29ff77ba6272e610283c" + integrity sha512-8DWEt+bmxyjp12aqGnYhpgroOZgvgzvs+mMqBIyZVET4eWQNKAuQSFXTlkztmq9/sxbvTnp+xu7KRZExyurZPA== + dependencies: + "@tanstack/query-persist-client-core" "4.22.4" + +"@tanstack/query-core@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-4.22.4.tgz#aca622d2f8800a147ece5520d956a076ab92f0ea" + integrity sha512-t79CMwlbBnj+yL82tEcmRN93bL4U3pae2ota4t5NN2z3cIeWw74pzdWrKRwOfTvLcd+b30tC+ciDlfYOKFPGUw== + +"@tanstack/query-persist-client-core@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@tanstack/query-persist-client-core/-/query-persist-client-core-4.22.4.tgz#a8ed136a8234b9cbd12ae3df857425330c6200db" + integrity sha512-F5rCLczSw8RjFlwWASD3oRR7D4oyG90QbBFaOqBCjGbvE3bcD+m/E4GGCp1qfACoLuH4KtxhdwdOFfE+e0TRZQ== + +"@tanstack/react-query-persist-client@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@tanstack/react-query-persist-client/-/react-query-persist-client-4.22.4.tgz#8e4fad6f70ca922ef9e7be58c5bd14b010cff780" + integrity sha512-vnRD28T0BLsbDRlantC6W34eLCbjSoZEkYL4t2QYRyuEcmUya2Ddbn+DN+RfZHqxoMiSJNfMdmRXsMPpNHZ1QA== + dependencies: + "@tanstack/query-persist-client-core" "4.22.4" + +"@tanstack/react-query@4.22.4": + version "4.22.4" + resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-4.22.4.tgz#851581c645f1c9cfcd394448fedd980a39bbc3fe" + integrity sha512-e5j5Z88XUQGeEPMyz5XF1V0mMf6Da+6URXiTpZfUb9nuHs2nlNoA+EoIvnhccE5b9YT6Yg7kARhn2L7u94M/4A== + dependencies: + "@tanstack/query-core" "4.22.4" + use-sync-external-store "^1.2.0" + +aria-hidden@^1.1.1: + version "1.2.3" + resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.2.3.tgz#14aeb7fb692bbb72d69bebfa47279c1fd725e954" + integrity sha512-xcLxITLe2HYa1cnYnwCjkOO1PqUHQpozB8x9AR0OgWN2woOBi5kSDVxKfd0b7sb1hw5qFeJhXm9H1nu3xSfLeQ== + dependencies: + tslib "^2.0.0" + +buffer-from@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +combine-errors@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/combine-errors/-/combine-errors-3.0.3.tgz#f4df6740083e5703a3181110c2b10551f003da86" + integrity sha512-C8ikRNRMygCwaTx+Ek3Yr+OuZzgZjduCOfSQBjbM8V3MfgcjSTeto/GXP6PAwKvJz/v15b7GHZvx5rOlczFw/Q== + dependencies: + custom-error-instance "2.1.1" + lodash.uniqby "4.5.0" + +core-js@^3.27.2: + version "3.31.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.31.1.tgz#f2b0eea9be9da0def2c5fece71064a7e5d687653" + integrity sha512-2sKLtfq1eFST7l7v62zaqXacPc7uG8ZAya8ogijLhTtaKNcpzpB4TMoTw2Si+8GYKRwFPMMtUT0263QFWFfqyQ== + +cross-fetch@^3.1.5: + version "3.1.8" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82" + integrity sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg== + dependencies: + node-fetch "^2.6.12" + +custom-error-instance@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/custom-error-instance/-/custom-error-instance-2.1.1.tgz#3cf6391487a6629a6247eb0ca0ce00081b7e361a" + integrity sha512-p6JFxJc3M4OTD2li2qaHkDCw9SfMw82Ldr6OC9Je1aXiGfhx2W8p3GaoeaGrPJTUN9NirTM/KTxHWMUdR1rsUg== + date-fns@^2.28.0: version "2.29.3" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.3.tgz#27402d2fc67eb442b511b70bbdf98e6411cd68a8" integrity sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA== +debug@~4.3.1, debug@~4.3.2: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +detect-node-es@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493" + integrity sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ== + dom-serializer@^1.0.1: version "1.4.1" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30" @@ -42,6 +490,22 @@ emoji-picker-react@^3.5.1: resolved "https://registry.yarnpkg.com/emoji-picker-react/-/emoji-picker-react-3.6.5.tgz#423fef704b64138b872f8087738c634a3589c6ac" integrity sha512-pfu3XkHSeqXjygyoKtRsmJdsNkRxhkE7hlnWrYBoPnm8V03aJ8Y9H5oRUQ+fF4WRZpjfJFsw5V7ewRVhuj/8cA== +engine.io-client@~6.5.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-6.5.0.tgz#c77f14c0e996d3746a1fa681b3b093003dc1743d" + integrity sha512-C7eN3OKggSfd5g8IDgUA9guC8TNS6CEganKT7dL6Fp3q+FobcQ/WBn2Qq2XTL1vNTiFZfDzXohvqLuR9dWejdg== + dependencies: + "@socket.io/component-emitter" "~3.1.0" + debug "~4.3.1" + engine.io-parser "~5.1.0" + ws "~8.11.0" + xmlhttprequest-ssl "~2.0.0" + +engine.io-parser@~5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.1.0.tgz#d593d6372d7f79212df48f807b8cace1ea1cb1b8" + integrity sha512-enySgNiK5tyZFynt3z7iqBR+Bto9EVVVvDFuTT0ioHCGbzirZVGDGiQjZzEp8hWl6hd5FSVytJGuScX1C1C35w== + entities@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" @@ -52,6 +516,21 @@ entities@^3.0.1: resolved "https://registry.yarnpkg.com/entities/-/entities-3.0.1.tgz#2b887ca62585e96db3903482d336c1006c3001d4" integrity sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q== +get-nonce@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3" + integrity sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q== + +graceful-fs@^4.2.4: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +hls.js@^1.4.0: + version "1.4.8" + resolved "https://registry.yarnpkg.com/hls.js/-/hls.js-1.4.8.tgz#6fedcb5224d7361e4f38046ffd45286d8a645df8" + integrity sha512-wYL7W49M6oKv0+P4RW50YkJaxDzgnHMMrN+YoLpow07hVgaedAdX9HfKkehTb04UEfeJhNSef5ucICYPsHOfqg== + html-dom-parser@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/html-dom-parser/-/html-dom-parser-1.2.0.tgz#8f689b835982ffbf245eda99730e92b8462c111e" @@ -85,11 +564,207 @@ inline-style-parser@0.1.1: resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== +invariant@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +js-base64@^3.7.2: + version "3.7.5" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-3.7.5.tgz#21e24cf6b886f76d6f5f165bfcd69cc55b9e3fca" + integrity sha512-3MEt5DTINKqfScXKfJFrRbxkrnk2AxPWGBL/ycjz4dK8iqiSJ06UxD8jh8xuh6p10TX4t2+7FsBYVxxQbMg+qA== + +"js-tokens@^3.0.0 || ^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +livepeer@2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/livepeer/-/livepeer-2.6.0.tgz#b2c1011436ec801390e8b77d1322087c83171c6b" + integrity sha512-tURkBvJQi0nyS5WlFHhKyRGx0qKqGt/DbKSzhUwJ9fAzT3GAlipujgKVOc3wnNWIj76LQrCp7onUmsrrkFRGkQ== + dependencies: + "@livepeer/core" "^1.6.0" + "@stitches/core" "^1.2.8" + core-js "^3.27.2" + cross-fetch "^3.1.5" + hls.js "^1.4.0" + ms "^3.0.0-canary.1" + multiformats "9.9.0" + tus-js-client "^3.0.1" + zustand "^4.3.2" + +lodash._baseiteratee@~4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/lodash._baseiteratee/-/lodash._baseiteratee-4.7.0.tgz#34a9b5543572727c3db2e78edae3c0e9e66bd102" + integrity sha512-nqB9M+wITz0BX/Q2xg6fQ8mLkyfF7MU7eE+MNBNjTHFKeKaZAPEzEg+E8LWxKWf1DQVflNEn9N49yAuqKh2mWQ== + dependencies: + lodash._stringtopath "~4.8.0" + +lodash._basetostring@~4.12.0: + version "4.12.0" + resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-4.12.0.tgz#9327c9dc5158866b7fa4b9d42f4638e5766dd9df" + integrity sha512-SwcRIbyxnN6CFEEK4K1y+zuApvWdpQdBHM/swxP962s8HIxPO3alBH5t3m/dl+f4CMUug6sJb7Pww8d13/9WSw== + +lodash._baseuniq@~4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8" + integrity sha512-Ja1YevpHZctlI5beLA7oc5KNDhGcPixFhcqSiORHNsp/1QTv7amAXzw+gu4YOvErqVlMVyIJGgtzeepCnnur0A== + dependencies: + lodash._createset "~4.0.0" + lodash._root "~3.0.0" + +lodash._createset@~4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26" + integrity sha512-GTkC6YMprrJZCYU3zcqZj+jkXkrXzq3IPBcF/fIPpNEAB4hZEtXU8zp/RwKOvZl43NUmwDbyRk3+ZTbeRdEBXA== + +lodash._root@~3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" + integrity sha512-O0pWuFSK6x4EXhM1dhZ8gchNtG7JMqBtrHdoUFUWXD7dJnNSUze1GuyQr5sOs0aCvgGeI3o/OJW8f4ca7FDxmQ== + +lodash._stringtopath@~4.8.0: + version "4.8.0" + resolved "https://registry.yarnpkg.com/lodash._stringtopath/-/lodash._stringtopath-4.8.0.tgz#941bcf0e64266e5fc1d66fed0a6959544c576824" + integrity sha512-SXL66C731p0xPDC5LZg4wI5H+dJo/EO4KTqOMwLYCH3+FmmfAKJEZCm6ohGpI+T1xwsDsJCfL4OnhorllvlTPQ== + dependencies: + lodash._basetostring "~4.12.0" + +lodash.throttle@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" + integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ== + +lodash.uniqby@4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.uniqby/-/lodash.uniqby-4.5.0.tgz#a3a17bbf62eeb6240f491846e97c1c4e2a5e1e21" + integrity sha512-IRt7cfTtHy6f1aRVA5n7kT8rgN3N1nH6MOWLcHfpWG2SH19E3JksLK38MktLxZDhlAjCP9jpIXkOnRXlu6oByQ== + dependencies: + lodash._baseiteratee "~4.7.0" + lodash._baseuniq "~4.6.0" + +loose-envify@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@^3.0.0-canary.1: + version "3.0.0-canary.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-3.0.0-canary.1.tgz#c7b34fbce381492fd0b345d1cf56e14d67b77b80" + integrity sha512-kh8ARjh8rMN7Du2igDRO9QJnqCb2xYTJxyQYK7vJJS4TvLLmsbyhiKpSW+t+y26gyOyMd0riphX0GeWKU3ky5g== + +multiformats@9.9.0: + version "9.9.0" + resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-9.9.0.tgz#c68354e7d21037a8f1f8833c8ccd68618e8f1d37" + integrity sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg== + +node-fetch@^2.6.12: + version "2.6.12" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.12.tgz#02eb8e22074018e3d5a83016649d04df0e348fba" + integrity sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g== + dependencies: + whatwg-url "^5.0.0" + +proper-lockfile@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-4.1.2.tgz#c8b9de2af6b2f1601067f98e01ac66baa223141f" + integrity sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA== + dependencies: + graceful-fs "^4.2.4" + retry "^0.12.0" + signal-exit "^3.0.2" + +querystringify@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" + integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== + react-property@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/react-property/-/react-property-2.0.0.tgz#2156ba9d85fa4741faf1918b38efc1eae3c6a136" integrity sha512-kzmNjIgU32mO4mmH5+iUyrqlpFQhF8K2k7eZ4fdLSOPFrD1XgEuSBv9LDEgxRXTMBqMd8ppT0x6TIzqE5pdGdw== +react-remove-scroll-bar@^2.3.3: + version "2.3.4" + resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.4.tgz#53e272d7a5cb8242990c7f144c44d8bd8ab5afd9" + integrity sha512-63C4YQBUt0m6ALadE9XV56hV8BgJWDmmTPY758iIJjfQKt2nYwoUrPk0LXRXcB/yIj82T1/Ixfdpdk68LwIB0A== + dependencies: + react-style-singleton "^2.2.1" + tslib "^2.0.0" + +react-remove-scroll@2.5.5: + version "2.5.5" + resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz#1e31a1260df08887a8a0e46d09271b52b3a37e77" + integrity sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw== + dependencies: + react-remove-scroll-bar "^2.3.3" + react-style-singleton "^2.2.1" + tslib "^2.1.0" + use-callback-ref "^1.3.0" + use-sidecar "^1.1.2" + +react-style-singleton@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.1.tgz#f99e420492b2d8f34d38308ff660b60d0b1205b4" + integrity sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g== + dependencies: + get-nonce "^1.0.0" + invariant "^2.2.4" + tslib "^2.0.0" + +regenerator-runtime@^0.13.11: + version "0.13.11" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" + integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + +retry@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== + +signal-exit@^3.0.2: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +socket.io-client@^4.5.2: + version "4.7.0" + resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-4.7.0.tgz#f869a41a2593bc36f058f3b46175024491d997b5" + integrity sha512-7Q8CeDrhuZzg4QLXl3tXlk5yb086oxYzehAVZRLiGCzCmtDneiHz1qHyyWcxhTgxXiokVpWQXoG/u60HoXSQew== + dependencies: + "@socket.io/component-emitter" "~3.1.0" + debug "~4.3.2" + engine.io-client "~6.5.0" + socket.io-parser "~4.2.4" + +socket.io-parser@~4.2.4: + version "4.2.4" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.4.tgz#c806966cf7270601e47469ddeec30fbdfda44c83" + integrity sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew== + dependencies: + "@socket.io/component-emitter" "~3.1.0" + debug "~4.3.1" + style-to-js@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/style-to-js/-/style-to-js-1.1.1.tgz#417786986cda61d4525c80aed9d1123a6a7af9b8" @@ -103,3 +778,89 @@ style-to-object@0.3.0: integrity sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA== dependencies: inline-style-parser "0.1.1" + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + +tslib@^2.0.0, tslib@^2.1.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.0.tgz#b295854684dbda164e181d259a22cd779dcd7bc3" + integrity sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA== + +tslib@^2.3.0: + version "2.5.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.3.tgz#24944ba2d990940e6e982c4bea147aba80209913" + integrity sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w== + +tus-js-client@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/tus-js-client/-/tus-js-client-3.1.0.tgz#20af57d06c23823fbe108ccb3a3dcb7503968cb4" + integrity sha512-Hfpc8ho4C9Lhs/OflPUA/nHUHZJUrKD5upoPBq7dYJJ9DQhWocsjJU2RZYfN16Y5n19j9dFDszwCvVZ5sfcogw== + dependencies: + buffer-from "^1.1.2" + combine-errors "^3.0.3" + is-stream "^2.0.0" + js-base64 "^3.7.2" + lodash.throttle "^4.1.1" + proper-lockfile "^4.1.2" + url-parse "^1.5.7" + +url-parse@^1.5.7: + version "1.5.10" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" + integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== + dependencies: + querystringify "^2.1.1" + requires-port "^1.0.0" + +use-callback-ref@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.0.tgz#772199899b9c9a50526fedc4993fc7fa1f7e32d5" + integrity sha512-3FT9PRuRdbB9HfXhEq35u4oZkvpJ5kuYbpqhCfmiZyReuRgpnhDlbr2ZEnnuS0RrJAPn6l23xjFg9kpDM+Ms7w== + dependencies: + tslib "^2.0.0" + +use-sidecar@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.1.2.tgz#2f43126ba2d7d7e117aa5855e5d8f0276dfe73c2" + integrity sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw== + dependencies: + detect-node-es "^1.1.0" + tslib "^2.0.0" + +use-sync-external-store@1.2.0, use-sync-external-store@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" + integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +ws@~8.11.0: + version "8.11.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143" + integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg== + +xmlhttprequest-ssl@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz#91360c86b914e67f44dce769180027c0da618c67" + integrity sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A== + +zustand@^4.3.2: + version "4.3.9" + resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.3.9.tgz#a7d4332bbd75dfd25c6848180b3df1407217f2ad" + integrity sha512-Tat5r8jOMG1Vcsj8uldMyqYKC5IZvQif8zetmLHs9WoZlntTHmIoNM8TpLRY31ExncuUvUOXehd0kvahkuHjDw== + dependencies: + use-sync-external-store "1.2.0"