Give video display as much space as possible (#84)

* Move room tools to top of page to use full width
Allow messages to be hidden while video is displaying
Allow video display to utilise all available width
Track unread messages while they are hidden
* Better portrait behaviour
* Show room controls by default
* Show room controls at same time as app bar
Improve video height calc.

Co-authored-by: Jeremy Kahn <jeremyckahn@gmail.com>
This commit is contained in:
Nasal Daemon 2023-01-24 03:50:14 +00:00 committed by GitHub
parent fcec242194
commit 8493ddade5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 715 additions and 320 deletions

458
package-lock.json generated
View File

@ -13,6 +13,7 @@
"@emotion/styled": "^11.10.0",
"@mui/icons-material": "^5.8.4",
"@mui/material": "^5.9.3",
"@react-hook/window-size": "^3.1.1",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.3.0",
"@testing-library/user-event": "^13.5.0",
@ -117,32 +118,32 @@
}
},
"node_modules/@babel/compat-data": {
"version": "7.18.8",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.8.tgz",
"integrity": "sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ==",
"version": "7.20.10",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.10.tgz",
"integrity": "sha512-sEnuDPpOJR/fcafHMjpcpGN5M2jbUGUHwmuWKM/YdPzeEDJg8bgmbcWQFUfE32MQjti1koACvoPVsDe8Uq+idg==",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/core": {
"version": "7.18.10",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.10.tgz",
"integrity": "sha512-JQM6k6ENcBFKVtWvLavlvi/mPcpYZ3+R+2EySDEMSMbp7Mn4FexlbbJVrx2R7Ijhr01T8gyqrOaABWIOgxeUyw==",
"version": "7.20.12",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.12.tgz",
"integrity": "sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==",
"dependencies": {
"@ampproject/remapping": "^2.1.0",
"@babel/code-frame": "^7.18.6",
"@babel/generator": "^7.18.10",
"@babel/helper-compilation-targets": "^7.18.9",
"@babel/helper-module-transforms": "^7.18.9",
"@babel/helpers": "^7.18.9",
"@babel/parser": "^7.18.10",
"@babel/template": "^7.18.10",
"@babel/traverse": "^7.18.10",
"@babel/types": "^7.18.10",
"@babel/generator": "^7.20.7",
"@babel/helper-compilation-targets": "^7.20.7",
"@babel/helper-module-transforms": "^7.20.11",
"@babel/helpers": "^7.20.7",
"@babel/parser": "^7.20.7",
"@babel/template": "^7.20.7",
"@babel/traverse": "^7.20.12",
"@babel/types": "^7.20.7",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
"json5": "^2.2.1",
"json5": "^2.2.2",
"semver": "^6.3.0"
},
"engines": {
@ -215,11 +216,11 @@
}
},
"node_modules/@babel/generator": {
"version": "7.18.12",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.12.tgz",
"integrity": "sha512-dfQ8ebCN98SvyL7IxNMCUtZQSq5R7kxgN+r8qYTGDmmSion1hX2C0zq2yo1bsCDhXixokv1SAWTZUMYbO/V5zg==",
"version": "7.20.7",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.7.tgz",
"integrity": "sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==",
"dependencies": {
"@babel/types": "^7.18.10",
"@babel/types": "^7.20.7",
"@jridgewell/gen-mapping": "^0.3.2",
"jsesc": "^2.5.1"
},
@ -264,13 +265,14 @@
}
},
"node_modules/@babel/helper-compilation-targets": {
"version": "7.18.9",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz",
"integrity": "sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg==",
"version": "7.20.7",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz",
"integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==",
"dependencies": {
"@babel/compat-data": "^7.18.8",
"@babel/compat-data": "^7.20.5",
"@babel/helper-validator-option": "^7.18.6",
"browserslist": "^4.20.2",
"browserslist": "^4.21.3",
"lru-cache": "^5.1.1",
"semver": "^6.3.0"
},
"engines": {
@ -280,6 +282,14 @@
"@babel/core": "^7.0.0"
}
},
"node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
"integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
"dependencies": {
"yallist": "^3.0.2"
}
},
"node_modules/@babel/helper-compilation-targets/node_modules/semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
@ -288,6 +298,11 @@
"semver": "bin/semver.js"
}
},
"node_modules/@babel/helper-compilation-targets/node_modules/yallist": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
},
"node_modules/@babel/helper-create-class-features-plugin": {
"version": "7.18.9",
"resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.9.tgz",
@ -367,12 +382,12 @@
}
},
"node_modules/@babel/helper-function-name": {
"version": "7.18.9",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.9.tgz",
"integrity": "sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A==",
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz",
"integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==",
"dependencies": {
"@babel/template": "^7.18.6",
"@babel/types": "^7.18.9"
"@babel/template": "^7.18.10",
"@babel/types": "^7.19.0"
},
"engines": {
"node": ">=6.9.0"
@ -412,18 +427,18 @@
}
},
"node_modules/@babel/helper-module-transforms": {
"version": "7.18.9",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz",
"integrity": "sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g==",
"version": "7.20.11",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz",
"integrity": "sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==",
"dependencies": {
"@babel/helper-environment-visitor": "^7.18.9",
"@babel/helper-module-imports": "^7.18.6",
"@babel/helper-simple-access": "^7.18.6",
"@babel/helper-simple-access": "^7.20.2",
"@babel/helper-split-export-declaration": "^7.18.6",
"@babel/helper-validator-identifier": "^7.18.6",
"@babel/template": "^7.18.6",
"@babel/traverse": "^7.18.9",
"@babel/types": "^7.18.9"
"@babel/helper-validator-identifier": "^7.19.1",
"@babel/template": "^7.20.7",
"@babel/traverse": "^7.20.10",
"@babel/types": "^7.20.7"
},
"engines": {
"node": ">=6.9.0"
@ -441,9 +456,9 @@
}
},
"node_modules/@babel/helper-plugin-utils": {
"version": "7.18.9",
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.9.tgz",
"integrity": "sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w==",
"version": "7.20.2",
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz",
"integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==",
"engines": {
"node": ">=6.9.0"
}
@ -481,11 +496,11 @@
}
},
"node_modules/@babel/helper-simple-access": {
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz",
"integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==",
"version": "7.20.2",
"resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz",
"integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==",
"dependencies": {
"@babel/types": "^7.18.6"
"@babel/types": "^7.20.2"
},
"engines": {
"node": ">=6.9.0"
@ -514,17 +529,17 @@
}
},
"node_modules/@babel/helper-string-parser": {
"version": "7.18.10",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz",
"integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==",
"version": "7.19.4",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz",
"integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-identifier": {
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz",
"integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==",
"version": "7.19.1",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz",
"integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==",
"engines": {
"node": ">=6.9.0"
}
@ -552,13 +567,13 @@
}
},
"node_modules/@babel/helpers": {
"version": "7.18.9",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.9.tgz",
"integrity": "sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ==",
"version": "7.20.7",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.7.tgz",
"integrity": "sha512-PBPjs5BppzsGaxHQCDKnZ6Gd9s6xl8bBCluz3vEInLGRJmnZan4F6BYCeqtyXqkk4W5IlPmjK4JlOuZkpJ3xZA==",
"dependencies": {
"@babel/template": "^7.18.6",
"@babel/traverse": "^7.18.9",
"@babel/types": "^7.18.9"
"@babel/template": "^7.20.7",
"@babel/traverse": "^7.20.7",
"@babel/types": "^7.20.7"
},
"engines": {
"node": ">=6.9.0"
@ -578,9 +593,9 @@
}
},
"node_modules/@babel/parser": {
"version": "7.18.11",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.11.tgz",
"integrity": "sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ==",
"version": "7.20.7",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.7.tgz",
"integrity": "sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==",
"bin": {
"parser": "bin/babel-parser.js"
},
@ -1904,31 +1919,31 @@
}
},
"node_modules/@babel/template": {
"version": "7.18.10",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz",
"integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==",
"version": "7.20.7",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz",
"integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==",
"dependencies": {
"@babel/code-frame": "^7.18.6",
"@babel/parser": "^7.18.10",
"@babel/types": "^7.18.10"
"@babel/parser": "^7.20.7",
"@babel/types": "^7.20.7"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/traverse": {
"version": "7.18.11",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.11.tgz",
"integrity": "sha512-TG9PiM2R/cWCAy6BPJKeHzNbu4lPzOSZpeMfeNErskGpTJx6trEvFaVCbDvpcxwy49BKWmEPwiW8mrysNiDvIQ==",
"version": "7.20.12",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.12.tgz",
"integrity": "sha512-MsIbFN0u+raeja38qboyF8TIT7K0BFzz/Yd/77ta4MsUsmP2RAnidIlwq7d5HFQrH/OZJecGV6B71C4zAgpoSQ==",
"dependencies": {
"@babel/code-frame": "^7.18.6",
"@babel/generator": "^7.18.10",
"@babel/generator": "^7.20.7",
"@babel/helper-environment-visitor": "^7.18.9",
"@babel/helper-function-name": "^7.18.9",
"@babel/helper-function-name": "^7.19.0",
"@babel/helper-hoist-variables": "^7.18.6",
"@babel/helper-split-export-declaration": "^7.18.6",
"@babel/parser": "^7.18.11",
"@babel/types": "^7.18.10",
"@babel/parser": "^7.20.7",
"@babel/types": "^7.20.7",
"debug": "^4.1.0",
"globals": "^11.1.0"
},
@ -1937,12 +1952,12 @@
}
},
"node_modules/@babel/types": {
"version": "7.18.10",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.10.tgz",
"integrity": "sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==",
"version": "7.20.7",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz",
"integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==",
"dependencies": {
"@babel/helper-string-parser": "^7.18.10",
"@babel/helper-validator-identifier": "^7.18.6",
"@babel/helper-string-parser": "^7.19.4",
"@babel/helper-validator-identifier": "^7.19.1",
"to-fast-properties": "^2.0.0"
},
"engines": {
@ -4528,6 +4543,57 @@
"resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
"integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="
},
"node_modules/@react-hook/debounce": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@react-hook/debounce/-/debounce-3.0.0.tgz",
"integrity": "sha512-ir/kPrSfAzY12Gre0sOHkZ2rkEmM4fS5M5zFxCi4BnCeXh2nvx9Ujd+U4IGpKCuPA+EQD0pg1eK2NGLvfWejag==",
"dependencies": {
"@react-hook/latest": "^1.0.2"
},
"peerDependencies": {
"react": ">=16.8"
}
},
"node_modules/@react-hook/event": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/@react-hook/event/-/event-1.2.6.tgz",
"integrity": "sha512-JUL5IluaOdn5w5Afpe/puPa1rj8X6udMlQ9dt4hvMuKmTrBS1Ya6sb4sVgvfe2eU4yDuOfAhik8xhbcCekbg9Q==",
"peerDependencies": {
"react": ">=16.8"
}
},
"node_modules/@react-hook/latest": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@react-hook/latest/-/latest-1.0.3.tgz",
"integrity": "sha512-dy6duzl+JnAZcDbNTfmaP3xHiKtbXYOaz3G51MGVljh548Y8MWzTr+PHLOfvpypEVW9zwvl+VyKjbWKEVbV1Rg==",
"peerDependencies": {
"react": ">=16.8"
}
},
"node_modules/@react-hook/throttle": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@react-hook/throttle/-/throttle-2.2.0.tgz",
"integrity": "sha512-LJ5eg+yMV8lXtqK3lR+OtOZ2WH/EfWvuiEEu0M3bhR7dZRfTyEJKxH1oK9uyBxiXPtWXiQggWbZirMCXam51tg==",
"dependencies": {
"@react-hook/latest": "^1.0.2"
},
"peerDependencies": {
"react": ">=16.8"
}
},
"node_modules/@react-hook/window-size": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/@react-hook/window-size/-/window-size-3.1.1.tgz",
"integrity": "sha512-yWnVS5LKnOUIrEsI44oz3bIIUYqflamPL27n+k/PC//PsX/YeWBky09oPeAoc9As6jSH16Wgo8plI+ECZaHk3g==",
"dependencies": {
"@react-hook/debounce": "^3.0.0",
"@react-hook/event": "^1.2.1",
"@react-hook/throttle": "^2.2.0"
},
"peerDependencies": {
"react": ">=16.8"
}
},
"node_modules/@rollup/plugin-babel": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
@ -16620,9 +16686,9 @@
"integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA=="
},
"node_modules/json5": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
"integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"bin": {
"json5": "lib/cli.js"
},
@ -21674,9 +21740,9 @@
}
},
"node_modules/promise": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/promise/-/promise-8.1.0.tgz",
"integrity": "sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q==",
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz",
"integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==",
"dependencies": {
"asap": "~2.0.6"
}
@ -24643,9 +24709,9 @@
}
},
"node_modules/terser": {
"version": "5.14.2",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz",
"integrity": "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==",
"version": "5.16.1",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.16.1.tgz",
"integrity": "sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw==",
"dependencies": {
"@jridgewell/source-map": "^0.3.2",
"acorn": "^8.5.0",
@ -26842,29 +26908,29 @@
}
},
"@babel/compat-data": {
"version": "7.18.8",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.8.tgz",
"integrity": "sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ=="
"version": "7.20.10",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.10.tgz",
"integrity": "sha512-sEnuDPpOJR/fcafHMjpcpGN5M2jbUGUHwmuWKM/YdPzeEDJg8bgmbcWQFUfE32MQjti1koACvoPVsDe8Uq+idg=="
},
"@babel/core": {
"version": "7.18.10",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.10.tgz",
"integrity": "sha512-JQM6k6ENcBFKVtWvLavlvi/mPcpYZ3+R+2EySDEMSMbp7Mn4FexlbbJVrx2R7Ijhr01T8gyqrOaABWIOgxeUyw==",
"version": "7.20.12",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.12.tgz",
"integrity": "sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==",
"requires": {
"@ampproject/remapping": "^2.1.0",
"@babel/code-frame": "^7.18.6",
"@babel/generator": "^7.18.10",
"@babel/helper-compilation-targets": "^7.18.9",
"@babel/helper-module-transforms": "^7.18.9",
"@babel/helpers": "^7.18.9",
"@babel/parser": "^7.18.10",
"@babel/template": "^7.18.10",
"@babel/traverse": "^7.18.10",
"@babel/types": "^7.18.10",
"@babel/generator": "^7.20.7",
"@babel/helper-compilation-targets": "^7.20.7",
"@babel/helper-module-transforms": "^7.20.11",
"@babel/helpers": "^7.20.7",
"@babel/parser": "^7.20.7",
"@babel/template": "^7.20.7",
"@babel/traverse": "^7.20.12",
"@babel/types": "^7.20.7",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
"json5": "^2.2.1",
"json5": "^2.2.2",
"semver": "^6.3.0"
},
"dependencies": {
@ -26912,11 +26978,11 @@
}
},
"@babel/generator": {
"version": "7.18.12",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.12.tgz",
"integrity": "sha512-dfQ8ebCN98SvyL7IxNMCUtZQSq5R7kxgN+r8qYTGDmmSion1hX2C0zq2yo1bsCDhXixokv1SAWTZUMYbO/V5zg==",
"version": "7.20.7",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.7.tgz",
"integrity": "sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==",
"requires": {
"@babel/types": "^7.18.10",
"@babel/types": "^7.20.7",
"@jridgewell/gen-mapping": "^0.3.2",
"jsesc": "^2.5.1"
},
@ -26951,20 +27017,34 @@
}
},
"@babel/helper-compilation-targets": {
"version": "7.18.9",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz",
"integrity": "sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg==",
"version": "7.20.7",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz",
"integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==",
"requires": {
"@babel/compat-data": "^7.18.8",
"@babel/compat-data": "^7.20.5",
"@babel/helper-validator-option": "^7.18.6",
"browserslist": "^4.20.2",
"browserslist": "^4.21.3",
"lru-cache": "^5.1.1",
"semver": "^6.3.0"
},
"dependencies": {
"lru-cache": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
"integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
"requires": {
"yallist": "^3.0.2"
}
},
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
},
"yallist": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
}
}
},
@ -27025,12 +27105,12 @@
}
},
"@babel/helper-function-name": {
"version": "7.18.9",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.9.tgz",
"integrity": "sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A==",
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz",
"integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==",
"requires": {
"@babel/template": "^7.18.6",
"@babel/types": "^7.18.9"
"@babel/template": "^7.18.10",
"@babel/types": "^7.19.0"
}
},
"@babel/helper-hoist-variables": {
@ -27058,18 +27138,18 @@
}
},
"@babel/helper-module-transforms": {
"version": "7.18.9",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz",
"integrity": "sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g==",
"version": "7.20.11",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz",
"integrity": "sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==",
"requires": {
"@babel/helper-environment-visitor": "^7.18.9",
"@babel/helper-module-imports": "^7.18.6",
"@babel/helper-simple-access": "^7.18.6",
"@babel/helper-simple-access": "^7.20.2",
"@babel/helper-split-export-declaration": "^7.18.6",
"@babel/helper-validator-identifier": "^7.18.6",
"@babel/template": "^7.18.6",
"@babel/traverse": "^7.18.9",
"@babel/types": "^7.18.9"
"@babel/helper-validator-identifier": "^7.19.1",
"@babel/template": "^7.20.7",
"@babel/traverse": "^7.20.10",
"@babel/types": "^7.20.7"
}
},
"@babel/helper-optimise-call-expression": {
@ -27081,9 +27161,9 @@
}
},
"@babel/helper-plugin-utils": {
"version": "7.18.9",
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.9.tgz",
"integrity": "sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w=="
"version": "7.20.2",
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz",
"integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ=="
},
"@babel/helper-remap-async-to-generator": {
"version": "7.18.9",
@ -27109,11 +27189,11 @@
}
},
"@babel/helper-simple-access": {
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz",
"integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==",
"version": "7.20.2",
"resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz",
"integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==",
"requires": {
"@babel/types": "^7.18.6"
"@babel/types": "^7.20.2"
}
},
"@babel/helper-skip-transparent-expression-wrappers": {
@ -27133,14 +27213,14 @@
}
},
"@babel/helper-string-parser": {
"version": "7.18.10",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz",
"integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw=="
"version": "7.19.4",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz",
"integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw=="
},
"@babel/helper-validator-identifier": {
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz",
"integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g=="
"version": "7.19.1",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz",
"integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w=="
},
"@babel/helper-validator-option": {
"version": "7.18.6",
@ -27159,13 +27239,13 @@
}
},
"@babel/helpers": {
"version": "7.18.9",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.9.tgz",
"integrity": "sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ==",
"version": "7.20.7",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.7.tgz",
"integrity": "sha512-PBPjs5BppzsGaxHQCDKnZ6Gd9s6xl8bBCluz3vEInLGRJmnZan4F6BYCeqtyXqkk4W5IlPmjK4JlOuZkpJ3xZA==",
"requires": {
"@babel/template": "^7.18.6",
"@babel/traverse": "^7.18.9",
"@babel/types": "^7.18.9"
"@babel/template": "^7.20.7",
"@babel/traverse": "^7.20.7",
"@babel/types": "^7.20.7"
}
},
"@babel/highlight": {
@ -27179,9 +27259,9 @@
}
},
"@babel/parser": {
"version": "7.18.11",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.11.tgz",
"integrity": "sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ=="
"version": "7.20.7",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.7.tgz",
"integrity": "sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg=="
},
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
"version": "7.18.6",
@ -28035,39 +28115,39 @@
}
},
"@babel/template": {
"version": "7.18.10",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz",
"integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==",
"version": "7.20.7",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz",
"integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==",
"requires": {
"@babel/code-frame": "^7.18.6",
"@babel/parser": "^7.18.10",
"@babel/types": "^7.18.10"
"@babel/parser": "^7.20.7",
"@babel/types": "^7.20.7"
}
},
"@babel/traverse": {
"version": "7.18.11",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.11.tgz",
"integrity": "sha512-TG9PiM2R/cWCAy6BPJKeHzNbu4lPzOSZpeMfeNErskGpTJx6trEvFaVCbDvpcxwy49BKWmEPwiW8mrysNiDvIQ==",
"version": "7.20.12",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.12.tgz",
"integrity": "sha512-MsIbFN0u+raeja38qboyF8TIT7K0BFzz/Yd/77ta4MsUsmP2RAnidIlwq7d5HFQrH/OZJecGV6B71C4zAgpoSQ==",
"requires": {
"@babel/code-frame": "^7.18.6",
"@babel/generator": "^7.18.10",
"@babel/generator": "^7.20.7",
"@babel/helper-environment-visitor": "^7.18.9",
"@babel/helper-function-name": "^7.18.9",
"@babel/helper-function-name": "^7.19.0",
"@babel/helper-hoist-variables": "^7.18.6",
"@babel/helper-split-export-declaration": "^7.18.6",
"@babel/parser": "^7.18.11",
"@babel/types": "^7.18.10",
"@babel/parser": "^7.20.7",
"@babel/types": "^7.20.7",
"debug": "^4.1.0",
"globals": "^11.1.0"
}
},
"@babel/types": {
"version": "7.18.10",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.10.tgz",
"integrity": "sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==",
"version": "7.20.7",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz",
"integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==",
"requires": {
"@babel/helper-string-parser": "^7.18.10",
"@babel/helper-validator-identifier": "^7.18.6",
"@babel/helper-string-parser": "^7.19.4",
"@babel/helper-validator-identifier": "^7.19.1",
"to-fast-properties": "^2.0.0"
}
},
@ -29990,6 +30070,44 @@
"resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
"integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="
},
"@react-hook/debounce": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@react-hook/debounce/-/debounce-3.0.0.tgz",
"integrity": "sha512-ir/kPrSfAzY12Gre0sOHkZ2rkEmM4fS5M5zFxCi4BnCeXh2nvx9Ujd+U4IGpKCuPA+EQD0pg1eK2NGLvfWejag==",
"requires": {
"@react-hook/latest": "^1.0.2"
}
},
"@react-hook/event": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/@react-hook/event/-/event-1.2.6.tgz",
"integrity": "sha512-JUL5IluaOdn5w5Afpe/puPa1rj8X6udMlQ9dt4hvMuKmTrBS1Ya6sb4sVgvfe2eU4yDuOfAhik8xhbcCekbg9Q==",
"requires": {}
},
"@react-hook/latest": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@react-hook/latest/-/latest-1.0.3.tgz",
"integrity": "sha512-dy6duzl+JnAZcDbNTfmaP3xHiKtbXYOaz3G51MGVljh548Y8MWzTr+PHLOfvpypEVW9zwvl+VyKjbWKEVbV1Rg==",
"requires": {}
},
"@react-hook/throttle": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@react-hook/throttle/-/throttle-2.2.0.tgz",
"integrity": "sha512-LJ5eg+yMV8lXtqK3lR+OtOZ2WH/EfWvuiEEu0M3bhR7dZRfTyEJKxH1oK9uyBxiXPtWXiQggWbZirMCXam51tg==",
"requires": {
"@react-hook/latest": "^1.0.2"
}
},
"@react-hook/window-size": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/@react-hook/window-size/-/window-size-3.1.1.tgz",
"integrity": "sha512-yWnVS5LKnOUIrEsI44oz3bIIUYqflamPL27n+k/PC//PsX/YeWBky09oPeAoc9As6jSH16Wgo8plI+ECZaHk3g==",
"requires": {
"@react-hook/debounce": "^3.0.0",
"@react-hook/event": "^1.2.1",
"@react-hook/throttle": "^2.2.0"
}
},
"@rollup/plugin-babel": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
@ -38958,9 +39076,9 @@
"integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA=="
},
"json5": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
"integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA=="
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="
},
"jsonfile": {
"version": "6.1.0",
@ -42491,9 +42609,9 @@
}
},
"promise": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/promise/-/promise-8.1.0.tgz",
"integrity": "sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q==",
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz",
"integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==",
"requires": {
"asap": "~2.0.6"
}
@ -44694,9 +44812,9 @@
}
},
"terser": {
"version": "5.14.2",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz",
"integrity": "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==",
"version": "5.16.1",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.16.1.tgz",
"integrity": "sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw==",
"requires": {
"@jridgewell/source-map": "^0.3.2",
"acorn": "^8.5.0",

View File

@ -9,6 +9,7 @@
"@emotion/styled": "^11.10.0",
"@mui/icons-material": "^5.8.4",
"@mui/material": "^5.9.3",
"@react-hook/window-size": "^3.1.1",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.3.0",
"@testing-library/user-event": "^13.5.0",

View File

@ -1,7 +1,8 @@
import { useEffect, useRef } from 'react'
import Paper from '@mui/material/Paper'
import Tooltip from '@mui/material/Tooltip'
import { PeerNameDisplay } from 'components/PeerNameDisplay'
import { getPeerName } from 'components/PeerNameDisplay'
import { VideoStreamType } from 'models/chat'
import { SelectedPeerStream } from './RoomVideoDisplay'
@ -48,7 +49,8 @@ export const PeerVideo = ({
video.srcObject = videoStream
}, [videoRef, videoStream])
const sizePercent = 100 / Math.sqrt(nextPerfectSquare(numberOfVideos - 1))
const cols = Math.sqrt(nextPerfectSquare(numberOfVideos - 1))
const rows = Math.ceil(numberOfVideos / cols)
const handleVideoClick = () => {
onVideoClick?.(userId, videoStreamType, videoStream)
@ -63,22 +65,27 @@ export const PeerVideo = ({
justifyContent: 'center',
mx: 'auto',
overflow: 'auto',
padding: 2,
padding: '0px',
marginBottom: '5px',
marginRight: '5px',
...(selectedPeerStream
? {
height: '100%',
height: 'calc(100% - 5px)',
width: 'calc(100% - 5px)',
}
: {
width: `calc(${sizePercent}% - 1em)`,
height: `calc(${sizePercent}% - 1em)`,
my: 1,
}),
...(selectedPeerStream &&
!isSelectedVideo && {
width: 'min-content',
width: `calc(${100 / cols}% - 5px)`,
height: `calc(${100 / rows}% - 5px)`,
}),
}}
elevation={10}
>
<Tooltip
title={getPeerName(userId)}
placement="top"
componentsProps={{
tooltip: { sx: { position: 'absolute', top: '25px' } },
}}
>
<video
playsInline
@ -91,16 +98,13 @@ export const PeerVideo = ({
marginLeft: 'auto',
marginRight: 'auto',
height: '100%',
width: '100%',
...(isSelfVideo && {
transform: 'rotateY(180deg)',
}),
}}
/>
<PeerNameDisplay
sx={{ textAlign: 'center', display: 'block', marginTop: 1, px: 1 }}
>
{userId}
</PeerNameDisplay>
</Tooltip>
</Paper>
)
}

View File

@ -1,15 +1,18 @@
import Accordion from '@mui/material/Accordion'
import AccordionSummary from '@mui/material/AccordionSummary'
import AccordionDetails from '@mui/material/AccordionDetails'
import { useContext } from 'react'
import { useWindowSize } from '@react-hook/window-size'
import Collapse from '@mui/material/Collapse'
import Zoom from '@mui/material/Zoom'
import Box from '@mui/material/Box'
import Divider from '@mui/material/Divider'
import Typography from '@mui/material/Typography'
import ExpandMoreIcon from '@mui/icons-material/ExpandMore'
import { v4 as uuid } from 'uuid'
import { rtcConfig } from 'config/rtcConfig'
import { trackerUrls } from 'config/trackerUrls'
import { RoomContext } from 'contexts/RoomContext'
import { ShellContext } from 'contexts/ShellContext'
import { MessageForm } from 'components/MessageForm'
import { ChatTranscript } from 'components/ChatTranscript'
@ -19,6 +22,8 @@ import { RoomVideoControls } from './RoomVideoControls'
import { RoomScreenShareControls } from './RoomScreenShareControls'
import { RoomFileUploadControls } from './RoomFileUploadControls'
import { RoomVideoDisplay } from './RoomVideoDisplay'
import { RoomShowMessagesControls } from './RoomShowMessagesControls'
import { RoomHideRoomControls } from './RoomHideRoomControls'
export interface RoomProps {
appId?: string
@ -61,6 +66,13 @@ export function Room({
await sendMessage(message)
}
const showMessages = roomContextValue.isShowingMessages
const { showRoomControls } = useContext(ShellContext)
const [windowWidth, windowHeight] = useWindowSize()
const landscape = windowWidth > windowHeight
return (
<RoomContext.Provider value={roomContextValue}>
<Box
@ -72,7 +84,6 @@ export function Room({
overflow: 'auto',
}}
>
{showVideoDisplay && <RoomVideoDisplay userId={userId} />}
<Box
sx={{
display: 'flex',
@ -81,28 +92,14 @@ export function Room({
overflow: 'auto',
}}
>
<Accordion>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel1a-content"
id="panel1a-header"
>
<Typography
sx={{
color: 'text.secondary',
textAlign: 'center',
flexGrow: 1,
}}
>
Room tools
</Typography>
</AccordionSummary>
<AccordionDetails>
<Collapse in={showRoomControls}>
<Box
sx={{
alignItems: 'flex-start',
display: 'flex',
justifyContent: 'center',
padding: 1,
overflowX: 'auto',
}}
>
<RoomAudioControls peerRoom={peerRoom} />
@ -112,9 +109,40 @@ export function Room({
peerRoom={peerRoom}
onInlineMediaUpload={handleInlineMediaUpload}
/>
<Zoom in={showVideoDisplay} mountOnEnter unmountOnExit>
<span>
<RoomShowMessagesControls />
</span>
</Zoom>
<RoomHideRoomControls />
</Box>
</AccordionDetails>
</Accordion>
</Collapse>
<Box
sx={{
display: 'flex',
flexDirection: landscape ? 'row' : 'column',
height: '100%',
width: '100%',
overflow: 'auto',
}}
>
{showVideoDisplay && (
<RoomVideoDisplay
userId={userId}
width="100%"
height={landscape || !showMessages ? '100%' : '60%'}
/>
)}
{showMessages && (
<Box
sx={{
display: 'flex',
flexDirection: 'column',
flexGrow: '1',
width: showVideoDisplay && landscape ? '400px' : '100%',
height: landscape ? '100%' : '40%',
}}
>
<ChatTranscript
messageLog={messageLog}
userId={userId}
@ -126,6 +154,9 @@ export function Room({
isMessageSending={isMessageSending}
/>
</Box>
)}
</Box>
</Box>
</Box>
</RoomContext.Provider>
)

View File

@ -0,0 +1,34 @@
import { useContext } from 'react'
import Fab from '@mui/material/Fab'
import Tooltip from '@mui/material/Tooltip'
import { ExpandLess } from '@mui/icons-material'
import { Box } from '@mui/material'
import { ShellContext } from 'contexts/ShellContext'
export function RoomHideRoomControls() {
const { setShowRoomControls } = useContext(ShellContext)
return (
<Box
sx={{
alignItems: 'center',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
px: 1,
}}
>
<Tooltip title="Hide controls">
<Fab
color="primary"
aria-label="hide controls"
onClick={() => setShowRoomControls(false)}
>
<ExpandLess />
</Fab>
</Tooltip>
</Box>
)
}

View File

@ -0,0 +1,37 @@
import { useContext } from 'react'
import Fab from '@mui/material/Fab'
import Tooltip from '@mui/material/Tooltip'
import { Comment, CommentsDisabled } from '@mui/icons-material'
import { Badge, Box } from '@mui/material'
import { RoomContext } from 'contexts/RoomContext'
export function RoomShowMessagesControls() {
const { isShowingMessages, setIsShowingMessages, unreadMessages } =
useContext(RoomContext)
return (
<Box
sx={{
alignItems: 'center',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
px: 1,
}}
>
<Tooltip title={isShowingMessages ? 'Hide messages' : 'Show messages'}>
<Fab
color={isShowingMessages ? 'error' : 'success'}
aria-label="show messages"
onClick={() => setIsShowingMessages(!isShowingMessages)}
>
<Badge color="error" badgeContent={unreadMessages}>
{isShowingMessages ? <CommentsDisabled /> : <Comment />}
</Badge>
</Fab>
</Tooltip>
</Box>
)
}

View File

@ -22,9 +22,15 @@ export interface SelectedPeerStream {
export interface RoomVideoDisplayProps {
userId: string
width: string
height: string
}
export const RoomVideoDisplay = ({ userId }: RoomVideoDisplayProps) => {
export const RoomVideoDisplay = ({
userId,
width,
height,
}: RoomVideoDisplayProps) => {
const shellContext = useContext(ShellContext)
const roomContext = useContext(RoomContext)
const [selectedPeerStream, setSelectedPeerStream] =
@ -121,11 +127,12 @@ export const RoomVideoDisplay = ({ userId }: RoomVideoDisplayProps) => {
flexDirection: 'column',
overflow: 'auto',
padding: 1,
width: '85%',
width: { width },
height: { height },
}}
>
{selectedPeerStream && (
<Box sx={{ height: '80%' }}>
<Box sx={{ height: '80%', width: '100%' }}>
<PeerVideo
isSelectedVideo
numberOfVideos={numberOfVideos}

View File

@ -88,6 +88,9 @@ export function useRoom(
_setMessageLog(messages.slice(-messageTranscriptSizeLimit))
}
const [isShowingMessages, setIsShowingMessages] = useState(true)
const [unreadMessages, setUnreadMessages] = useState(0)
const [selfVideoStream, setSelfVideoStream] = useState<MediaStream | null>(
null
)
@ -110,6 +113,9 @@ export function useRoom(
() => ({
isPrivate,
isMessageSending,
isShowingMessages,
setIsShowingMessages,
unreadMessages,
selfVideoStream,
setSelfVideoStream,
peerVideoStreams,
@ -124,6 +130,9 @@ export function useRoom(
[
isPrivate,
isMessageSending,
isShowingMessages,
setIsShowingMessages,
unreadMessages,
selfVideoStream,
setSelfVideoStream,
peerVideoStreams,
@ -168,6 +177,10 @@ export function useRoom(
}
}, [setDoShowPeers])
useEffect(() => {
if (isShowingMessages) setUnreadMessages(0)
}, [isShowingMessages, setUnreadMessages])
const [sendPeerId, receivePeerId] = usePeerRoomAction<string>(
peerRoom,
PeerActions.PEER_NAME
@ -234,7 +247,11 @@ export function useRoom(
receivePeerMessage(message => {
const userSettings = settingsContext.getUserSettings()
if (!tabHasFocus) {
if (!isShowingMessages) {
setUnreadMessages(unreadMessages + 1)
}
if (!tabHasFocus || !isShowingMessages) {
if (userSettings.playSoundOnNewMessage) {
newMessageAudio.play()
}
@ -302,6 +319,8 @@ export function useRoom(
Object.values({ ...peerVideoStreams, ...peerScreenStreams }).length > 0
)
if (!showVideoDisplay && !isShowingMessages) setIsShowingMessages(true)
const handleInlineMediaUpload = async (files: File[]) => {
const fileOfferId = await fileTransfer.offer(files)

View File

@ -1,5 +1,6 @@
import { PropsWithChildren } from 'react'
import Box from '@mui/material/Box'
import Collapse from '@mui/material/Collapse'
import { styled } from '@mui/material/styles'
import { DrawerHeader } from './DrawerHeader'
@ -38,12 +39,14 @@ const Main = styled('main', {
interface RouteContentProps extends PropsWithChildren {
isDrawerOpen: boolean
isPeerListOpen: boolean
showAppBar: boolean
}
export const RouteContent = ({
children,
isDrawerOpen,
isPeerListOpen,
showAppBar,
}: RouteContentProps) => {
return (
<Main
@ -55,7 +58,9 @@ export const RouteContent = ({
width: '100%',
}}
>
<Collapse in={showAppBar} sx={{ flex: 'none' }}>
<DrawerHeader />
</Collapse>
<Box sx={{ overflow: 'auto', flexGrow: 1 }}>{children}</Box>
</Main>
)

View File

@ -40,6 +40,9 @@ export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => {
const [isRoomShareDialogOpen, setIsRoomShareDialogOpen] = useState(false)
const [doShowPeers, setDoShowPeers] = useState(false)
const [alertSeverity, setAlertSeverity] = useState<AlertColor>('info')
const [showAppBar, setShowAppBar] = useState(true)
const [showRoomControls, setShowRoomControls] = useState(true)
const [isFullscreen, setIsFullscreen] = useState(false)
const [title, setTitle] = useState('')
const [alertText, setAlertText] = useState('')
const [numberOfPeers, setNumberOfPeers] = useState(1)
@ -67,6 +70,8 @@ export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => {
tabHasFocus,
setDoShowPeers,
setNumberOfPeers,
showRoomControls,
setShowRoomControls,
setTitle,
showAlert,
isPeerListOpen,
@ -97,6 +102,8 @@ export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => {
tabHasFocus,
setDoShowPeers,
setNumberOfPeers,
showRoomControls,
setShowRoomControls,
setTitle,
showAlert,
audioState,
@ -135,6 +142,57 @@ export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => {
document.title = title
}, [title])
const enterFullscreen = async () => {
const body: any = document.body
try {
if (body.requestFullscreen) {
await body.requestFullscreen()
} else if (body.webkitRequestFullscreen) {
await body.webkitRequestFullscreen()
} else if (body.mozRequestFullScreen) {
await body.mozRequestFullScreen()
} else if (body.msRequestFullscreen) {
await body.msRequestFullscreen()
}
} catch (e) {
// Silence harmless errors
}
}
const exitFullscreen = async () => {
const document: any = window.document
try {
if (document.exitFullscreen) {
await document.exitFullscreen()
} else if (document.webkitExitFullscreen) {
await document.webkitExitFullscreen()
} else if (document.mozCancelFullScreen) {
await document.mozCancelFullScreen()
} else if (document.msExitFullScreen) {
await document.msExitFullScreen()
}
} catch (e) {
// Silence harmless errors
}
}
useEffect(() => {
if (isFullscreen) {
enterFullscreen()
setShowRoomControls(false)
setShowAppBar(false)
} else {
exitFullscreen()
setShowAppBar(true)
setShowRoomControls(true)
}
}, [isFullscreen, setShowRoomControls, setShowAppBar])
useEffect(() => {
if (isFullscreen) setShowAppBar(showRoomControls)
}, [isFullscreen, showRoomControls, setShowAppBar])
useEffect(() => {
const handleFocus = () => {
setTabHasFocus(true)
@ -142,11 +200,16 @@ export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => {
const handleBlur = () => {
setTabHasFocus(false)
}
const handleFullscreen = (event: Event) => {
setIsFullscreen(!!document.fullscreenElement)
}
window.addEventListener('focus', handleFocus)
window.addEventListener('blur', handleBlur)
document.addEventListener('fullscreenchange', handleFullscreen)
return () => {
window.removeEventListener('focus', handleFocus)
window.removeEventListener('blur', handleBlur)
document.removeEventListener('fullscreenchange', handleFullscreen)
}
}, [])
@ -230,7 +293,11 @@ export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => {
numberOfPeers={numberOfPeers}
title={title}
onPeerListClick={handlePeerListClick}
onRoomControlsClick={() => setShowRoomControls(!showRoomControls)}
setIsQRCodeDialogOpen={setIsQRCodeDialogOpen}
showAppBar={showAppBar}
isFullscreen={isFullscreen}
setIsFullscreen={setIsFullscreen}
/>
<Drawer
isDrawerOpen={isDrawerOpen}
@ -245,6 +312,7 @@ export const Shell = ({ appNeedsUpdate, children, userPeerId }: ShellProps) => {
<RouteContent
isDrawerOpen={isDrawerOpen}
isPeerListOpen={isPeerListOpen}
showAppBar={showAppBar}
>
<ErrorBoundary>{children}</ErrorBoundary>
</RouteContent>

View File

@ -1,13 +1,22 @@
import { styled } from '@mui/material/styles'
import MuiAppBar, { AppBarProps as MuiAppBarProps } from '@mui/material/AppBar'
import Toolbar from '@mui/material/Toolbar'
import Typography from '@mui/material/Typography'
import StepIcon from '@mui/material/StepIcon'
import Tooltip from '@mui/material/Tooltip'
import IconButton from '@mui/material/IconButton'
import MenuIcon from '@mui/icons-material/Menu'
import LinkIcon from '@mui/icons-material/Link'
import QrCode2Icon from '@mui/icons-material/QrCode2'
import MuiAppBar, { AppBarProps as MuiAppBarProps } from '@mui/material/AppBar'
import Fab from '@mui/material/Fab'
import StepIcon from '@mui/material/StepIcon'
import Toolbar from '@mui/material/Toolbar'
import Tooltip from '@mui/material/Tooltip'
import Typography from '@mui/material/Typography'
import Slide from '@mui/material/Slide'
import Zoom from '@mui/material/Zoom'
import ExpandMore from '@mui/icons-material/ExpandMore'
import Fullscreen from '@mui/icons-material/Fullscreen'
import FullscreenExit from '@mui/icons-material/FullscreenExit'
import Link from '@mui/icons-material/Link'
import Menu from '@mui/icons-material/Menu'
import QrCode2 from '@mui/icons-material/QrCode2'
import RoomPreferences from '@mui/icons-material/RoomPreferences'
import { drawerWidth } from './Drawer'
import { peerListWidth } from './PeerList'
@ -54,7 +63,11 @@ interface ShellAppBarProps {
numberOfPeers: number
title: string
onPeerListClick: () => void
onRoomControlsClick: () => void
setIsQRCodeDialogOpen: (isOpen: boolean) => void
showAppBar: boolean
isFullscreen: boolean
setIsFullscreen: (isFullscreen: boolean) => void
}
export const ShellAppBar = ({
@ -67,9 +80,16 @@ export const ShellAppBar = ({
numberOfPeers,
title,
onPeerListClick,
onRoomControlsClick,
showAppBar,
isFullscreen,
setIsFullscreen,
}: ShellAppBarProps) => {
const handleQRCodeClick = () => setIsQRCodeDialogOpen(true)
const onClickFullscreen = () => setIsFullscreen(!isFullscreen)
return (
<>
<Slide appear={false} in={showAppBar} mountOnEnter unmountOnExit>
<AppBar
position="fixed"
isDrawerOpen={isDrawerOpen}
@ -91,7 +111,7 @@ export const ShellAppBar = ({
sx={{ mr: 2, ...(isDrawerOpen && { display: 'none' }) }}
onClick={onDrawerOpen}
>
<MenuIcon />
<Menu />
</IconButton>
<Typography
variant="h6"
@ -108,7 +128,7 @@ export const ShellAppBar = ({
aria-label="Copy current URL"
onClick={onLinkButtonClick}
>
<LinkIcon />
<Link />
</IconButton>
</Tooltip>
{doShowPeers ? (
@ -120,7 +140,30 @@ export const ShellAppBar = ({
aria-label="Show QR Code"
onClick={handleQRCodeClick}
>
<QrCode2Icon />
<QrCode2 />
</IconButton>
</Tooltip>
<Tooltip title="Show Room Controls">
<IconButton
size="large"
color="inherit"
aria-label="show room controls"
onClick={onRoomControlsClick}
>
<RoomPreferences />
</IconButton>
</Tooltip>
<Tooltip
title={isFullscreen ? 'Exit fullscreen' : 'Enter fullscreen'}
>
<IconButton
size="large"
edge="end"
color="inherit"
aria-label="fullscreen"
onClick={onClickFullscreen}
>
{isFullscreen ? <FullscreenExit /> : <Fullscreen />}
</IconButton>
</Tooltip>
<Tooltip title="Click to show peer list">
@ -138,5 +181,23 @@ export const ShellAppBar = ({
) : null}
</Toolbar>
</AppBar>
</Slide>
<Zoom
style={{ position: 'absolute', left: '16px', top: '16px' }}
in={!showAppBar}
unmountOnExit
>
<Tooltip title="Show room controls">
<Fab
size="small"
aria-label="show room controls"
color="primary"
onClick={onRoomControlsClick}
>
<ExpandMore />
</Fab>
</Tooltip>
</Zoom>
</>
)
}

View File

@ -4,6 +4,9 @@ import { FileOfferMetadata } from 'models/chat'
interface RoomContextProps {
isPrivate: boolean
isMessageSending: boolean
isShowingMessages: boolean
setIsShowingMessages: Dispatch<SetStateAction<boolean>>
unreadMessages: number
selfVideoStream: MediaStream | null
setSelfVideoStream: Dispatch<SetStateAction<MediaStream | null>>
peerVideoStreams: Record<string, MediaStream>
@ -21,6 +24,9 @@ interface RoomContextProps {
export const RoomContext = createContext<RoomContextProps>({
isPrivate: false,
isMessageSending: false,
isShowingMessages: true,
setIsShowingMessages: () => {},
unreadMessages: 0,
selfVideoStream: null,
setSelfVideoStream: () => {},
peerVideoStreams: {},

View File

@ -8,6 +8,8 @@ interface ShellContextProps {
tabHasFocus: boolean
setDoShowPeers: Dispatch<SetStateAction<boolean>>
setNumberOfPeers: Dispatch<SetStateAction<number>>
showRoomControls: boolean
setShowRoomControls: Dispatch<SetStateAction<boolean>>
setTitle: Dispatch<SetStateAction<string>>
showAlert: (message: string, options?: AlertOptions) => void
roomId?: string
@ -31,6 +33,8 @@ export const ShellContext = createContext<ShellContextProps>({
tabHasFocus: true,
setDoShowPeers: () => {},
setNumberOfPeers: () => {},
showRoomControls: false,
setShowRoomControls: () => {},
setTitle: () => {},
showAlert: () => {},
roomId: undefined,