Merge branch 'live-transcription-postrefactor' into live-transcription
|
|
@ -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",
|
||||
{
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ Thank you for looking into contributing to`daily-demos`! We want these projects
|
|||
|
||||
## Before contributing
|
||||
|
||||
### Run prebuilt-ui locally
|
||||
### Run /prebuilt locally
|
||||
|
||||
Please follow the instructions in `README.md`.
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ _Bug reports_
|
|||
Before creating a new bug report, please do two things:
|
||||
|
||||
1. If you want to report a bug you experienced while on a Daily call, try out these [troubleshooting tips](https://help.daily.co/en/articles/2303117-top-troubleshooting-tips) to see if that takes care of the bug.
|
||||
2. If you're still seeing the error, check to see if somebody else has [already filed the issue](https://github.com/daily-co/daily-demos/issues) before creating a new one.
|
||||
2. If you're still seeing the error, check to see if somebody else has [already filed the issue](https://github.com/daily-demos/examples/issues) before creating a new one.
|
||||
|
||||
If you've done those two things and need to create an issue, we'll ask you to tell us:
|
||||
|
||||
|
|
|
|||
|
|
@ -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,11 +18,11 @@ Please note: these demos are intended as educational resources for using the Dai
|
|||
|
||||
## Contents
|
||||
|
||||
## [Daily JS (Web)](./dailyjs/)
|
||||
## [Custom (Web)](./custom/)
|
||||
|
||||
Examples that showcase the Daily CallObject using our Javascript library
|
||||
Examples that showcase the Daily call object using our Javascript library
|
||||
|
||||
## [Prebuilt UI](./prebuilt-ui)
|
||||
## [Prebuilt UI](./prebuilt)
|
||||
|
||||
Examples that showcase using and customizing the Daily Prebuilt UI
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Daily JS Examples
|
||||
# Custom Examples (Daily JS)
|
||||
|
||||
### [🤙 Basic call](./basic-call)
|
||||
|
||||
|
|
@ -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?
|
||||
|
|
@ -47,7 +47,7 @@ Primary call context that manages Daily call state, participant state and call o
|
|||
**[useCallMachine.js](../shared/contexts/useCallMachine.js)**
|
||||
Abstraction hook that manages Daily call state and error handling
|
||||
|
||||
**[ParticipantProvider.js](../shared/contexts/ParticipantProvider.js)**
|
||||
**[ParticipantsProvider.js](../shared/contexts/ParticipantsProvider.js)**
|
||||
Manages participant state and abstracts common selectors / derived data
|
||||
|
||||
## Deploy your own on Vercel
|
||||
|
|
@ -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>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
# Domain excluding 'https://' and 'daily.co' e.g. 'somedomain'
|
||||
DAILY_DOMAIN=
|
||||
|
||||
# Obtained from https://dashboard.daily.co/developers
|
||||
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');
|
||||
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"name": "@custom/basic-call",
|
||||
"description": "Basic Call Example",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@custom/shared": "*",
|
||||
"next": "^11.1.2",
|
||||
"pluralize": "^8.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-plugin-module-resolver": "^4.1.0",
|
||||
"next-compose-plugins": "^2.2.1",
|
||||
"next-transpile-modules": "^8.0.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 |
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
### Live example
|
||||
|
||||
**[See it in action here ➡️](https://dailyjs-live-streaming.vercel.app)**
|
||||
**[See it in action here ➡️](https://custom-live-streaming.vercel.app)**
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -25,7 +25,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
|
||||
```
|
||||
|
||||
## How does this example work?
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
|
||||
import App from '@dailyjs/basic-call/components/App';
|
||||
import { LiveStreamingProvider } from '../../contexts/LiveStreamingProvider';
|
||||
import App from '@custom/basic-call/components/App';
|
||||
import { LiveStreamingProvider } from '../contexts/LiveStreamingProvider';
|
||||
|
||||
// Extend our basic call app component with the live streaming context
|
||||
export const AppWithLiveStreaming = () => (
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { Button } from '@dailyjs/shared/components/Button';
|
||||
import { CardBody } from '@dailyjs/shared/components/Card';
|
||||
import Field from '@dailyjs/shared/components/Field';
|
||||
import { TextInput, SelectInput } from '@dailyjs/shared/components/Input';
|
||||
import Modal from '@dailyjs/shared/components/Modal';
|
||||
import { Well } from '@dailyjs/shared/components/Well';
|
||||
import { useCallState } from '@dailyjs/shared/contexts/CallProvider';
|
||||
import { useParticipants } from '@dailyjs/shared/contexts/ParticipantsProvider';
|
||||
import { useUIState } from '@dailyjs/shared/contexts/UIStateProvider';
|
||||
import { useLiveStreaming } from '../../contexts/LiveStreamingProvider';
|
||||
import { Button } from '@custom/shared/components/Button';
|
||||
import { CardBody } from '@custom/shared/components/Card';
|
||||
import Field from '@custom/shared/components/Field';
|
||||
import { TextInput, SelectInput } from '@custom/shared/components/Input';
|
||||
import Modal from '@custom/shared/components/Modal';
|
||||
import { Well } from '@custom/shared/components/Well';
|
||||
import { useCallState } from '@custom/shared/contexts/CallProvider';
|
||||
import { useParticipants } from '@custom/shared/contexts/ParticipantsProvider';
|
||||
import { useUIState } from '@custom/shared/contexts/UIStateProvider';
|
||||
import { useLiveStreaming } from '../contexts/LiveStreamingProvider';
|
||||
|
||||
export const LIVE_STREAMING_MODAL = 'live-streaming';
|
||||
|
||||
|
|
@ -55,7 +55,7 @@ export const LiveStreamingModal = () => {
|
|||
isOpen={currentModals[LIVE_STREAMING_MODAL]}
|
||||
onClose={() => closeModal(LIVE_STREAMING_MODAL)}
|
||||
actions={[
|
||||
<Button fullWidth variant="outline">
|
||||
<Button key="close" fullWidth variant="outline">
|
||||
Close
|
||||
</Button>,
|
||||
!isStreaming ? (
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
import React from 'react';
|
||||
|
||||
import { TrayButton } from '@dailyjs/shared/components/Tray';
|
||||
import { useUIState } from '@dailyjs/shared/contexts/UIStateProvider';
|
||||
import { ReactComponent as IconStream } from '@dailyjs/shared/icons/streaming-md.svg';
|
||||
import { TrayButton } from '@custom/shared/components/Tray';
|
||||
import { useUIState } from '@custom/shared/contexts/UIStateProvider';
|
||||
import { ReactComponent as IconStream } from '@custom/shared/icons/streaming-md.svg';
|
||||
|
||||
import { useLiveStreaming } from '../../contexts/LiveStreamingProvider';
|
||||
import { LIVE_STREAMING_MODAL } from '../LiveStreamingModal';
|
||||
import { useLiveStreaming } from '../contexts/LiveStreamingProvider';
|
||||
import { LIVE_STREAMING_MODAL } from './LiveStreamingModal';
|
||||
|
||||
export const Tray = () => {
|
||||
const { openModal } = useUIState();
|
||||
|
|
@ -5,8 +5,8 @@ import React, {
|
|||
useEffect,
|
||||
useCallback,
|
||||
} from 'react';
|
||||
import { useCallState } from '@dailyjs/shared/contexts/CallProvider';
|
||||
import { useUIState } from '@dailyjs/shared/contexts/UIStateProvider';
|
||||
import { useCallState } from '@custom/shared/contexts/CallProvider';
|
||||
import { useUIState } from '@custom/shared/contexts/UIStateProvider';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
export const LiveStreamingContext = createContext();
|
||||
|
Before Width: | Height: | Size: 270 KiB After Width: | Height: | Size: 270 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/live-streaming",
|
||||
"name": "@custom/live-streaming",
|
||||
"description": "Basic Call + Live Streaming",
|
||||
"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 AppWithLiveStreaming from '../components/App';
|
||||
|
||||
import { LiveStreamingModal } from '../components/LiveStreamingModal';
|
||||
|
|
@ -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 |
|
|
@ -0,0 +1,46 @@
|
|||
# Live Transcription
|
||||
|
||||

|
||||
|
||||
### Live example
|
||||
|
||||
**[See it in action here ➡️](https://custom-live-transcription.vercel.app)**
|
||||
|
||||
---
|
||||
|
||||
## What does this demo do?
|
||||
|
||||
- Use `startTranscription()` and `stopTranscription()` methods to create a transcript of a call
|
||||
- Integrates Deepgram transcription service into Daily calls
|
||||
- Listen for incoming transcription messages using the call object `app-message` event
|
||||
- Extend the basic call demo with a transcription provider and aside
|
||||
- Show a notification bubble on transcript tray button when a new message is received
|
||||
|
||||
Please note: this demo is not currently mobile optimised
|
||||
|
||||
### Getting started
|
||||
|
||||
```
|
||||
# set both DAILY_API_KEY and DAILY_DOMAIN
|
||||
mv env.example .env.local
|
||||
|
||||
yarn
|
||||
yarn workspace @custom/live-transcription dev
|
||||
```
|
||||
|
||||
### Setting up transcription
|
||||
|
||||
For testing the transcription service, you will have to register for a Deepgram API key and configure your Daily domain with that key.
|
||||
|
||||
TODO: Add more instructions here, or point to docs when ready.
|
||||
|
||||
## How does this example work?
|
||||
|
||||
In this example we extend the [basic call demo](../basic-call) with the ability to generate transcription of the meeting in real time and log that in a side panel.
|
||||
|
||||
We pass a custom tray object, a custom app object (wrapping the original in a new `TranscriptionProvider`) as well as add our `TranscriptionAside` panel. We also symlink both the `public` and `pages/api` folders from the basic call.
|
||||
|
||||
|
||||
## Deploy your own on Vercel
|
||||
|
||||
[](https://vercel.com/new/daily-co/clone-flow?repository-url=https%3A%2F%2Fgithub.com%2Fdaily-demos%2Fexamples.git&env=DAILY_DOMAIN%2CDAILY_API_KEY&envDescription=Your%20Daily%20domain%20and%20API%20key%20can%20be%20found%20on%20your%20account%20dashboard&envLink=https%3A%2F%2Fdashboard.daily.co&project-name=daily-examples&repo-name=daily-examples)
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import React from 'react';
|
||||
|
||||
import App from '@custom/basic-call/components/App';
|
||||
import { TranscriptionProvider } from '../contexts/TranscriptionProvider';
|
||||
|
||||
// Extend our basic call app component with the Live Transcription context
|
||||
export const AppWithTranscription = () => (
|
||||
<TranscriptionProvider>
|
||||
<App />
|
||||
</TranscriptionProvider>
|
||||
);
|
||||
|
||||
export default AppWithTranscription;
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { Aside } from '@custom/shared/components/Aside';
|
||||
import Button from '@custom/shared/components/Button';
|
||||
import { useCallState } from '@custom/shared/contexts/CallProvider';
|
||||
import { useParticipants } from '@custom/shared/contexts/ParticipantsProvider';
|
||||
import { useUIState } from '@custom/shared/contexts/UIStateProvider';
|
||||
import { useTranscription } from '../contexts/TranscriptionProvider';
|
||||
|
||||
export const TRANSCRIPTION_ASIDE = 'transcription';
|
||||
|
||||
export const TranscriptionAside = () => {
|
||||
const { callObject } = useCallState();
|
||||
const { showAside, setShowAside } = useUIState();
|
||||
const { transcriptionHistory } = useTranscription();
|
||||
const [isTranscribing, setIsTranscribing] = useState(false);
|
||||
const { isOwner } = useParticipants();
|
||||
|
||||
const msgWindowRef = useRef();
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (msgWindowRef.current) {
|
||||
msgWindowRef.current.scrollTop = msgWindowRef.current.scrollHeight;
|
||||
}
|
||||
}, [transcriptionHistory?.length]);
|
||||
|
||||
if (!showAside || showAside !== TRANSCRIPTION_ASIDE) {
|
||||
return null;
|
||||
}
|
||||
|
||||
async function startTranscription() {
|
||||
setIsTranscribing(true);
|
||||
await callObject.startTranscription();
|
||||
}
|
||||
|
||||
async function stopTranscription() {
|
||||
setIsTranscribing(false);
|
||||
await callObject.stopTranscription();
|
||||
}
|
||||
|
||||
return (
|
||||
<Aside onClose={() => setShowAside(false)}>
|
||||
{isOwner && (
|
||||
<div className="owner-actions">
|
||||
|
||||
<Button
|
||||
fullWidth
|
||||
size="tiny"
|
||||
disabled={isTranscribing}
|
||||
onClick={() =>
|
||||
startTranscription()
|
||||
}
|
||||
>
|
||||
{isTranscribing ? 'Transcribing' : 'Start transcribing'}
|
||||
</Button>
|
||||
<Button
|
||||
fullWidth
|
||||
size="tiny"
|
||||
disabled={!isTranscribing}
|
||||
onClick={() =>
|
||||
stopTranscription()
|
||||
}
|
||||
>
|
||||
Stop transcribing
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
<div className="messages-container" ref={msgWindowRef}>
|
||||
{transcriptionHistory.map((msg) => (
|
||||
<div key={msg.id}>
|
||||
<span className="sender">{msg.sender}: </span>
|
||||
<span className="content">{msg.message}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<style jsx>{`
|
||||
.owner-actions {
|
||||
display: flex;
|
||||
font-weight: bold;
|
||||
align-self: center;
|
||||
gap: var(--spacing-xxxs);
|
||||
margin: var(--spacing-xs) var(--spacing-xxs);
|
||||
}
|
||||
.messages-container {
|
||||
flex: 1;
|
||||
overflow-y: scroll;
|
||||
margin-left: var(--spacing-xs);
|
||||
}
|
||||
.messages-container .sender {
|
||||
font-weight: bold;
|
||||
}
|
||||
`}</style>
|
||||
</Aside>
|
||||
);
|
||||
};
|
||||
|
||||
export default TranscriptionAside;
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
import React from 'react';
|
||||
|
||||
import { TrayButton } from '@custom/shared/components/Tray';
|
||||
import { useUIState } from '@custom/shared/contexts/UIStateProvider';
|
||||
import { ReactComponent as IconTranscription } from '@custom/shared/icons/chat-md.svg';
|
||||
import { useTranscription } from '../contexts/TranscriptionProvider';
|
||||
import { TRANSCRIPTION_ASIDE } from './TranscriptionAside';
|
||||
|
||||
export const Tray = () => {
|
||||
const { toggleAside } = useUIState();
|
||||
const { hasNewMessages } = useTranscription();
|
||||
|
||||
return (
|
||||
<TrayButton
|
||||
label="Transcript"
|
||||
bubble={hasNewMessages}
|
||||
onClick={() => {
|
||||
toggleAside(TRANSCRIPTION_ASIDE);
|
||||
}}
|
||||
>
|
||||
<IconTranscription />
|
||||
</TrayButton>
|
||||
);
|
||||
};
|
||||
|
||||
export default Tray;
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
import React, {
|
||||
createContext,
|
||||
useCallback,
|
||||
useContext,
|
||||
useEffect,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { useCallState } from '@custom/shared/contexts/CallProvider';
|
||||
import { nanoid } from 'nanoid';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
export const TranscriptionContext = createContext();
|
||||
|
||||
export const TranscriptionProvider = ({ children }) => {
|
||||
const { callObject } = useCallState();
|
||||
const [transcriptionHistory, setTranscriptionHistory] = useState([]);
|
||||
const [hasNewMessages, setHasNewMessages] = useState(false);
|
||||
const [isTranscribing, setIsTranscribing] = useState(false);
|
||||
|
||||
const handleNewMessage = useCallback(
|
||||
(e) => {
|
||||
const participants = callObject.participants();
|
||||
// Collect only transcription messages, and gather enough
|
||||
// words to be able to post messages at sentence intervals
|
||||
if (e.fromId === 'transcription' && e.data?.is_final) {
|
||||
|
||||
// Get the sender's current display name or the local name
|
||||
const sender = e.data?.session_id !== participants.local.session_id
|
||||
? participants[e.data.session_id].user_name
|
||||
: participants.local.user_name;
|
||||
|
||||
setTranscriptionHistory((oldState) => [
|
||||
...oldState,
|
||||
{ sender, message: e.data.text, id: nanoid() },
|
||||
]);
|
||||
}
|
||||
|
||||
setHasNewMessages(true);
|
||||
},
|
||||
[callObject]
|
||||
);
|
||||
|
||||
const handleTranscriptionStarted = useCallback(() => {
|
||||
console.log('💬 Transcription started');
|
||||
setIsTranscribing(true);
|
||||
}, []);
|
||||
|
||||
const handleTranscriptionStopped = useCallback(() => {
|
||||
console.log('💬 Transcription stopped');
|
||||
setIsTranscribing(false);
|
||||
}, []);
|
||||
|
||||
const handleTranscriptionError = useCallback(() => {
|
||||
console.log('❗ Transcription error!');
|
||||
setIsTranscribing(false);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!callObject) {
|
||||
return false;
|
||||
}
|
||||
|
||||
console.log(`💬 Transcription provider listening for app messages`);
|
||||
|
||||
callObject.on('app-message', handleNewMessage);
|
||||
|
||||
callObject.on('transcription-started', handleTranscriptionStarted);
|
||||
callObject.on('transcription-stopped', handleTranscriptionStopped);
|
||||
callObject.on('transcription-error', handleTranscriptionError);
|
||||
|
||||
return () => callObject.off('app-message', handleNewMessage);
|
||||
}, [callObject, handleNewMessage, handleTranscriptionStarted, handleTranscriptionStopped, handleTranscriptionError]);
|
||||
|
||||
return (
|
||||
<TranscriptionContext.Provider
|
||||
value={{
|
||||
isTranscribing,
|
||||
transcriptionHistory,
|
||||
hasNewMessages,
|
||||
setHasNewMessages,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</TranscriptionContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
TranscriptionProvider.propTypes = {
|
||||
children: PropTypes.node,
|
||||
};
|
||||
|
||||
export const useTranscription = () => useContext(TranscriptionContext);
|
||||
|
|
@ -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,6 +1,6 @@
|
|||
{
|
||||
"name": "@dailyjs/basic-call",
|
||||
"description": "Basic Call Example",
|
||||
"name": "@custom/live-transcription",
|
||||
"description": "Basic Call + Transcription Example",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
|
@ -10,7 +10,8 @@
|
|||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@dailyjs/shared": "*",
|
||||
"@custom/shared": "*",
|
||||
"@custom/basic-call": "*",
|
||||
"next": "^11.0.0",
|
||||
"pluralize": "^8.0.0",
|
||||
"react": "^17.0.2",
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
import React from 'react';
|
||||
import App from '@custom/basic-call/pages/_app';
|
||||
import AppWithTranscription from '../components/App';
|
||||
|
||||
import TranscriptionAside from '../components/TranscriptionAside';
|
||||
import Tray from '../components/Tray';
|
||||
|
||||
App.asides = [TranscriptionAside];
|
||||
App.customAppComponent = <AppWithTranscription />;
|
||||
App.customTrayComponent = <Tray />;
|
||||
|
||||
export default App;
|
||||
|
|
@ -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();
|
||||