188 lines
6.8 KiB
Plaintext
188 lines
6.8 KiB
Plaintext
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
'use client'
|
|
import { CameraIcon, HdIcon, MicrochipIcon, Server, VideoIcon } from 'lucide-react';
|
|
import Peer, { DataConnection } from 'peerjs';
|
|
import React, { ReactNode, useCallback, useEffect, useRef, useState } from 'react'
|
|
|
|
type FlowStateType = {
|
|
color: 'red' | 'blue' | 'green' | 'orange',
|
|
flow: 'MIC' | 'VIDEO' | 'SERVER' | 'NO_PEERS' | 'ROOM',
|
|
loading: boolean
|
|
}
|
|
|
|
export default function WebRTCChatUsingPeer() {
|
|
let mediaStream
|
|
// UI
|
|
|
|
|
|
const peerRef = useRef<Peer>(undefined)
|
|
const [peers, setPeers] = useState<string[]>([])
|
|
|
|
|
|
const connection = useRef<DataConnection>(undefined)
|
|
const videoRef = useRef<HTMLVideoElement>(null)
|
|
// const [mediaStream, setMediaStream] = useState<MediaStream>(null)
|
|
const [received, setReceivved] = useState<string>('')
|
|
const [peerId, setPeerId] = useState<string>('')
|
|
const [theirPeerId, setTheirPeerId] = useState<string>('')
|
|
const [myStream, setMyStream] = useState<MediaStream>(null);
|
|
|
|
const [devices, setDevices] = useState<MediaDeviceInfo[]>([])
|
|
const [selectedDevice, setSelectedDevice] = useState<{ video: { deviceId: { exact: string } }, audio: { deviceId: { exact: string } } }>()
|
|
|
|
const peer = new Peer({
|
|
host: "localhost",
|
|
port: 4000,
|
|
path: "/myapp",
|
|
secure: false, // Use true with HTTPS
|
|
});
|
|
|
|
|
|
useEffect(() => {
|
|
peer.on("open", function (id) {
|
|
setPeerId(id)
|
|
console.log("My peer ID is: " + id);
|
|
});
|
|
}, [])
|
|
|
|
|
|
peer.on('connection', function (conn) {
|
|
console.log(`Got Connection`, conn)
|
|
conn.on("data", function (data) {
|
|
setReceivved(data as string)
|
|
console.log("Received", data);
|
|
});
|
|
conn.send("Hello!");
|
|
});
|
|
// useEffect(() => {
|
|
// // Get user media
|
|
// navigator.mediaDevices.getUserMedia({ video: true, audio: true })
|
|
// .then(stream => {
|
|
// // setMyStream(stream);
|
|
// // if (videoRef.current) {
|
|
// // videoRef.current.srcObject = stream;
|
|
// // }
|
|
// })
|
|
// .catch(err => console.error("Failed to get local stream", err));
|
|
|
|
// // Initialize PeerJS
|
|
// // const peer = new Peer(); // PeerJS manages server connection
|
|
// // currentPeer.current = peer;
|
|
|
|
// peer.on('open', (id) => {
|
|
// setPeerId(id);
|
|
// console.log('My peer ID is:', id);
|
|
// });
|
|
|
|
// // Listen for incoming calls
|
|
// peer.on('call', (call) => {
|
|
// if (myStream) {
|
|
// // Answer the call with your stream
|
|
// call.answer(myStream);
|
|
// call.on('stream', (remoteStream) => {
|
|
// // Show stream in remote video element
|
|
// if (videoRef.current) {
|
|
// videoRef.current.srcObject = remoteStream;
|
|
// }
|
|
// });
|
|
// }
|
|
// });
|
|
|
|
// peer.on('error', (err) => console.error(err));
|
|
|
|
// return () => {
|
|
// if (peer) {
|
|
// peer.destroy();
|
|
// }
|
|
// };
|
|
// }, [myStream]);
|
|
|
|
|
|
// useEffect(() => {
|
|
// const load = async () => {
|
|
// // Load media devices
|
|
// const res = await navigator.mediaDevices.getUserMedia({ video: true, audio: true })
|
|
// // .then(async res =>
|
|
// setDevices(await navigator.mediaDevices.enumerateDevices())
|
|
// // )
|
|
// // setFlowIdx(1)
|
|
// // setFlowIdx(2)
|
|
|
|
// // console.log(await navigator.mediaDevices.enumerateDevices())
|
|
// // console.log(await navigator.mediaDevices.getUserMedia().)
|
|
// }
|
|
// load()
|
|
// peer.on("call", function (call) {
|
|
// alert(`You have a call`)
|
|
// // Answer the call, providing our mediaStream
|
|
// // if (mediaStream) {
|
|
// call.answer(mediaStream);
|
|
|
|
// call.on('stream', (remoteStream) => {
|
|
// // Show stream in remote video element
|
|
// if (videoRef.current) {
|
|
// videoRef.current.srcObject = remoteStream;
|
|
// }
|
|
// });
|
|
// // }
|
|
// });
|
|
// }, [])
|
|
|
|
return (
|
|
<div>
|
|
{JSON.stringify(peerId)}
|
|
<div>
|
|
<b>Settings</b>
|
|
<b>Video</b>
|
|
{devices.filter(a => a.kind === 'videoinput').map(device =>
|
|
<div key={device.deviceId}
|
|
onClick={() => setSelectedDevice((d: any) => {
|
|
return { ...d, video: { deviceId: { exact: device.deviceId } } }
|
|
})}
|
|
className={`${selectedDevice && selectedDevice.video && device.deviceId === selectedDevice?.video.deviceId.exact ? 'bg-green-300' : ''}`}
|
|
>
|
|
{device.label}
|
|
</div>
|
|
)}
|
|
<b>Audio</b>
|
|
{devices.filter(a => a.kind === 'audioinput').map(device =>
|
|
<div key={device.deviceId}
|
|
onClick={() => setSelectedDevice((d: any) => {
|
|
return { ...d, audio: { deviceId: { exact: device.deviceId } } }
|
|
})}
|
|
className={`${selectedDevice && selectedDevice.audio && device.deviceId === selectedDevice?.audio.deviceId.exact ? 'bg-green-300' : ''}`}
|
|
|
|
>
|
|
{device.label}
|
|
</div>
|
|
)}
|
|
</div>
|
|
<input placeholder='Cannect to' onChange={e => setTheirPeerId(e.target.value)} />
|
|
<button onClick={() => {
|
|
console.log(`Connecting`)
|
|
connection.current
|
|
= peer.connect(theirPeerId, {
|
|
|
|
});
|
|
}}>Start</button>
|
|
<button
|
|
className='p-2'
|
|
onClick={() => {
|
|
// const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true });
|
|
|
|
navigator.mediaDevices.getUserMedia(selectedDevice)
|
|
.then(stream => peer.call(theirPeerId, stream))
|
|
// const call = peer.call(theirPeerId, stream);
|
|
|
|
// const stream = await navigator.mediaDevices.getUserMedia({
|
|
// video: { deviceId: { exact: selectedVideoId } }
|
|
// });
|
|
}}
|
|
>Call</button>
|
|
<textarea onChange={e => connection.current?.send(e.target.value)} placeholder='Message' rows={6} />
|
|
{JSON.stringify(received)}
|
|
<video ref={videoRef} />
|
|
</div>
|
|
)
|
|
}
|