React Dialpad
This is a modified version of React Dialpad that I published to quickly change one thing to allow passing props in to the dialer state. Happy Hacking
React Dialpad provides you a simple UI independent of communication platform to create calls and handle incoming calls.
Open demo on two browser windows to see peer-to-peer behaviour.
Install
npm i react-dialpad
Features
Component interaction is achieved in two ways:
- Prop of `onActionInvoked` in order to listen actions invoked by user via UI buttons
- Component methods in order to update component
Props
onActionInvoked(action, data)
Called when an action is invoked by the user by pressing buttons
Params:
- action: One of the following actions
- CALL_STARTED: Invoked when Call button is pressed
- CALL_ENDED: Invoked when the Call End button pressed
- CALL_REPLIED: Invoked when the Call Reply button pressed
- CALL_REJECTED: Invoked when the Call Reject button pressed
- data: Data related to action. e.g. called number for CALL_STARTED action
onStateChanged(state)
Called when any state change has occured. Just for loggin purpose
States:
- DEFAULT:
- CALLING:
- RINGING:
- ON_CALL:
- INCOMING_CALL:
- REPLYING:
- REJECTING:
- ENDING
Methods
Methods can be accessed using Refs
setRinging()
- Navigates to RINGING state.
setOnCall()
- Navigates to ON_CALL state.
endCall()
- Resets to DEFAULT state.
setIncomingCall(contact)
- Navigates to INCOMING_CALL state. contact: { name, number }
Inspired by
https://dribbble.com/shots/2280148-Day-003-Animated-Dial-Pad https://codepen.io/anon/pen/mWvymM
Example Usage
import React from 'react';import Peer from 'peerjs'; import ReactDialpad from 'react-dialpad'; class App extends React.Component { constructor() { super(); this.state = { number: '', }; this.peer = null; this.call = null; this.getUserMedia = this.getUserMedia.bind(this); this.registerCallEvents = this.registerCallEvents.bind(this); this.registerPeerEvents = this.registerPeerEvents.bind(this); this.onActionInvoked = this.onActionInvoked.bind(this); this.onStateChanged = this.onStateChanged.bind(this); this.onCallStarted = this.onCallStarted.bind(this); this.onCallEnded = this.onCallEnded.bind(this); this.onCallReplied = this.onCallReplied.bind(this); this.onCallRejected = this.onCallRejected.bind(this); } componentDidMount() { const number = Date.now().toString().slice(-5); this.setState({ number }); const that = this; this.peer = new Peer(number, { secure: true, port: 443, debug: 3 }); this.registerPeerEvents(this.peer); } getUserMedia() { navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia; return new Promise((resolve, reject) => { navigator.getUserMedia({ video: true, audio: true }, resolve, reject); }); } registerCallEvents(call) { call.on('stream', (remoteStream) => { this.dialpad.setOnCall(); }); call.on('close', () => { this.dialpad.endCall(); }); } registerPeerEvents(peer) { peer.on('call', (call) => { this.call = call; this.dialpad.setIncomingCall({ name: call.peer, number: call.peer }); }); } onActionInvoked(action, data) { switch (action) { case 'CALL_STARTED': this.onCallStarted(data.number); break; case 'CALL_ENDED': this.onCallEnded(); break; case 'CALL_REPLIED': this.onCallReplied(); break; case 'CALL_REJECTED': this.onCallRejected(); break; default: break; } } onStateChanged(state) { console.log('to state', state); } onCallStarted(number) { console.log('Calling...', number); this.getUserMedia().then((stream) => { this.call = this.peer.call(number, stream); this.dialpad.setRinging(); this.registerCallEvents(this.call); }).catch((err) => { console.log('Failed to get local stream', err); }); } onCallEnded() { if (this.call.open) { this.call.close(); } else { this.dialpad.endCall(); } } onCallReplied() { this.getUserMedia().then((stream) => { this.call.answer(stream); // Answer the call with an A/V stream. this.registerCallEvents(this.call); }).catch((err) => { console.log('Failed to get local stream', err); }); } onCallRejected() { if (this.call.open) { this.call.close(); } else { this.dialpad.endCall(); } } render() { const style = { margin: '0 30px', float: 'left', }; return ( <div className="app"> <div style={style}>Your number: {this.state.number}</div> <ReactDialpad style={style} ref={dialpad => (this.dialpad = dialpad)} onActionInvoked={this.onActionInvoked} onStateChanged={this.onStateChanged} /> </div> ); }} export default App;