rendering web app calling tracks

This commit is contained in:
balzack 2025-02-01 22:36:45 -08:00
parent 8a5e634479
commit 666f2cbab0
3 changed files with 75 additions and 49 deletions

View File

@ -37,13 +37,13 @@
.calling {
height: 100%;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
display: flex;
flex-direction: column;
.title {
flex: 1;
position: absolute;
top: 32px;
display: flex;
justify-content: center;
align-items: center;
@ -54,17 +54,17 @@
}
.logo {
flex: 4;
}
.control {
flex: 2;
display: flex;
align-items: center;
justify-content: center;
position: absolute;
max-width: 50%;
height: 50%;
aspect-ratio: 1;
top: 92px;
border-radius: 16px;
}
.buttons {
position: absolute;
bottom: 64px;
display: flex;
flex-direction: row;
padding: 16px;
@ -74,7 +74,8 @@
}
.status {
flex: 1;
position: absolute;
bottom: 32px;
display: flex;
align-items: center;
justify-content: center;

View File

@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react';
import React, { useEffect, useRef, useState } from 'react';
import classes from './Calling.module.css'
import { useCalling } from './useCalling.hook';
import { Card } from '../card/Card';
@ -15,6 +15,8 @@ export function Calling({ callCard }: { callCard: string }) {
const [ignoring, setIgnoring] = useState(false);
const [declining, setDeclining] = useState(false);
const [accepting, setAccepting] = useState(false);
const remote = useRef();
const local = useRef();
const { state, actions } = useCalling();
const showError = () => {
@ -148,6 +150,22 @@ export function Calling({ callCard }: { callCard: string }) {
}
}, [callCard]);
useEffect(() => {
if (local.current) {
local.current.srcObject = state.localStream;
local.current.load();
local.current.play();
}
}, [state.localStream]);
useEffect(() => {
if (remote.current) {
remote.current.srcObject = state.remoteStream;
remote.current.load();
remote.current.play();
}
}, [state.remoteStream]);
const calls = state.calls.map((contact, index) => {
const { callId, card } = contact;
const { name, handle, node, imageUrl } = card;
@ -164,28 +182,39 @@ export function Calling({ callCard }: { callCard: string }) {
return (
<div className={state.calls.length > 0 || connecting || state.calling ? classes.active : classes.inactive}>
{ !state.calling && !connecting && state.calls.length > 0 && (
<div>
{ calls }
</div>
)}
{ !state.calling && connecting && (
<Loader size={48} />
)}
{ state.calling && (
<div className={classes.calling}>
<div className={classes.title}>
{ state.calling.name && (
<Text className={classes.name}>{ state.calling.name }</Text>
)}
{ !state.calling.name && (
<Text className={classes.name}>{ `${state.calling.handle}/${state.calling.node}` }</Text>
)}
<div>
{ !state.calling && !connecting && state.calls.length > 0 && (
<div>
{ calls }
</div>
<div className={classes.logo}>
<Image radius="sm" height="100%" width="auto" fit="container" src={state.calling.imageUrl} />
</div>
<div className={classes.control}>
)}
{ !state.calling && connecting && (
<Loader size={48} />
)}
{ state.calling && (
<div className={classes.calling}>
<div className={classes.title}>
{ state.calling.name && (
<Text className={classes.name}>{ state.calling.name }</Text>
)}
{ !state.calling.name && (
<Text className={classes.name}>{ `${state.calling.handle}/${state.calling.node}` }</Text>
)}
</div>
<div className={classes.logo}>
<Image radius="lg" height="100%" width="auto" fit="contain" src={state.calling.imageUrl} />
</div>
<div className={classes.status}>
{ !state.connected && (
<Text className={classes.label}>{ state.strings.connecting }</Text>
)}
</div>
<div style={{ position: 'absolute', width: '100%', height: '100%', top: 0, left: 0, backgroundColor: '#888888', display: state.remoteVideo ? 'block' : 'none' }}>
<video ref={remote} disablePictureInPicture playsInline autoPlay style={{ width: '100%', height: '100%' }} />
</div>
<div style={{ position: 'absolute', width: state.remoteVideo ? '20%' : '100%', height: state.remoteVideo ? '20%' : '100%', top: 0, left: 0, backgroundColor: '#888888', display: state.localVideo ? 'block' : 'none' }}>
<video ref={local} disablePictureInPicture playsInline autoPlay style={{ width: '100%', height: '100%' }} />
</div>
<div className={classes.buttons}>
<ActionIcon onClick={toggleAudio} disabled={!state.connected} loading={applyingAudio} color={Colors.primary} size="xl">
{ state.audioEnabled && (
@ -206,13 +235,8 @@ export function Calling({ callCard }: { callCard: string }) {
<ActionIcon onClick={end} color={Colors.offsync} size="xl"><IconPhone className={classes.off} /></ActionIcon>
</div>
</div>
<div className={classes.status}>
{ !state.connected && (
<Text className={classes.label}>{ state.strings.connecting }</Text>
)}
</div>
</div>
)}
)}
</div>
</div>
)
}

View File

@ -81,15 +81,15 @@ export function useCalling() {
const audioStream = await getAudioStream(null);
const audioTrack = audioStream.getTracks().find((track: MediaStreamTrack) => track.kind === 'audio');
if (audioTrack) {
localAudio.current = null;
localAudio.current = audioTrack;
}
localVideo.current = null;
localStream.current = new MediaStream();
localStream.current = null;
remoteStream.current = new MediaStream();
if (localAudio.current) {
localAudio.current.enabled = true;
await updatePeer('local_track', localAudio.current);
await updatePeer('local_track', { track: audioTrack, stream: audioStream });
}
updateState({ localStream: localStream.current, remoteStream: remoteStream.current,
audioEnabled: true, videoEnabled: false, localVideo: false, remoteVideo: false, connected: true });
@ -157,11 +157,11 @@ export function useCalling() {
}
}
const peerTrack = async (track: MediaStreamTrack) => {
const peerTrack = async (track: MediaStreamTrack, stream: MediaStream) => {
if (call.current && localStream.current) {
try {
const { peer } = call.current;
peer.addTrack(track, localStream.current);
peer.addTrack(track, stream);
} catch (err) {
console.log(err);
}
@ -189,7 +189,7 @@ export function useCalling() {
}
}
} else if (type === 'local_track') {
await peerTrack(data);
await peerTrack(data.track, data.stream);
} else if (type === 'close' && call.current) {
peerUpdate.current = [];
const { peer, link } = call.current;
@ -339,8 +339,9 @@ export function useCalling() {
const videoTrack = videoStream.getTracks().find((track: MediaStreamTrack) => track.kind === 'video');
if (videoTrack) {
localVideo.current = videoTrack;
updatePeer('local_track', videoTrack);
updateState({ localVideo: true });
localStream.current = videoStream;
updatePeer('local_track', { track: videoTrack, stream: videoStream });
updateState({ localVideo: true, localStream: videoStream });
}
}
if (localVideo.current) {