StreamList.jsx 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. import React from "react";
  2. import styled from "styled-components";
  3. import useOpenVidu from "./useOpenVidu";
  4. import useLocalStorage from "../../hooks/useLocalStorage";
  5. import LocalStream from "./LocalStream";
  6. import RemoteStream from "./RemoteStream";
  7. const StyledWebConference = styled.div`
  8. position: fixed;
  9. top: 5em;
  10. right: 1em;
  11. bottom: 5.5em;
  12. z-index: 1;
  13. width: 150px;
  14. overflow-y: auto;
  15. overflow-x: hidden;
  16. padding: 0.5em;
  17. & video {
  18. border-radius: 5px;
  19. }
  20. & .local-stream {
  21. position: relative;
  22. & .actions {
  23. position: absolute;
  24. bottom: 2px;
  25. right: 0;
  26. left: 0;
  27. display: flex;
  28. justify-content: center;
  29. }
  30. & button {
  31. padding: 5px;
  32. margin: 5px;
  33. border-radius: 50%;
  34. opacity: 0.5;
  35. width: 30px;
  36. height: 30px;
  37. }
  38. & button.active {
  39. background-color: var(--color-primary);
  40. }
  41. &:hover button {
  42. opacity: 1;
  43. }
  44. }
  45. & .remote-stream {
  46. position: relative;
  47. margin-bottom: 0.5em;
  48. & .name {
  49. position: absolute;
  50. bottom: 0;
  51. left: 0;
  52. right: 0;
  53. padding: 2px 5px;
  54. background-color: #95959540;
  55. text-align: center;
  56. border-radius: 0 0 5px 5px;
  57. }
  58. }
  59. `;
  60. const WebConferenceContent = ({ users }) => {
  61. const { remoteStreams = [], localStream } = useOpenVidu();
  62. const [showLocalVideo, setShowLocalVideo] = useLocalStorage(
  63. "showLocalVideo",
  64. true
  65. );
  66. const [showLocalAudio, setShowLocalAudio] = useLocalStorage(
  67. "showLocalAudio",
  68. true
  69. );
  70. const toggleVideo = React.useCallback(() => {
  71. setShowLocalVideo((prev) => !prev);
  72. }, [setShowLocalVideo]);
  73. const toggleAudio = React.useCallback(() => {
  74. setShowLocalAudio((prev) => !prev);
  75. }, [setShowLocalAudio]);
  76. // const { localUsers: users } = useUsers();
  77. const streamMap = React.useMemo(
  78. () =>
  79. remoteStreams.reduce((acc, stream) => {
  80. acc[stream.data.uid] = stream;
  81. return acc;
  82. }, {}),
  83. [remoteStreams]
  84. );
  85. return (
  86. <StyledWebConference>
  87. {localStream && (
  88. <div className="local-stream">
  89. <LocalStream
  90. stream={localStream}
  91. video={showLocalVideo}
  92. audio={showLocalAudio}
  93. />
  94. <div className="actions">
  95. <button
  96. onClick={toggleVideo}
  97. className={showLocalVideo ? "active" : ""}
  98. >
  99. <img
  100. src={"https://icongr.am/entypo/camera.svg?size=16&color=f9fbfa"}
  101. />
  102. </button>
  103. <button
  104. onClick={toggleAudio}
  105. className={showLocalAudio ? "active" : ""}
  106. >
  107. <img
  108. src={"https://icongr.am/entypo/mic.svg?size=16&color=f9fbfa"}
  109. />
  110. </button>
  111. </div>
  112. </div>
  113. )}
  114. {users.map(
  115. ({ name, uid, color }) =>
  116. streamMap[uid] && (
  117. <div key={uid} className="remote-stream">
  118. <RemoteStream stream={streamMap[uid]} />
  119. <span className="name" style={{ backgroundColor: color }}>
  120. {name}
  121. </span>
  122. </div>
  123. )
  124. )}
  125. </StyledWebConference>
  126. );
  127. };
  128. export default WebConferenceContent;