Merge pull request #33 from daily-demos/remove-eslint
Switch linter to Next Core Web Vitals
|
|
@ -1,18 +1,13 @@
|
|||
{
|
||||
"extends": ["airbnb", "airbnb/hooks", "prettier"],
|
||||
"parser": "babel-eslint",
|
||||
"extends": ["next/core-web-vitals", "prettier"],
|
||||
"env": {
|
||||
"browser": true,
|
||||
"node": true,
|
||||
"es6": true
|
||||
},
|
||||
"rules": {
|
||||
"no-console": 0,
|
||||
"react/jsx-props-no-spreading": 0,
|
||||
"react/forbid-prop-types": 0,
|
||||
"react/require-default-props": 0,
|
||||
"react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
|
||||
"import/no-extraneous-dependencies": 0,
|
||||
"@next/next/no-img-element": 0,
|
||||
"import/order": [
|
||||
"error",
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ Setup dependencies via `yarn install`.
|
|||
|
||||
Add the required environment variables (e.g. your Daily API key) for the demo being used. Each demo's README will list the required environment variables to run it locally.
|
||||
|
||||
Run an example via `yarn workspace @dailyjs/basic-call dev` (replacing `basic-call` with the name of the demo).
|
||||
Run an example via `yarn workspace @custom/basic-call dev` (replacing `basic-call` with the name of the demo).
|
||||
|
||||
Please note: these demos are intended as educational resources for using the Daily platform as well as showcasing common usage patterns and best practices. That said, they are not intended to be used as production ready applications.
|
||||
|
||||
|
|
@ -18,7 +18,7 @@ Please note: these demos are intended as educational resources for using the Dai
|
|||
|
||||
## Contents
|
||||
|
||||
## [Daily JS (Web)](./dailyjs/)
|
||||
## [Daily JS (Web)](./custom/)
|
||||
|
||||
Examples that showcase the Daily CallObject using our Javascript library
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ Demonstrates using manual track management to support larger call sizes
|
|||
|
||||
We recommend starting with the [basic call](./basic-call) example, showcasing the common flow of a call Daily call, device management and error handling.
|
||||
|
||||
Run an examples with `yarn workspace @dailyjs/[demo-name] dev` (replacing `[demo-name]` with the name of the demo you'd like to run e.g. `basic-call`.
|
||||
Run an examples with `yarn workspace @custom/[demo-name] dev` (replacing `[demo-name]` with the name of the demo you'd like to run e.g. `basic-call`.
|
||||
|
||||
- Please ensure your Daily rooms are setup to use [web sockets](https://docs.daily.co/reference#domain-configuration)
|
||||
- Follow the instructions within each demo first, making sure to set all the necassary local environment variables etc
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
### Live example
|
||||
|
||||
**[See it in action here ➡️](https://dailyjs-basic-call.vercel.app)**
|
||||
**[See it in action here ➡️](https://custom-basic-call.vercel.app)**
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ mv env.example .env.local
|
|||
|
||||
# from project root...
|
||||
yarn
|
||||
yarn workspace @dailyjs/basic-call dev
|
||||
yarn workspace @custom/basic-call dev
|
||||
```
|
||||
|
||||
## How does this example work?
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import ExpiryTimer from '@dailyjs/shared/components/ExpiryTimer';
|
||||
import { useCallState } from '@dailyjs/shared/contexts/CallProvider';
|
||||
import { useCallUI } from '@dailyjs/shared/hooks/useCallUI';
|
||||
import ExpiryTimer from '@custom/shared/components/ExpiryTimer';
|
||||
import { useCallState } from '@custom/shared/contexts/CallProvider';
|
||||
import { useCallUI } from '@custom/shared/hooks/useCallUI';
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import Room from '../Room';
|
||||
import Room from '../Call/Room';
|
||||
import { Asides } from './Asides';
|
||||
import { Modals } from './Modals';
|
||||
|
||||
|
|
@ -13,7 +13,7 @@ export const App = ({ customComponentForState }) => {
|
|||
|
||||
const componentForState = useCallUI({
|
||||
state,
|
||||
room: () => <Room />,
|
||||
room: <Room />,
|
||||
...customComponentForState,
|
||||
});
|
||||
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import React from 'react';
|
||||
import { PeopleAside } from '@dailyjs/shared/components/Aside/PeopleAside';
|
||||
import { useUIState } from '@dailyjs/shared/contexts/UIStateProvider';
|
||||
import { NetworkAside } from '@custom/shared/components/Aside';
|
||||
import { PeopleAside } from '@custom/shared/components/Aside';
|
||||
import { useUIState } from '@custom/shared/contexts/UIStateProvider';
|
||||
|
||||
export const Asides = () => {
|
||||
const { asides } = useUIState();
|
||||
|
|
@ -8,6 +9,7 @@ export const Asides = () => {
|
|||
return (
|
||||
<>
|
||||
<PeopleAside />
|
||||
<NetworkAside />
|
||||
{asides.map((AsideComponent) => (
|
||||
<AsideComponent key={AsideComponent.name} />
|
||||
))}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import DeviceSelectModal from '@dailyjs/shared/components/DeviceSelectModal/DeviceSelectModal';
|
||||
import { useUIState } from '@dailyjs/shared/contexts/UIStateProvider';
|
||||
import DeviceSelectModal from '@custom/shared/components/DeviceSelectModal/DeviceSelectModal';
|
||||
import { useUIState } from '@custom/shared/contexts/UIStateProvider';
|
||||
|
||||
export const Modals = () => {
|
||||
const { modals } = useUIState();
|
||||
|
|
@ -1,2 +1 @@
|
|||
export { App as default } from './App';
|
||||
export { Modals } from './Modals';
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import { Audio } from '@dailyjs/shared/components/Audio';
|
||||
import { BasicTray } from '@dailyjs/shared/components/Tray';
|
||||
import { useParticipants } from '@dailyjs/shared/contexts/ParticipantsProvider';
|
||||
import useJoinSound from '@dailyjs/shared/hooks/useJoinSound';
|
||||
import { Audio } from '@custom/shared/components/Audio';
|
||||
import { BasicTray } from '@custom/shared/components/Tray';
|
||||
import { useParticipants } from '@custom/shared/contexts/ParticipantsProvider';
|
||||
import useJoinSound from '@custom/shared/hooks/useJoinSound';
|
||||
import PropTypes from 'prop-types';
|
||||
import WaitingRoom from '../WaitingRoom';
|
||||
import { WaitingRoom } from './WaitingRoom';
|
||||
|
||||
export const RoomContainer = ({ children }) => {
|
||||
export const Container = ({ children }) => {
|
||||
const { isOwner } = useParticipants();
|
||||
|
||||
useJoinSound();
|
||||
|
|
@ -42,8 +42,8 @@ export const RoomContainer = ({ children }) => {
|
|||
);
|
||||
};
|
||||
|
||||
RoomContainer.propTypes = {
|
||||
Container.propTypes = {
|
||||
children: PropTypes.node,
|
||||
};
|
||||
|
||||
export default RoomContainer;
|
||||
export default Container;
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import HeaderCapsule from '@dailyjs/shared/components/HeaderCapsule';
|
||||
import { useParticipants } from '@dailyjs/shared/contexts/ParticipantsProvider';
|
||||
import { useUIState } from '@dailyjs/shared/contexts/UIStateProvider';
|
||||
import HeaderCapsule from '@custom/shared/components/HeaderCapsule';
|
||||
import { useParticipants } from '@custom/shared/contexts/ParticipantsProvider';
|
||||
import { useUIState } from '@custom/shared/contexts/UIStateProvider';
|
||||
|
||||
export const Header = () => {
|
||||
const { participantCount } = useParticipants();
|
||||
|
|
@ -10,7 +10,13 @@ export const Header = () => {
|
|||
return useMemo(
|
||||
() => (
|
||||
<header className="room-header">
|
||||
<img src="assets/daily-logo.svg" alt="Daily" className="logo" />
|
||||
<img
|
||||
src="/assets/daily-logo.svg"
|
||||
alt="Daily"
|
||||
className="logo"
|
||||
width="80"
|
||||
height="32"
|
||||
/>
|
||||
|
||||
<HeaderCapsule>Basic call demo</HeaderCapsule>
|
||||
<HeaderCapsule>
|
||||
|
|
@ -31,7 +37,8 @@ export const Header = () => {
|
|||
flex: 0 0 auto;
|
||||
column-gap: var(--spacing-xxs);
|
||||
box-sizing: border-box;
|
||||
padding: var(--spacing-sm);
|
||||
padding: var(--spacing-sm) var(--spacing-sm) var(--spacing-xxs)
|
||||
var(--spacing-sm);
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
import React from 'react';
|
||||
import VideoContainer from '@custom/shared/components/VideoContainer/VideoContainer';
|
||||
|
||||
import { Container } from './Container';
|
||||
import { Header } from './Header';
|
||||
import { VideoGrid } from './VideoGrid';
|
||||
|
||||
export function Room() {
|
||||
return (
|
||||
<Container>
|
||||
<Header />
|
||||
<VideoContainer>
|
||||
<VideoGrid />
|
||||
</VideoContainer>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
export default Room;
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useState, useMemo, useEffect, useRef } from 'react';
|
||||
import Tile from '@dailyjs/shared/components/Tile';
|
||||
import { DEFAULT_ASPECT_RATIO } from '@dailyjs/shared/constants';
|
||||
import { useParticipants } from '@dailyjs/shared/contexts/ParticipantsProvider';
|
||||
import Tile from '@custom/shared/components/Tile';
|
||||
import { DEFAULT_ASPECT_RATIO } from '@custom/shared/constants';
|
||||
import { useParticipants } from '@custom/shared/contexts/ParticipantsProvider';
|
||||
import { useDeepCompareMemo } from 'use-deep-compare';
|
||||
|
||||
/**
|
||||
|
|
@ -2,8 +2,8 @@ import React from 'react';
|
|||
import {
|
||||
WaitingRoomModal,
|
||||
WaitingRoomNotification,
|
||||
} from '@dailyjs/shared/components/WaitingRoom';
|
||||
import { useWaitingRoom } from '@dailyjs/shared/contexts/WaitingRoomProvider';
|
||||
} from '@custom/shared/components/WaitingRoom';
|
||||
import { useWaitingRoom } from '@custom/shared/contexts/WaitingRoomProvider';
|
||||
|
||||
export const WaitingRoom = () => {
|
||||
const { setShowModal, showModal } = useWaitingRoom();
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { Card, CardHeader, CardBody } from '@dailyjs/shared/components/Card';
|
||||
import Loader from '@dailyjs/shared/components/Loader';
|
||||
import { Well } from '@dailyjs/shared/components/Well';
|
||||
import { Card, CardHeader, CardBody } from '@custom/shared/components/Card';
|
||||
import Loader from '@custom/shared/components/Loader';
|
||||
import Well from '@custom/shared/components/Well';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
export const CreatingRoom = ({ onCreated }) => {
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { Button } from '@dailyjs/shared/components/Button';
|
||||
import Button from '@custom/shared/components/Button';
|
||||
import {
|
||||
Card,
|
||||
CardBody,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
} from '@dailyjs/shared/components/Card';
|
||||
import Field from '@dailyjs/shared/components/Field';
|
||||
import { TextInput, BooleanInput } from '@dailyjs/shared/components/Input';
|
||||
import { Well } from '@dailyjs/shared/components/Well';
|
||||
} from '@custom/shared/components/Card';
|
||||
import Field from '@custom/shared/components/Field';
|
||||
import { TextInput, BooleanInput } from '@custom/shared/components/Input';
|
||||
import Well from '@custom/shared/components/Well';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
/**
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { Card, CardBody, CardHeader } from '@dailyjs/shared/components/Card';
|
||||
import { Card, CardBody, CardHeader } from '@custom/shared/components/Card';
|
||||
|
||||
export const NotConfigured = () => (
|
||||
<Card>
|
||||
|
|
@ -6,3 +6,6 @@ DAILY_API_KEY=
|
|||
|
||||
# Daily REST API endpoint
|
||||
DAILY_REST_DOMAIN=https://api.daily.co/v1
|
||||
|
||||
# Run in demo mode (will create a demo room for you to try)
|
||||
DAILY_DEMO_MODE=0
|
||||
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
|
|
@ -1,5 +1,5 @@
|
|||
const withPlugins = require('next-compose-plugins');
|
||||
const withTM = require('next-transpile-modules')(['@dailyjs/shared']);
|
||||
const withTM = require('next-transpile-modules')(['@custom/shared']);
|
||||
|
||||
const packageJson = require('./package.json');
|
||||
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "@dailyjs/basic-call",
|
||||
"name": "@custom/basic-call",
|
||||
"description": "Basic Call Example",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
|
|
@ -10,11 +10,9 @@
|
|||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@dailyjs/shared": "*",
|
||||
"next": "^11.0.0",
|
||||
"pluralize": "^8.0.0",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2"
|
||||
"@custom/shared": "*",
|
||||
"next": "^11.1.2",
|
||||
"pluralize": "^8.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-plugin-module-resolver": "^4.1.0",
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
import React from 'react';
|
||||
import GlobalHead from '@dailyjs/shared/components/GlobalHead';
|
||||
import GlobalStyle from '@dailyjs/shared/components/GlobalStyle';
|
||||
import GlobalStyle from '@custom/shared/components/GlobalStyle';
|
||||
import Head from 'next/head';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
|
|
@ -10,7 +9,6 @@ function App({ Component, pageProps }) {
|
|||
<Head>
|
||||
<title>Daily - {process.env.PROJECT_TITLE}</title>
|
||||
</Head>
|
||||
<GlobalHead />
|
||||
<GlobalStyle />
|
||||
<Component
|
||||
asides={App.asides}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
import Document, { Html, Head, Main, NextScript } from 'next/document';
|
||||
|
||||
class MyDocument extends Document {
|
||||
render() {
|
||||
return (
|
||||
<Html>
|
||||
<Head>
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Rubik:wght@400;500;600&display=optional"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
</Head>
|
||||
<body>
|
||||
<Main />
|
||||
<NextScript />
|
||||
</body>
|
||||
</Html>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default MyDocument;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
export default async function handler(req, res) {
|
||||
const { privacy, expiryMinutes } = req.body;
|
||||
const { privacy, expiryMinutes, ...rest } = req.body;
|
||||
|
||||
if (req.method === 'POST') {
|
||||
console.log(`Creating room on domain ${process.env.DAILY_DOMAIN}`);
|
||||
|
|
@ -16,7 +16,7 @@ export default async function handler(req, res) {
|
|||
exp: Math.round(Date.now() / 1000) + (expiryMinutes || 5) * 60, // expire in x minutes
|
||||
eject_at_room_exp: true,
|
||||
enable_knocking: privacy !== 'public',
|
||||
enable_recording: 'local',
|
||||
...rest,
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
|
@ -1,15 +1,16 @@
|
|||
import React, { useState, useCallback } from 'react';
|
||||
import { CallProvider } from '@dailyjs/shared/contexts/CallProvider';
|
||||
import { MediaDeviceProvider } from '@dailyjs/shared/contexts/MediaDeviceProvider';
|
||||
import { ParticipantsProvider } from '@dailyjs/shared/contexts/ParticipantsProvider';
|
||||
import { TracksProvider } from '@dailyjs/shared/contexts/TracksProvider';
|
||||
import { UIStateProvider } from '@dailyjs/shared/contexts/UIStateProvider';
|
||||
import { WaitingRoomProvider } from '@dailyjs/shared/contexts/WaitingRoomProvider';
|
||||
import getDemoProps from '@dailyjs/shared/lib/demoProps';
|
||||
import { CallProvider } from '@custom/shared/contexts/CallProvider';
|
||||
import { MediaDeviceProvider } from '@custom/shared/contexts/MediaDeviceProvider';
|
||||
import { ParticipantsProvider } from '@custom/shared/contexts/ParticipantsProvider';
|
||||
import { TracksProvider } from '@custom/shared/contexts/TracksProvider';
|
||||
import { UIStateProvider } from '@custom/shared/contexts/UIStateProvider';
|
||||
import { WaitingRoomProvider } from '@custom/shared/contexts/WaitingRoomProvider';
|
||||
import getDemoProps from '@custom/shared/lib/demoProps';
|
||||
import PropTypes from 'prop-types';
|
||||
import App from '../components/App';
|
||||
import { CreatingRoom } from '../components/CreatingRoom';
|
||||
import { Intro, NotConfigured } from '../components/Intro';
|
||||
import CreatingRoom from '../components/Prejoin/CreatingRoom';
|
||||
import Intro from '../components/Prejoin/Intro';
|
||||
import NotConfigured from '../components/Prejoin/NotConfigured';
|
||||
|
||||
/**
|
||||
* Index page
|
||||
|
|
@ -22,7 +23,6 @@ import { Intro, NotConfigured } from '../components/Intro';
|
|||
export default function Index({
|
||||
domain,
|
||||
isConfigured = false,
|
||||
predefinedRoom = '',
|
||||
forceFetchToken = false,
|
||||
forceOwner = false,
|
||||
subscribeToTracksAutomatically = true,
|
||||
|
|
@ -32,7 +32,7 @@ export default function Index({
|
|||
customTrayComponent,
|
||||
customAppComponent,
|
||||
}) {
|
||||
const [roomName, setRoomName] = useState(predefinedRoom);
|
||||
const [roomName, setRoomName] = useState();
|
||||
const [fetchingToken, setFetchingToken] = useState(false);
|
||||
const [token, setToken] = useState();
|
||||
const [tokenError, setTokenError] = useState();
|
||||
|
|
@ -137,7 +137,6 @@ export default function Index({
|
|||
|
||||
Index.propTypes = {
|
||||
isConfigured: PropTypes.bool.isRequired,
|
||||
predefinedRoom: PropTypes.string,
|
||||
domain: PropTypes.string,
|
||||
asides: PropTypes.arrayOf(PropTypes.func),
|
||||
modals: PropTypes.arrayOf(PropTypes.func),
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import MessageCard from '@dailyjs/shared/components/MessageCard';
|
||||
import MessageCard from '@custom/shared/components/MessageCard';
|
||||
|
||||
export default function RoomNotFound() {
|
||||
return (
|
||||
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
### Live example
|
||||
|
||||
**[See it in action here ➡️](https://dailyjs-flying-emojis.vercel.app)**
|
||||
**[See it in action here ➡️](https://custom-flying-emojis.vercel.app)**
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -23,7 +23,7 @@ Please note: this demo is not currently mobile optimised
|
|||
mv env.example .env.local
|
||||
|
||||
yarn
|
||||
yarn workspace @dailyjs/flying-emojis dev
|
||||
yarn workspace @custom/flying-emojis dev
|
||||
```
|
||||
|
||||
## Deploy your own on Vercel
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import App from '@dailyjs/basic-call/components/App';
|
||||
import FlyingEmojiOverlay from '../FlyingEmojis/FlyingEmojisOverlay';
|
||||
import App from '@custom/basic-call/components/App';
|
||||
import FlyingEmojiOverlay from './FlyingEmojisOverlay';
|
||||
|
||||
export const AppWithEmojis = () => (
|
||||
<>
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useEffect, useRef, useCallback } from 'react';
|
||||
import { useCallState } from '@dailyjs/shared/contexts/CallProvider';
|
||||
import { useCallState } from '@custom/shared/contexts/CallProvider';
|
||||
|
||||
const EMOJI_MAP = {
|
||||
fire: '🔥',
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
import Button from '@dailyjs/shared/components/Button';
|
||||
import { TrayButton } from '@dailyjs/shared/components/Tray';
|
||||
import { ReactComponent as IconStar } from '@dailyjs/shared/icons/star-md.svg';
|
||||
import Button from '@custom/shared/components/Button';
|
||||
import { TrayButton } from '@custom/shared/components/Tray';
|
||||
import { ReactComponent as IconStar } from '@custom/shared/icons/star-md.svg';
|
||||
|
||||
const COOLDOWN = 1500;
|
||||
|
||||
|
Before Width: | Height: | Size: 143 KiB After Width: | Height: | Size: 143 KiB |
|
|
@ -1,7 +1,7 @@
|
|||
const withPlugins = require('next-compose-plugins');
|
||||
const withTM = require('next-transpile-modules')([
|
||||
'@dailyjs/shared',
|
||||
'@dailyjs/basic-call',
|
||||
'@custom/shared',
|
||||
'@custom/basic-call',
|
||||
]);
|
||||
|
||||
const packageJson = require('./package.json');
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "@dailyjs/flying-emojis",
|
||||
"name": "@custom/flying-emojis",
|
||||
"description": "Basic Call + Flying Emojis",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
|
|
@ -10,8 +10,8 @@
|
|||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@dailyjs/basic-call": "*",
|
||||
"@dailyjs/shared": "*",
|
||||
"@custom/basic-call": "*",
|
||||
"@custom/shared": "*",
|
||||
"next": "^11.0.0",
|
||||
"pluralize": "^8.0.0",
|
||||
"react": "^17.0.2",
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import App from '@dailyjs/basic-call/pages/_app';
|
||||
import App from '@custom/basic-call/pages/_app';
|
||||
import AppWithEmojis from '../components/App';
|
||||
import Tray from '../components/Tray';
|
||||
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
import Doc from '@custom/basic-call/pages/_document';
|
||||
|
||||
export default Doc;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import Index from '@dailyjs/basic-call/pages';
|
||||
import getDemoProps from '@dailyjs/shared/lib/demoProps';
|
||||
import Index from '@custom/basic-call/pages';
|
||||
import getDemoProps from '@custom/shared/lib/demoProps';
|
||||
|
||||
export async function getStaticProps() {
|
||||
const defaultProps = getDemoProps();
|
||||
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
|
||||
import App from '@dailyjs/basic-call/components/App';
|
||||
import Room from '@dailyjs/basic-call/components/Room';
|
||||
import App from '@custom/basic-call/components/App';
|
||||
import Room from '@custom/basic-call/components/Room';
|
||||
import PaginatedVideoGrid from '../PaginatedVideoGrid';
|
||||
|
||||
export const AppWithPagination = () => (
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
### Live example
|
||||
|
||||
**[See it in action here ➡️](https://dailyjs-pagination.vercel.app)**
|
||||
**[See it in action here ➡️](https://custom-pagination.vercel.app)**
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ Please note: this demo is not currently mobile optimised
|
|||
mv env.example .env.local
|
||||
|
||||
yarn
|
||||
yarn workspace @dailyjs/live-streaming dev
|
||||
yarn workspace @custom/live-streaming dev
|
||||
```
|
||||
|
||||
Note: this example uses an additional env `MANUAL_TRACK_SUBS=1` that will disable [automatic track management](https://docs.daily.co/reference#%EF%B8%8F-setsubscribetotracksautomatically).
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
import React from 'react';
|
||||
|
||||
import App from '@custom/basic-call/components/App';
|
||||
import Room from '@custom/basic-call/components/Call/Room';
|
||||
import PaginatedVideoGrid from './PaginatedVideoGrid';
|
||||
|
||||
export const AppWithPagination = () => (
|
||||
<App
|
||||
customComponentForState={{
|
||||
room: <Room MainComponent={PaginatedVideoGrid} />,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
export default AppWithPagination;
|
||||
|
|
@ -5,19 +5,19 @@ import React, {
|
|||
useEffect,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { Button } from '@dailyjs/shared/components/Button';
|
||||
import Tile from '@dailyjs/shared/components/Tile';
|
||||
import { Button } from '@custom/shared/components/Button';
|
||||
import Tile from '@custom/shared/components/Tile';
|
||||
import {
|
||||
DEFAULT_ASPECT_RATIO,
|
||||
MEETING_STATE_JOINED,
|
||||
} from '@dailyjs/shared/constants';
|
||||
import { useCallState } from '@dailyjs/shared/contexts/CallProvider';
|
||||
import { useParticipants } from '@dailyjs/shared/contexts/ParticipantsProvider';
|
||||
import { isLocalId } from '@dailyjs/shared/contexts/participantsState';
|
||||
import { useActiveSpeaker } from '@dailyjs/shared/hooks/useActiveSpeaker';
|
||||
import { useCamSubscriptions } from '@dailyjs/shared/hooks/useCamSubscriptions';
|
||||
import { ReactComponent as IconArrow } from '@dailyjs/shared/icons/raquo-md.svg';
|
||||
import sortByKey from '@dailyjs/shared/lib/sortByKey';
|
||||
} from '@custom/shared/constants';
|
||||
import { useCallState } from '@custom/shared/contexts/CallProvider';
|
||||
import { useParticipants } from '@custom/shared/contexts/ParticipantsProvider';
|
||||
import { isLocalId } from '@custom/shared/contexts/participantsState';
|
||||
import { useActiveSpeaker } from '@custom/shared/hooks/useActiveSpeaker';
|
||||
import { useCamSubscriptions } from '@custom/shared/hooks/useCamSubscriptions';
|
||||
import { ReactComponent as IconArrow } from '@custom/shared/icons/raquo-md.svg';
|
||||
import sortByKey from '@custom/shared/lib/sortByKey';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useDeepCompareMemo } from 'use-deep-compare';
|
||||
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import React from 'react';
|
||||
|
||||
import { TrayButton } from '@dailyjs/shared/components/Tray';
|
||||
import { useCallState } from '@dailyjs/shared/contexts/CallProvider';
|
||||
import { ReactComponent as IconAdd } from '@dailyjs/shared/icons/add-md.svg';
|
||||
import { TrayButton } from '@custom/shared/components/Tray';
|
||||
import { useCallState } from '@custom/shared/contexts/CallProvider';
|
||||
import { ReactComponent as IconAdd } from '@custom/shared/icons/add-md.svg';
|
||||
|
||||
export const Tray = () => {
|
||||
const { callObject } = useCallState();
|
||||
|
Before Width: | Height: | Size: 714 KiB After Width: | Height: | Size: 714 KiB |
|
|
@ -1,7 +1,7 @@
|
|||
const withPlugins = require('next-compose-plugins');
|
||||
const withTM = require('next-transpile-modules')([
|
||||
'@dailyjs/shared',
|
||||
'@dailyjs/basic-call',
|
||||
'@custom/shared',
|
||||
'@custom/basic-call',
|
||||
]);
|
||||
|
||||
const packageJson = require('./package.json');
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "@dailyjs/pagination",
|
||||
"name": "@custom/pagination",
|
||||
"description": "Basic Call + Pagination",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
|
|
@ -10,8 +10,8 @@
|
|||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@dailyjs/shared": "*",
|
||||
"@dailyjs/basic-call": "*",
|
||||
"@custom/shared": "*",
|
||||
"@custom/basic-call": "*",
|
||||
"next": "^11.0.0",
|
||||
"pluralize": "^8.0.0",
|
||||
"react": "^17.0.2",
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
|
||||
import App from '@dailyjs/basic-call/pages/_app';
|
||||
import App from '@custom/basic-call/pages/_app';
|
||||
import AppWithPagination from '../components/App';
|
||||
|
||||
import Tray from '../components/Tray';
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
import Doc from '@custom/basic-call/pages/_document';
|
||||
|
||||
export default Doc;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import Index from '@dailyjs/basic-call/pages';
|
||||
import getDemoProps from '@dailyjs/shared/lib/demoProps';
|
||||
import Index from '@custom/basic-call/pages';
|
||||
import getDemoProps from '@custom/shared/lib/demoProps';
|
||||
|
||||
export async function getStaticProps() {
|
||||
const defaultProps = getDemoProps();
|
||||
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
|
|
@ -22,7 +22,7 @@ Please note: this demo is not currently mobile optimised
|
|||
mv env.example .env.local
|
||||
|
||||
yarn
|
||||
yarn workspace @dailyjs/recording dev
|
||||
yarn workspace @custom/recording dev
|
||||
```
|
||||
|
||||
### How does this demo work?
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
|
||||
import App from '@dailyjs/basic-call/components/App';
|
||||
import { RecordingProvider } from '../../contexts/RecordingProvider';
|
||||
import App from '@custom/basic-call/components/App';
|
||||
import { RecordingProvider } from '../contexts/RecordingProvider';
|
||||
|
||||
// Extend our basic call app component with the recording context
|
||||
export const AppWithRecording = () => (
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import { Button } from '@dailyjs/shared/components/Button';
|
||||
import { CardBody } from '@dailyjs/shared/components/Card';
|
||||
import Modal from '@dailyjs/shared/components/Modal';
|
||||
import Well from '@dailyjs/shared/components/Well';
|
||||
import { useCallState } from '@dailyjs/shared/contexts/CallProvider';
|
||||
import { useUIState } from '@dailyjs/shared/contexts/UIStateProvider';
|
||||
import Button from '@custom/shared/components/Button';
|
||||
import { CardBody } from '@custom/shared/components/Card';
|
||||
import Modal from '@custom/shared/components/Modal';
|
||||
import Well from '@custom/shared/components/Well';
|
||||
import { useCallState } from '@custom/shared/contexts/CallProvider';
|
||||
import { useUIState } from '@custom/shared/contexts/UIStateProvider';
|
||||
import {
|
||||
RECORDING_COUNTDOWN_1,
|
||||
RECORDING_COUNTDOWN_2,
|
||||
|
|
@ -15,7 +15,7 @@ import {
|
|||
RECORDING_TYPE_CLOUD,
|
||||
RECORDING_UPLOADING,
|
||||
useRecording,
|
||||
} from '../../contexts/RecordingProvider';
|
||||
} from '../contexts/RecordingProvider';
|
||||
|
||||
export const RECORDING_MODAL = 'recording';
|
||||
|
||||
|
|
@ -75,12 +75,13 @@ export const RecordingModal = () => {
|
|||
isOpen={currentModals[RECORDING_MODAL]}
|
||||
onClose={() => closeModal(RECORDING_MODAL)}
|
||||
actions={[
|
||||
<Button fullWidth variant="outline">
|
||||
<Button key="close" fullWidth variant="outline">
|
||||
Close
|
||||
</Button>,
|
||||
<Button
|
||||
fullWidth
|
||||
disabled={!disabled}
|
||||
key="record"
|
||||
onClick={() => handleRecordingClick()}
|
||||
>
|
||||
{renderButtonLabel()}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import React, { useEffect } from 'react';
|
||||
|
||||
import { TrayButton } from '@dailyjs/shared/components/Tray';
|
||||
import { useUIState } from '@dailyjs/shared/contexts/UIStateProvider';
|
||||
import { ReactComponent as IconRecord } from '@dailyjs/shared/icons/record-md.svg';
|
||||
import { TrayButton } from '@custom/shared/components/Tray';
|
||||
import { useUIState } from '@custom/shared/contexts/UIStateProvider';
|
||||
import { ReactComponent as IconRecord } from '@custom/shared/icons/record-md.svg';
|
||||
|
||||
import {
|
||||
RECORDING_ERROR,
|
||||
|
|
@ -10,8 +10,8 @@ import {
|
|||
RECORDING_SAVED,
|
||||
RECORDING_UPLOADING,
|
||||
useRecording,
|
||||
} from '../../contexts/RecordingProvider';
|
||||
import { RECORDING_MODAL } from '../RecordingModal';
|
||||
} from '../contexts/RecordingProvider';
|
||||
import { RECORDING_MODAL } from './RecordingModal';
|
||||
|
||||
export const Tray = () => {
|
||||
const { openModal } = useUIState();
|
||||
|
|
@ -6,13 +6,13 @@ import React, {
|
|||
useState,
|
||||
} from 'react';
|
||||
|
||||
import { useCallState } from '@dailyjs/shared/contexts/CallProvider';
|
||||
import { useParticipants } from '@dailyjs/shared/contexts/ParticipantsProvider';
|
||||
import { useUIState } from '@dailyjs/shared/contexts/UIStateProvider';
|
||||
import { useCallState } from '@custom/shared/contexts/CallProvider';
|
||||
import { useParticipants } from '@custom/shared/contexts/ParticipantsProvider';
|
||||
import { useUIState } from '@custom/shared/contexts/UIStateProvider';
|
||||
import {
|
||||
CALL_STATE_REDIRECTING,
|
||||
CALL_STATE_JOINED,
|
||||
} from '@dailyjs/shared/contexts/useCallMachine';
|
||||
} from '@custom/shared/contexts/useCallMachine';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useDeepCompareEffect } from 'use-deep-compare';
|
||||
|
||||
|
Before Width: | Height: | Size: 281 KiB After Width: | Height: | Size: 281 KiB |
|
|
@ -1,7 +1,7 @@
|
|||
const withPlugins = require('next-compose-plugins');
|
||||
const withTM = require('next-transpile-modules')([
|
||||
'@dailyjs/shared',
|
||||
'@dailyjs/basic-call',
|
||||
'@custom/shared',
|
||||
'@custom/basic-call',
|
||||
]);
|
||||
|
||||
const packageJson = require('./package.json');
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "@dailyjs/recording",
|
||||
"name": "@custom/recording",
|
||||
"description": "Basic Call + Recording",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
|
|
@ -10,8 +10,8 @@
|
|||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@dailyjs/shared": "*",
|
||||
"@dailyjs/basic-call": "*",
|
||||
"@custom/shared": "*",
|
||||
"@custom/basic-call": "*",
|
||||
"next": "^11.0.0",
|
||||
"pluralize": "^8.0.0",
|
||||
"react": "^17.0.2",
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import App from '@dailyjs/basic-call/pages/_app';
|
||||
import App from '@custom/basic-call/pages/_app';
|
||||
import AppWithRecording from '../components/App';
|
||||
|
||||
import { RecordingModal } from '../components/RecordingModal';
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
import Doc from '@custom/basic-call/pages/_document';
|
||||
|
||||
export default Doc;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import Index from '@dailyjs/basic-call/pages';
|
||||
import getDemoProps from '@dailyjs/shared/lib/demoProps';
|
||||
import Index from '@custom/basic-call/pages';
|
||||
import getDemoProps from '@custom/shared/lib/demoProps';
|
||||
|
||||
export async function getStaticProps() {
|
||||
const defaultProps = getDemoProps();
|
||||
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { ReactComponent as IconClose } from '../../icons/close-sm.svg';
|
||||
import { Button } from '../Button';
|
||||
import Button from '../Button';
|
||||
|
||||
export const ASIDE_WIDTH = 380;
|
||||
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
import React, { useCallback, useMemo, useEffect, useState } from 'react';
|
||||
import { Aside } from '@custom/shared/components/Aside';
|
||||
import { useCallState } from '../../contexts/CallProvider';
|
||||
import { useUIState } from '../../contexts/UIStateProvider';
|
||||
import Capsule from '../Capsule';
|
||||
|
||||
export const NETWORK_ASIDE = 'network';
|
||||
|
||||
const NETWORK_QUALITY_LABELS = {
|
||||
low: 'Low',
|
||||
'very-low': 'Very Low',
|
||||
good: 'Good',
|
||||
};
|
||||
|
||||
export const NetworkAside = () => {
|
||||
const { callObject } = useCallState();
|
||||
const { showAside, setShowAside } = useUIState();
|
||||
const [networkStats, setNetworkStats] = useState();
|
||||
|
||||
const updateStats = useCallback(async () => {
|
||||
setNetworkStats(await callObject.getNetworkStats());
|
||||
}, [callObject]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!callObject) {
|
||||
return;
|
||||
}
|
||||
|
||||
updateStats();
|
||||
|
||||
const i = setInterval(updateStats, 2000);
|
||||
|
||||
return () => clearInterval(i);
|
||||
}, [callObject, updateStats]);
|
||||
|
||||
const downloadKbs = useMemo(
|
||||
() =>
|
||||
Math.round(
|
||||
(networkStats?.stats?.latest?.videoRecvBitsPerSecond ?? 0) / 1000
|
||||
),
|
||||
[networkStats]
|
||||
);
|
||||
|
||||
const uploadKbs = useMemo(
|
||||
() =>
|
||||
Math.round(
|
||||
(networkStats?.stats?.latest?.videoSendBitsPerSecond ?? 0) / 1000
|
||||
),
|
||||
[networkStats]
|
||||
);
|
||||
|
||||
if (!showAside || showAside !== NETWORK_ASIDE) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Aside onClose={() => setShowAside(false)}>
|
||||
<div className="network-aside">
|
||||
{networkStats ? (
|
||||
<>
|
||||
<div className="panel">
|
||||
<h4>Packet Loss:</h4>
|
||||
Your network quality is:
|
||||
<Capsule variant="success">
|
||||
{NETWORK_QUALITY_LABELS[networkStats.threshold]}
|
||||
</Capsule>
|
||||
</div>
|
||||
<div className="panel">
|
||||
<h4>Download rate:</h4>
|
||||
{downloadKbs} kbps
|
||||
</div>
|
||||
<div className="panel">
|
||||
<h4>Upload rate:</h4>
|
||||
{uploadKbs} kbps
|
||||
</div>
|
||||
<div className="note">
|
||||
Download and upload rates reflect bandwidth used by this call.
|
||||
Updated every 2 seconds.
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<>Fetching network stats...</>
|
||||
)}
|
||||
<style jsx>{`
|
||||
.panel {
|
||||
background-color: var(--gray-wash);
|
||||
border-radius: var(--radius-sm);
|
||||
padding: var(--spacing-sm);
|
||||
margin: var(--spacing-xxs);
|
||||
}
|
||||
|
||||
.panel h4 {
|
||||
margin: 0 0 var(--spacing-xxs) 0;
|
||||
}
|
||||
|
||||
.note {
|
||||
margin: var(--spacing-xxs);
|
||||
color: var(--text-mid);
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
</Aside>
|
||||
);
|
||||
};
|
||||
|
||||
export default NetworkAside;
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
import React from 'react';
|
||||
import Aside from '@dailyjs/shared/components/Aside';
|
||||
import { ReactComponent as IconCamOff } from '@dailyjs/shared/icons/camera-off-sm.svg';
|
||||
import { ReactComponent as IconCamOn } from '@dailyjs/shared/icons/camera-on-sm.svg';
|
||||
import { ReactComponent as IconMicOff } from '@dailyjs/shared/icons/mic-off-sm.svg';
|
||||
import { ReactComponent as IconMicOn } from '@dailyjs/shared/icons/mic-on-sm.svg';
|
||||
import { Aside } from '@custom/shared/components/Aside';
|
||||
import { ReactComponent as IconCamOff } from '@custom/shared/icons/camera-off-sm.svg';
|
||||
import { ReactComponent as IconCamOn } from '@custom/shared/icons/camera-on-sm.svg';
|
||||
import { ReactComponent as IconMicOff } from '@custom/shared/icons/mic-off-sm.svg';
|
||||
import { ReactComponent as IconMicOn } from '@custom/shared/icons/mic-on-sm.svg';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useCallState } from '../../contexts/CallProvider';
|
||||
import { useParticipants } from '../../contexts/ParticipantsProvider';
|
||||
import { useUIState } from '../../contexts/UIStateProvider';
|
||||
import { Button } from '../Button';
|
||||
import Button from '../Button';
|
||||
|
||||
export const PEOPLE_ASIDE = 'people';
|
||||
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
export { Aside as default } from './Aside';
|
||||
export { Aside } from './Aside';
|
||||
export { PeopleAside } from './PeopleAside';
|
||||
export { NetworkAside } from './NetworkAside';
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
* into into a single audio node using the CombinedAudioTrack component
|
||||
*/
|
||||
import React, { useEffect, useMemo } from 'react';
|
||||
import { useTracks } from '@dailyjs/shared/contexts/TracksProvider';
|
||||
import { useTracks } from '@custom/shared/contexts/TracksProvider';
|
||||
import Bowser from 'bowser';
|
||||
import { Portal } from 'react-portal';
|
||||
import AudioTrack from './AudioTrack';
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
import React, { useRef, useEffect } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
const AudioTrack = ({ track }) => {
|
||||
const audioRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!audioRef.current) return false;
|
||||
let playTimeout;
|
||||
|
||||
const handleCanPlay = () => {
|
||||
playTimeout = setTimeout(() => {
|
||||
console.log('Unable to autoplay audio element');
|
||||
}, 1500);
|
||||
};
|
||||
const handlePlay = () => {
|
||||
clearTimeout(playTimeout);
|
||||
};
|
||||
audioRef.current.addEventListener('canplay', handleCanPlay);
|
||||
audioRef.current.addEventListener('play', handlePlay);
|
||||
audioRef.current.srcObject = new MediaStream([track]);
|
||||
|
||||
const audioEl = audioRef.current;
|
||||
|
||||
return () => {
|
||||
audioEl?.removeEventListener('canplay', handleCanPlay);
|
||||
audioEl?.removeEventListener('play', handlePlay);
|
||||
};
|
||||
}, [track]);
|
||||
|
||||
return track ? (
|
||||
<audio autoPlay playsInline ref={audioRef}>
|
||||
<track kind="captions" />
|
||||
</audio>
|
||||
) : null;
|
||||
};
|
||||
|
||||
AudioTrack.propTypes = {
|
||||
track: PropTypes.object,
|
||||
};
|
||||
|
||||
export default AudioTrack;
|
||||