123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- import {faSquare, faThLarge, faUserFriends} from '@fortawesome/free-solid-svg-icons';
- import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
- import {Room, RoomEvent, setLogLevel, VideoPresets} from 'livekit-client';
- import {DisplayContext, DisplayOptions, LiveKitRoom} from '@livekit/react-components';
- import {useState} from 'react';
- import 'react-aspect-ratio/aspect-ratio.css';
- import {useNavigate, useLocation} from 'react-router-dom';
- // 新增代码
- let currentRoom: Room;
- export const RoomPage = () => {
- const [numParticipants, setNumParticipants] = useState(0);
- const [displayOptions, setDisplayOptions] = useState<DisplayOptions>({
- stageLayout: 'grid',
- showStats: false,
- });
- const navigate = useNavigate();
- const query = new URLSearchParams(useLocation().search);
- const url = query.get('url');
- const token = query.get('token');
- const recorder = query.get('recorder');
- if (!url || !token) {
- return <div>url and token are required</div>;
- }
- const onLeave = () => {
- navigate('/');
- };
- const updateParticipantSize = (room: Room) => {
- setNumParticipants(room.participants.size + 1);
- };
- const onParticipantDisconnected = (room: Room) => {
- updateParticipantSize(room);
- /* Special rule for recorder */
- if (recorder && parseInt(recorder, 10) === 1 && room.participants.size === 0) {
- console.log('END_RECORDING');
- }
- };
- const updateOptions = (options: DisplayOptions) => {
- setDisplayOptions({
- ...displayOptions,
- ...options,
- });
- };
- // 新增代码开始
- const encoder = new TextEncoder();
- const decoder = new TextDecoder();
- const enterText = () => {
- const textField = document.getElementById('entry') as HTMLInputElement;
- const chat = document.getElementById('chat') as HTMLDivElement;
- if (textField.value.trim()) {
- textField.focus();
- const msg = encoder.encode(textField.value);
- currentRoom.localParticipant.publishData(msg, 0);
- chat.innerHTML += `<div style="color:yellow">${currentRoom.localParticipant.identity} (me): ${textField.value}</div>`;
- chat.scrollTop = chat.scrollHeight;
- textField.value = '';
- }
- };
- const handleData = (msg: Uint8Array, participant?: any) => {
- const chat = document.getElementById('chat') as HTMLDivElement;
- const str = decoder.decode(msg);
- let from = 'server';
- if (participant) {
- from = participant.identity;
- }
- chat.innerHTML += `<div>${from}: ${str}</div>`;
- chat.scrollTop = chat.scrollHeight;
- };
- const closeChat = () => {
- const chatArea: any = document.getElementById('chat-area');
- chatArea.style.display = 'none';
- }
- const handleKeydown = (e: any) => {
- if (e.target.value.trim() && e.key === 'Enter') {
- enterText()
- }
- }
- // 新增代码结束
- return (
- <DisplayContext.Provider value={displayOptions}>
- <div className="video-chat">
- <div className="roomContainer">
- <div className="topBar">
- <h2>Zoom Video</h2>
- <div className="right">
- <div>
- <input
- id="showStats"
- type="checkbox"
- onChange={(e) => updateOptions({showStats: e.target.checked})}
- />
- <label htmlFor="showStats">Show Stats</label>
- </div>
- <div>
- <button
- className="iconButton"
- disabled={displayOptions.stageLayout === 'grid'}
- onClick={() => {
- updateOptions({stageLayout: 'grid'});
- }}
- >
- <FontAwesomeIcon height={32} icon={faThLarge}/>
- </button>
- <button
- className="iconButton"
- disabled={displayOptions.stageLayout === 'speaker'}
- onClick={() => {
- updateOptions({stageLayout: 'speaker'});
- }}
- >
- <FontAwesomeIcon height={32} icon={faSquare}/>
- </button>
- </div>
- <div className="participantCount">
- <FontAwesomeIcon icon={faUserFriends}/>
- <span>{numParticipants}</span>
- </div>
- </div>
- </div>
- <LiveKitRoom
- url={url}
- token={token}
- onConnected={(room) => {
- setLogLevel('debug');
- onConnected(room, query);
- room.on(RoomEvent.ParticipantConnected, () => updateParticipantSize(room));
- room.on(RoomEvent.ParticipantDisconnected, () => onParticipantDisconnected(room));
- room.on(RoomEvent.DataReceived, handleData);
- updateParticipantSize(room);
- }}
- roomOptions={{
- adaptiveStream: isSet(query, 'adaptiveStream'),
- dynacast: isSet(query, 'dynacast'),
- publishDefaults: {
- simulcast: isSet(query, 'simulcast'),
- },
- videoCaptureDefaults: {
- resolution: VideoPresets.h720.resolution,
- },
- }}
- onLeave={onLeave}
- />
- </div>
- {
- currentRoom &&
- <div className="chat-area" id="chat-area">
- <div className="title">
- <h2>Chat</h2>
- <div className="close" onClick={closeChat}>x</div>
- </div>
- <div className="chat" id="chat"></div>
- <div className="send">
- <input type="text" className="input" id="entry" placeholder="Enter your message"
- onKeyDown={event => handleKeydown(event)}/>
- <button className="chat-btn" onClick={enterText}>
- Send
- </button>
- </div>
- </div>
- }
- </div>
- </DisplayContext.Provider>
- );
- };
- async function onConnected(room: Room, query: URLSearchParams) {
- // make it easier to debug
- // (window as any).currentRoom = room;
- // 新增代码
- currentRoom = room;
- if (isSet(query, 'audioEnabled')) {
- const audioDeviceId = query.get('audioDeviceId');
- if (audioDeviceId && room.options.audioCaptureDefaults) {
- room.options.audioCaptureDefaults.deviceId = audioDeviceId;
- }
- await room.localParticipant.setMicrophoneEnabled(true);
- }
- if (isSet(query, 'videoEnabled')) {
- const videoDeviceId = query.get('videoDeviceId');
- if (videoDeviceId && room.options.videoCaptureDefaults) {
- room.options.videoCaptureDefaults.deviceId = videoDeviceId;
- }
- await room.localParticipant.setCameraEnabled(true);
- }
- }
- function isSet(query: URLSearchParams, key: string): boolean {
- return query.get(key) === '1' || query.get(key) === 'true';
- }
|