wip: 0.2.4

还未实现 rtc 握手
This commit is contained in:
loveuer
2025-05-22 17:57:36 +08:00
parent 16e9d663f4
commit 013670b78f
4 changed files with 112 additions and 15 deletions

View File

@ -3,6 +3,7 @@ import {useEffect, useState} from "react";
import {createUseStyles} from "react-jss";
import {useWebsocket} from "../hook/websocket/u-ws.tsx";
import {Resp} from "../interface/response.ts";
import {message} from "../hook/message/u-message.tsx";
const useClass = createUseStyles({
'@global': {
@ -68,6 +69,12 @@ interface Bubble {
angle: number; // 新增角度属性
}
interface WSMessage {
body: Client;
time: number;
type: "enter" | "leave" | "offer" | "answer"
}
interface Client {
client_type: 'desktop' | 'mobile' | 'tablet';
app_type: 'web';
@ -83,6 +90,7 @@ interface Store {
client: Client | null
clients: Client[]
rtc: RTCPeerConnection | null
ch: RTCDataChannel | null
offer: RTCSessionDescription | null
candidate: RTCIceCandidate | null
}
@ -98,6 +106,7 @@ function handleFileChunk(chunk: any) {
console.log("[D] rtc file chunk =", chunk)
}
export const LocalSharing: React.FC = () => {
const classes = useClass();
const [rtcStore, setRTCStore] = useState<Store>({} as Store)
@ -175,6 +184,46 @@ export const LocalSharing: React.FC = () => {
return bubbles;
};
const updateClients = async (room?: string) => {
const res = await fetch(`/api/ulocal/clients?room=${room ? room : rtcStore.client?.room}`)
const jes = await res.json() as Resp<Client[]>
console.log('[D] update clients called, resp =', jes)
setRTCStore(val => {
return {...val, clients: jes.data}
})
}
const handleWSEvent = async (e: MessageEvent) => {
const msg = JSON.parse(e.data) as WSMessage
console.log('[D] ws event msg =', msg)
switch (msg.type) {
case "enter":
await updateClients()
break
case "leave":
await updateClients()
break
case "offer":
console.log('[D] rtc =', rtcStore.rtc)
const offer = JSON.parse(e.data) as { offer: RTCSessionDescriptionInit, id: number, room: string }
console.log('[D] offer =', offer)
await rtcStore.rtc?.setRemoteDescription(offer.offer)
const answer = await rtcStore.rtc?.createAnswer()
await rtcStore.rtc?.setLocalDescription(answer)
console.log('[D] answer =', answer)
await fetch("/api/ulocal/answer", {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({id: offer.id, room: offer.room, answer: answer})
})
break
case "answer":
// const _answer = JSON.parse(e.data) as { answer: RTCSessionDescriptionInit, id: number, room: string }
// await rtcStore.rtc?.setRemoteDescription(_answer.answer)
// break
}
}
useEffect(() => {
const fn = async () => {
const rtc = new RTCPeerConnection({iceServers: [{urls: "stun:stun.qq.com:3478"}]})
@ -193,12 +242,10 @@ export const LocalSharing: React.FC = () => {
}
})
console.log('[D] rtc step 1')
await waitNegotiationneeded
const candidate: RTCIceCandidate | null = await waitCandidate;
if (!candidate) throw new Error("candidate is null")
console.log('[D] rtc step 2')
const res = await fetch("/api/ulocal/register", {
method: "POST",
@ -206,19 +253,21 @@ export const LocalSharing: React.FC = () => {
body: JSON.stringify({candidate: candidate, offer: rtc.localDescription})
})
const jes = await res.json() as Resp<Client>;
if (!jes.data.id) {
message.error("注册失败")
throw new Error("register failed")
}
setRTCStore(val => {
return {...val, client: jes.data, candidate: candidate, offer: rtc.localDescription}
return {...val, client: jes.data, candidate: candidate, offer: rtc.localDescription, rtc: rtc, ch: dataChannel}
})
const api = `${window.location.protocol === 'https' ? 'wss' : 'ws'}://${window.location.host}/api/ulocal/ws?id=${jes.data.id}`
console.log('[D] websocker url =', api)
connect(api, {})
//console.log('[D] websocket url =', api)
connect(api, {fn: handleWSEvent})
const res2 = await fetch(`/api/ulocal/clients?room=${jes.data.room}`)
const jes2 = await res2.json() as Resp<Client[]>
setRTCStore(val => {
return {...val, clients: jes2.data}
})
await updateClients(jes.data.room)
}
fn()
@ -228,8 +277,15 @@ export const LocalSharing: React.FC = () => {
// 气泡点击处理
const handleBubbleClick = async (id: string) => {
console.log('[D] click bubble!!!', id)
// await link(id)
await fetch('/api/ulocal/offer', {
method: 'POST',
headers: {"Content-Type": "application/json"},
body: JSON.stringify({room: rtcStore.client?.room, id: id, offer: rtcStore.offer})
})
setTimeout(() => {
rtcStore.ch?.send("hello, world")
}, 1000)
};
return <div className={classes.container}>