From fea35cefbbc86f18537522da8d6956d46af9dea0 Mon Sep 17 00:00:00 2001 From: Jon Date: Fri, 9 Jul 2021 14:12:04 +0100 Subject: [PATCH] page button styles --- dailyjs/basic-call/.gitignore | 35 ++++++ dailyjs/basic-call/components/Room/Room.js | 1 - .../components/VideoGrid/VideoGrid.js | 4 +- dailyjs/pagination/README.md | 2 +- .../PaginatedVideoGrid/PaginatedVideoGrid.js | 103 +++++++++++------- dailyjs/pagination/components/Tray/Tray.js | 24 ++++ dailyjs/pagination/components/Tray/index.js | 1 + dailyjs/pagination/pages/_app.js | 3 + dailyjs/shared/hooks/usePreferredLayer.js | 11 +- dailyjs/shared/icons/raquo-md.svg | 3 + 10 files changed, 135 insertions(+), 52 deletions(-) create mode 100644 dailyjs/basic-call/.gitignore create mode 100644 dailyjs/pagination/components/Tray/Tray.js create mode 100644 dailyjs/pagination/components/Tray/index.js create mode 100644 dailyjs/shared/icons/raquo-md.svg diff --git a/dailyjs/basic-call/.gitignore b/dailyjs/basic-call/.gitignore new file mode 100644 index 0000000..058f0ec --- /dev/null +++ b/dailyjs/basic-call/.gitignore @@ -0,0 +1,35 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +node_modules +.pnp +.pnp.js + +# testing +/coverage + +# next.js +.next +out + +# production +build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# vercel +.vercel \ No newline at end of file diff --git a/dailyjs/basic-call/components/Room/Room.js b/dailyjs/basic-call/components/Room/Room.js index 4dd639a..13e8ce4 100644 --- a/dailyjs/basic-call/components/Room/Room.js +++ b/dailyjs/basic-call/components/Room/Room.js @@ -54,7 +54,6 @@ export const Room = ({ MainComponent = VideoGrid }) => { overflow: hidden; min-height: 0px; height: 100%; - padding: var(--spacing-xxxs); box-sizing: border-box; } `} diff --git a/dailyjs/basic-call/components/VideoGrid/VideoGrid.js b/dailyjs/basic-call/components/VideoGrid/VideoGrid.js index 1975d5f..744f185 100644 --- a/dailyjs/basic-call/components/VideoGrid/VideoGrid.js +++ b/dailyjs/basic-call/components/VideoGrid/VideoGrid.js @@ -19,7 +19,7 @@ import { useDeepCompareMemo } from 'use-deep-compare'; export const VideoGrid = React.memo( () => { const containerRef = useRef(); - const { participants } = useParticipants(); + const { participants, allParticipants } = useParticipants(); const [dimensions, setDimensions] = useState({ width: 1, height: 1, @@ -106,7 +106,7 @@ export const VideoGrid = React.memo( // Optimise performance by reducing video quality // when more participants join (if in SFU mode) - usePreferredLayer(); + usePreferredLayer(allParticipants); if (!participants.length) { return null; diff --git a/dailyjs/pagination/README.md b/dailyjs/pagination/README.md index 55a599d..733e3b7 100644 --- a/dailyjs/pagination/README.md +++ b/dailyjs/pagination/README.md @@ -25,7 +25,7 @@ yarn yarn workspace @dailyjs/live-streaming dev ``` -Note that this example uses a env `MANUAL_TRACK_SUBS=1` which will disable [automatic track management](https://docs.daily.co/reference#%EF%B8%8F-setsubscribetotracksautomatically). +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). ## How does this example work? diff --git a/dailyjs/pagination/components/PaginatedVideoGrid/PaginatedVideoGrid.js b/dailyjs/pagination/components/PaginatedVideoGrid/PaginatedVideoGrid.js index 9fcafcc..e7be39e 100644 --- a/dailyjs/pagination/components/PaginatedVideoGrid/PaginatedVideoGrid.js +++ b/dailyjs/pagination/components/PaginatedVideoGrid/PaginatedVideoGrid.js @@ -1,5 +1,3 @@ -/* global rtcpeers */ - import React, { useCallback, useMemo, @@ -7,16 +5,19 @@ import React, { useRef, useState, } from 'react'; - +import { Button } from '@dailyjs/shared/components/Button'; import Tile from '@dailyjs/shared/components/Tile'; import { DEFAULT_ASPECT_RATIO } from '@dailyjs/shared/constants'; import { useParticipants } from '@dailyjs/shared/contexts/ParticipantsProvider'; import { useTracks } from '@dailyjs/shared/contexts/TracksProvider'; import { useActiveSpeaker } from '@dailyjs/shared/hooks/useActiveSpeaker'; +import usePreferredLayer from '@dailyjs/shared/hooks/usePreferredLayer'; +import { ReactComponent as IconArrow } from '@dailyjs/shared/icons/raquo-md.svg'; import sortByKey from '@dailyjs/shared/lib/sortByKey'; - +import { debounce } from 'debounce'; import { useDeepCompareMemo } from 'use-deep-compare'; +// --- Constants const MIN_TILE_WIDTH = 280; const MAX_TILES_PER_PAGE = 12; @@ -31,11 +32,13 @@ export const PaginatedVideoGrid = () => { const { updateCamSubscriptions } = useTracks(); + // Memoized participant count (does not include screen shares) const displayableParticipantCount = useMemo( () => participantCount, [participantCount] ); + // Grid size (dictated by screen size) const [dimensions, setDimensions] = useState({ width: 1, height: 1, @@ -69,30 +72,33 @@ export const PaginatedVideoGrid = () => { }; }, []); + // Memoized reference to the max columns and rows possible given screen size const [maxColumns, maxRows] = useMemo(() => { const { width, height } = dimensions; - const columns = Math.max(1, Math.floor(width / MIN_TILE_WIDTH)); const widthPerTile = width / columns; const rows = Math.max(1, Math.floor(height / (widthPerTile * (9 / 16)))); - return [columns, rows]; }, [dimensions]); + // Memoized count of how many tiles can we show per page const pageSize = useMemo( () => Math.min(maxColumns * maxRows, maxTilesPerPage), [maxColumns, maxRows, maxTilesPerPage] ); + // Calc and set the total number of pages as participant count mutates useEffect(() => { setPages(Math.ceil(displayableParticipantCount / pageSize)); }, [pageSize, displayableParticipantCount]); + // Make sure we never see a blank page (if we're on the last page and people leave) useEffect(() => { if (page <= pages) return; setPage(pages); }, [page, pages]); + // Brutishly calculate the dimensions of each tile given the size of the grid const [tileWidth, tileHeight] = useMemo(() => { const { width, height } = dimensions; const n = Math.min(pageSize, displayableParticipantCount); @@ -119,6 +125,7 @@ export const PaginatedVideoGrid = () => { ); }, [dimensions, pageSize, displayableParticipantCount]); + // Memoized array of participants on the current page (those we can see) const visibleParticipants = useMemo( () => participants.length - page * pageSize > 0 @@ -129,6 +136,8 @@ export const PaginatedVideoGrid = () => { /** * Play / pause tracks based on pagination + * Note: we pause adjacent page tracks and unsubscribe from everything else + * Please refer to project README for more information */ const camSubscriptions = useMemo(() => { const maxSubs = 3 * pageSize; @@ -169,40 +178,26 @@ export const PaginatedVideoGrid = () => { }; }, [page, pageSize, participants, visibleParticipants]); + // Update subscriptions when array of subscribed or paused participants mutates + const debouncedUpdate = useCallback( + (subIds, pausedIds) => + debounce(() => updateCamSubscriptions(subIds, pausedIds), 90), + [updateCamSubscriptions] + ); + useEffect(() => { - updateCamSubscriptions( + debouncedUpdate( camSubscriptions?.subscribedIds, camSubscriptions?.pausedIds ); }, [ camSubscriptions?.subscribedIds, camSubscriptions?.pausedIds, - updateCamSubscriptions, + debouncedUpdate, ]); - /** - * Set bandwidth layer based on amount of visible participants - */ - useEffect(() => { - if (typeof rtcpeers === 'undefined' || rtcpeers?.getCurrentType() !== 'sfu') - return; - - const sfu = rtcpeers.soup; - const count = visibleParticipants.length; - - visibleParticipants.forEach(({ id }) => { - if (count < 5) { - // High quality video for calls with < 5 people per page - sfu.setPreferredLayerForTrack(id, 'cam-video', 2); - } else if (count < 10) { - // Medium quality video for calls with < 10 people per page - sfu.setPreferredLayerForTrack(id, 'cam-video', 1); - } else { - // Low quality video for calls with 10 or more people per page - sfu.setPreferredLayerForTrack(id, 'cam-video', 0); - } - }); - }, [visibleParticipants]); + // Set bandwidth layer based on amount of visible participants + usePreferredLayer(visibleParticipants); /** * Handle position updates based on active speaker events @@ -268,17 +263,23 @@ export const PaginatedVideoGrid = () => { return (
- {pages > 1 && page > 1 && ( - - )} +
{tiles}
- {pages > 1 && page < pages && ( - - )} +
); diff --git a/dailyjs/pagination/components/Tray/Tray.js b/dailyjs/pagination/components/Tray/Tray.js new file mode 100644 index 0000000..e04e896 --- /dev/null +++ b/dailyjs/pagination/components/Tray/Tray.js @@ -0,0 +1,24 @@ +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'; + +export const Tray = () => { + const { callObject } = useCallState(); + + return ( + <> + { + callObject.addFakeParticipant(); + }} + > + + + + ); +}; + +export default Tray; diff --git a/dailyjs/pagination/components/Tray/index.js b/dailyjs/pagination/components/Tray/index.js new file mode 100644 index 0000000..100bcc8 --- /dev/null +++ b/dailyjs/pagination/components/Tray/index.js @@ -0,0 +1 @@ +export { Tray as default } from './Tray'; diff --git a/dailyjs/pagination/pages/_app.js b/dailyjs/pagination/pages/_app.js index 2204a2c..5ffe4b9 100644 --- a/dailyjs/pagination/pages/_app.js +++ b/dailyjs/pagination/pages/_app.js @@ -3,6 +3,9 @@ import React from 'react'; import App from '@dailyjs/basic-call/pages/_app'; import AppWithPagination from '../components/App'; +import Tray from '../components/Tray'; + +App.customTrayComponent = ; App.customAppComponent = ; export default App; diff --git a/dailyjs/shared/hooks/usePreferredLayer.js b/dailyjs/shared/hooks/usePreferredLayer.js index 9059976..3da474d 100644 --- a/dailyjs/shared/hooks/usePreferredLayer.js +++ b/dailyjs/shared/hooks/usePreferredLayer.js @@ -1,7 +1,6 @@ /* global rtcpeers */ import { useEffect } from 'react'; -import { useParticipants } from '../contexts/ParticipantsProvider'; /** * This hook will switch between one of the 3 simulcast layers @@ -15,9 +14,7 @@ import { useParticipants } from '../contexts/ParticipantsProvider'; * * Note: this will have no effect when not in SFU mode */ -export const usePreferredLayer = () => { - const { allParticipants } = useParticipants(); - +export const usePreferredLayer = (participants) => { /** * Set bandwidth layer based on amount of visible participants */ @@ -26,9 +23,9 @@ export const usePreferredLayer = () => { return; const sfu = rtcpeers.soup; - const count = allParticipants.length; + const count = participants.length; - allParticipants.forEach(({ id }) => { + participants.forEach(({ id }) => { if (count < 5) { // High quality video for calls with < 5 people per page sfu.setPreferredLayerForTrack(id, 'cam-video', 2); @@ -40,7 +37,7 @@ export const usePreferredLayer = () => { sfu.setPreferredLayerForTrack(id, 'cam-video', 0); } }); - }, [allParticipants]); + }, [participants]); }; export default usePreferredLayer; diff --git a/dailyjs/shared/icons/raquo-md.svg b/dailyjs/shared/icons/raquo-md.svg new file mode 100644 index 0000000..6574767 --- /dev/null +++ b/dailyjs/shared/icons/raquo-md.svg @@ -0,0 +1,3 @@ + + +