mirror of
https://github.com/balzack/databag.git
synced 2025-02-12 03:29:16 +00:00
added muting of audio and video tracks
This commit is contained in:
parent
e6a706e459
commit
8376f75f9c
@ -27,6 +27,7 @@
|
||||
"react-color": "^2.19.3",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-easy-crop": "^4.1.4",
|
||||
"react-icons": "^4.8.0",
|
||||
"react-player": "^2.10.0",
|
||||
"react-resize-detector": "^7.0.0",
|
||||
"react-router-dom": "^6.2.2",
|
||||
|
@ -12,6 +12,8 @@ export function useRingContext() {
|
||||
callStatus: null,
|
||||
localStream: null,
|
||||
remoteStream: null,
|
||||
video: false,
|
||||
audio: false,
|
||||
});
|
||||
const access = useRef(null);
|
||||
|
||||
@ -22,6 +24,9 @@ export function useRingContext() {
|
||||
const ws = useRef(null);
|
||||
const pc = useRef(null);
|
||||
const stream = useRef(null);
|
||||
const accessVideo = useRef(false);
|
||||
const videoTrack = useRef();
|
||||
const audioTrack = useRef();
|
||||
|
||||
const updateState = (value) => {
|
||||
setState((s) => ({ ...s, ...value }))
|
||||
@ -87,9 +92,7 @@ export function useRingContext() {
|
||||
// form peer connection
|
||||
pc.current = new RTCPeerConnection();
|
||||
pc.current.ontrack = (ev) => { //{streams: [stream]}) => {
|
||||
console.log("ADD TRACK", ev);
|
||||
if (!stream.current) {
|
||||
console.log("ADD STREAM");
|
||||
stream.current = new MediaStream();
|
||||
updateState({ remoteStream: stream.current });
|
||||
}
|
||||
@ -119,6 +122,7 @@ console.log("ADD STREAM");
|
||||
try {
|
||||
const signal = JSON.parse(ev.data);
|
||||
if (signal.description) {
|
||||
stream.current = null;
|
||||
if (signal.description.type === 'offer' && pc.current.signalingState !== 'stable') {
|
||||
return; //rudely ignore
|
||||
}
|
||||
@ -142,7 +146,15 @@ console.log("ADD STREAM");
|
||||
// update state to disconnected
|
||||
pc.current.close();
|
||||
calling.current = null;
|
||||
updateState({ calling: null });
|
||||
if (videoTrack.current) {
|
||||
videoTrack.current.stop();
|
||||
videoTrack.current = null;
|
||||
}
|
||||
if (audioTrack.current) {
|
||||
audioTrack.current.stop();
|
||||
audioTrack.current = null;
|
||||
}
|
||||
updateState({ callStatus: null });
|
||||
}
|
||||
ws.current.onopen = async () => {
|
||||
calling.current.state = "connected"
|
||||
@ -181,6 +193,14 @@ console.log("ADD STREAM");
|
||||
console.log(err);
|
||||
}
|
||||
ws.current.close();
|
||||
if (videoTrack.current) {
|
||||
videoTrack.current.stop();
|
||||
videoTrack.current = null;
|
||||
}
|
||||
if (audioTrack.current) {
|
||||
audioTrack.current.stop();
|
||||
audioTrack.current = null;
|
||||
}
|
||||
},
|
||||
call: async (cardId, contactNode, contactToken) => {
|
||||
if (calling.current) {
|
||||
@ -224,7 +244,6 @@ console.log("ADD STREAM");
|
||||
console.log("ADD TRACK", ev);
|
||||
if (!stream.current) {
|
||||
stream.current = new MediaStream();
|
||||
console.log("ADD STREAM");
|
||||
updateState({ remoteStream: stream.current });
|
||||
}
|
||||
stream.current.addTrack(ev.track);
|
||||
@ -243,17 +262,21 @@ console.log("ADD STREAM");
|
||||
}
|
||||
};
|
||||
|
||||
accessVideo.current = false;
|
||||
const stream = await navigator.mediaDevices.getUserMedia({
|
||||
video: true,
|
||||
video: false,
|
||||
audio: true,
|
||||
});
|
||||
updateState({ localStream: stream });
|
||||
updateState({ audio: true, localStream: stream });
|
||||
for (const track of stream.getTracks()) {
|
||||
console.log("ADD TRANSCEIVER TRACK");
|
||||
if (track.kind === 'audio') {
|
||||
audioTrack.current = track;
|
||||
}
|
||||
if (track.kind === 'video') {
|
||||
videoTrack.current = track;
|
||||
}
|
||||
pc.current.addTrack(track);
|
||||
}
|
||||
// const stream = await whiteNoise();
|
||||
// pc.current.addTransceiver(stream.getTracks()[0], {streams: [stream]});
|
||||
|
||||
const protocol = window.location.protocol === 'http:' ? 'ws://' : 'wss://';
|
||||
ws.current = createWebsocket(`${protocol}${window.location.host}/signal`);
|
||||
@ -267,6 +290,9 @@ console.log("ADD TRANSCEIVER TRACK");
|
||||
calling.current.state = 'connected';
|
||||
updateState({ callStatus: "connected" });
|
||||
}
|
||||
if (signal.status === 'closed') {
|
||||
ws.current.close();
|
||||
}
|
||||
}
|
||||
else if (signal.description) {
|
||||
if (signal.description.type === 'offer' && pc.current.signalingState !== 'stable') {
|
||||
@ -293,6 +319,14 @@ console.log("ADD TRANSCEIVER TRACK");
|
||||
clearInterval(ringInterval);
|
||||
clearInterval(aliveInterval);
|
||||
calling.current = null;
|
||||
if (videoTrack.current) {
|
||||
videoTrack.current.stop();
|
||||
videoTrack.current = null;
|
||||
}
|
||||
if (audioTrack.current) {
|
||||
audioTrack.current.stop();
|
||||
audioTrack.current = null;
|
||||
}
|
||||
updateState({ callStatus: null });
|
||||
}
|
||||
ws.current.onopen = () => {
|
||||
@ -305,6 +339,41 @@ console.log("ADD TRANSCEIVER TRACK");
|
||||
ws.current.close();
|
||||
}
|
||||
},
|
||||
enableVideo: async () => {
|
||||
if (!accessVideo.current) {
|
||||
accessVideo.current = true;
|
||||
const stream = await navigator.mediaDevices.getUserMedia({
|
||||
video: true,
|
||||
audio: true,
|
||||
});
|
||||
updateState({ localStream: stream });
|
||||
for (const track of stream.getTracks()) {
|
||||
if (track.kind === 'audio') {
|
||||
audioTrack.current = track;
|
||||
}
|
||||
if (track.kind === 'video') {
|
||||
videoTrack.current = track;
|
||||
}
|
||||
pc.current.addTrack(track);
|
||||
}
|
||||
}
|
||||
else {
|
||||
videoTrack.current.enabled = true;
|
||||
}
|
||||
updateState({ video: true });
|
||||
},
|
||||
disableVideo: async () => {
|
||||
videoTrack.current.enabled = false;
|
||||
updateState({ video: false });
|
||||
},
|
||||
enableAudio: async () => {
|
||||
audioTrack.current.enabled = true;
|
||||
updateState({ audio: true });
|
||||
},
|
||||
disableAudio: async () => {
|
||||
audioTrack.current.enabled = false;
|
||||
updateState({ audio: false });
|
||||
},
|
||||
}
|
||||
|
||||
return { state, actions }
|
||||
|
@ -15,6 +15,7 @@ import { Welcome } from './welcome/Welcome';
|
||||
import { BottomNav } from './bottomNav/BottomNav';
|
||||
import { Logo } from 'logo/Logo';
|
||||
import { EyeInvisibleOutlined, CloseOutlined, PhoneOutlined } from '@ant-design/icons';
|
||||
import { IoVideocamOffOutline, IoVideocamOutline, IoMicOffOutline, IoMicOutline, IoCallOutline } from "react-icons/io5";
|
||||
|
||||
export function Session() {
|
||||
|
||||
@ -307,7 +308,7 @@ export function Session() {
|
||||
</div>
|
||||
</RingingWrapper>
|
||||
</Modal>
|
||||
<Modal centered visible={state.callStatus} footer={null} closable={false} width={callWidth + 12} height={callHeight + 12} bodyStyle={{ paddingBottom: 0, paddingTop: 6, paddingLeft: 6, paddingRight: 6 }}>
|
||||
<Modal centered visible={state.callStatus} footer={null} closable={false} width={callWidth + 12} height={callHeight + 12} bodyStyle={{ paddingBottom: 0, paddingTop: 6, paddingLeft: 6, paddingRight: 6, paddingBottom: 6 }}>
|
||||
<CallingWrapper>
|
||||
{ state.remoteStream && (
|
||||
<video ref={remote} disablepictureinpicture autoPlay style={{ width: '100%', height: '100%' }}
|
||||
@ -319,6 +320,31 @@ export function Session() {
|
||||
complete={() => console.log("VIDEO COMPLETE")} progress={() => console.log("VIDEO PROGRESS")} error={() => console.log("VIDEO ERROR")} waiting={() => console.log("VIDEO WAITING")} />
|
||||
</div>
|
||||
)}
|
||||
<div className="calling-options">
|
||||
{ state.video && (
|
||||
<div className="calling-option" onClick={actions.disableVideo}>
|
||||
<IoVideocamOutline />
|
||||
</div>
|
||||
)}
|
||||
{ !state.video && (
|
||||
<div className="calling-option" onClick={actions.enableVideo}>
|
||||
<IoVideocamOffOutline />
|
||||
</div>
|
||||
)}
|
||||
{ state.audio && (
|
||||
<div className="calling-option" onClick={actions.disableAudio}>
|
||||
<IoMicOutline />
|
||||
</div>
|
||||
)}
|
||||
{ !state.audio && (
|
||||
<div className="calling-option" onClick={actions.enableAudio}>
|
||||
<IoMicOffOutline />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="calling-end" onClick={actions.end}>
|
||||
<IoCallOutline />
|
||||
</div>
|
||||
</CallingWrapper>
|
||||
</Modal>
|
||||
</SessionWrapper>
|
||||
|
@ -53,7 +53,7 @@ export const RingingWrapper = styled.div`
|
||||
background-color: ${Colors.white};
|
||||
border-radius: 16px;
|
||||
margin: 8px;
|
||||
transform: rotate(270deg);
|
||||
transform: rotate(135deg);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@ -73,13 +73,53 @@ export const RingingWrapper = styled.div`
|
||||
`;
|
||||
|
||||
export const CallingWrapper = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.calling-local {
|
||||
width: 33%;
|
||||
height: 33%;
|
||||
bottom: 16px;
|
||||
right: 16px;
|
||||
left: 16px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.calling-end {
|
||||
position: absolute;
|
||||
bottom: 16px;
|
||||
color: ${Colors.white};
|
||||
font-size: 24px;
|
||||
background-color: ${Colors.alert};
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 8px;
|
||||
border-radius: 20px;
|
||||
cursor: pointer;
|
||||
transform: rotate(270deg);
|
||||
}
|
||||
|
||||
.calling-options {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.calling-option {
|
||||
color: ${Colors.white};
|
||||
font-size: 24px;
|
||||
background-color: ${Colors.primary};
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 8px;
|
||||
border-radius: 20px;
|
||||
cursor: pointer;
|
||||
margin-left: 8px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
`;
|
||||
|
||||
|
||||
|
@ -27,6 +27,8 @@ export function useSession() {
|
||||
callStatus: null,
|
||||
localStream: null,
|
||||
remoteStream: null,
|
||||
video: false,
|
||||
audio: false,
|
||||
});
|
||||
|
||||
const app = useContext(AppContext);
|
||||
@ -62,7 +64,7 @@ export function useSession() {
|
||||
}
|
||||
});
|
||||
|
||||
updateState({ ringing, localStream: ring.state.localStream, remoteStream: ring.state.remoteStream, callStatus: ring.state.callStatus });
|
||||
updateState({ ringing, video: ring.state.video, audio: ring.state.audio, localStream: ring.state.localStream, remoteStream: ring.state.remoteStream, callStatus: ring.state.callStatus });
|
||||
}, [ring.state]);
|
||||
|
||||
useEffect(() => {
|
||||
@ -155,6 +157,21 @@ export function useSession() {
|
||||
const { cardId, callId, contactNode, contactToken, calleeToken } = call;
|
||||
ring.actions.accept(cardId, callId, contactNode, contactToken, calleeToken);
|
||||
},
|
||||
end: async () => {
|
||||
ring.actions.end();
|
||||
},
|
||||
enableVideo: async () => {
|
||||
await ring.actions.enableVideo();
|
||||
},
|
||||
disableVideo: async () => {
|
||||
await ring.actions.disableVideo();
|
||||
},
|
||||
enableAudio: async () => {
|
||||
await ring.actions.enableAudio();
|
||||
},
|
||||
disableAudio: async () => {
|
||||
await ring.actions.disableAudio();
|
||||
},
|
||||
};
|
||||
|
||||
return { state, actions };
|
||||
|
@ -9129,6 +9129,11 @@ react-fast-compare@^3.0.1:
|
||||
resolved "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz"
|
||||
integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==
|
||||
|
||||
react-icons@^4.8.0:
|
||||
version "4.8.0"
|
||||
resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.8.0.tgz#621e900caa23b912f737e41be57f27f6b2bff445"
|
||||
integrity sha512-N6+kOLcihDiAnj5Czu637waJqSnwlMNROzVZMhfX68V/9bu9qHaMIJC4UdozWoOk57gahFCNHwVvWzm0MTzRjg==
|
||||
|
||||
react-is@^16.12.0, "react-is@^16.12.0 || ^17.0.0 || ^18.0.0", react-is@^16.13.1, react-is@^16.7.0:
|
||||
version "16.13.1"
|
||||
resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
|
||||
|
Loading…
Reference in New Issue
Block a user