Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ LABEL maintainer "Alexey Vakulich <[email protected]>"
RUN mkdir -p /app

COPY ./build /app/
COPY ./nginx.conf /etc/nginx/nginx.conf
COPY ./config/nginx/nginx.conf /etc/nginx/nginx.conf

EXPOSE 80

Expand Down
File renamed without changes.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
},
"dependencies": {
"@babel/polyfill": "^7.0.0",
"@ok2ju/simple-multi-peer": "^0.2.0",
"hark": "^1.2.3",
"prop-types": "^15.6.2",
"react": "16.8.0-alpha.1",
Expand All @@ -43,8 +42,9 @@
"react-redux": "^6.0.0",
"react-router": "^4.3.1",
"redux": "^4.0.1",
"redux-saga": "^1.0.0",
"redux-thunk": "^2.3.0",
"socket.io-client": "^2.1.1",
"stanza": "^11.0.1",
"styled-components": "^4.1.3"
},
"devDependencies": {
Expand Down
86 changes: 86 additions & 0 deletions src/actions/API.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import * as Constants from './constants'
import Signal from '../services/signal'
import { getClient } from '../reducers/api'

const fetchConfig = async () => {
return new Promise((resolve) => {
resolve({
// userId: 'admin@localhost',
userId: `admin${Math.floor(Math.random() * 100)}@anon.raven.io`,
displayName: `Guest${Math.floor(Math.random() * 100)}`,
credential: '',
id: '',
signalingUrl: 'ws://localhost:5280/xmpp-websocket/',
iceServers: [{
host: 'stun.l.google.com',
password: '',
port: '19302',
type: 'stun',
username: ''
}, {
host: 'global.stun.twilio.com',
password: '',
port: '3478',
type: 'stun',
username: '',
transport: 'udp'
}]
})
})
}

export const connectionStateChanged = (connectionState) => ({
payload: connectionState,
type: Constants.CONNECTION_STATE_CHANGE
})

const receivedConfig = (configUrl, config, userData) => ({
payload: {
config: config,
configUrl: configUrl,
token: userData
},
type: Constants.RECEIVED_CONFIG
})

const receivedConfigError = () => ({
type: Constants.RECEIVED_CONFIG_ERROR
})

export const connect = (configUrl, userData) =>
async (dispatch, getState) => {
let config
dispatch(connectionStateChanged('connecting'))

try {
config = await fetchConfig(configUrl, userData) // TODO: use guest config here
dispatch(receivedConfig(configUrl, config, userData))
} catch (error) {
dispatch(receivedConfigError(error))
dispatch(connectionStateChanged('failed'))
}

const signalingClient = new Signal(dispatch, getState, {
jid: config.userId,
password: config.credential,
resource: config.id,
wsURL: config.signalingUrl
})

dispatch({
payload: signalingClient,
type: Constants.SIGNALING_CLIENT
})

signalingClient.connect()
}

export const disconnect = () =>
(dispatch, getState) => {
const signal = getClient(getState())
if (signal) {
signal.disconnect()
}

dispatch({ type: Constants.SIGNALING_CLIENT_SHUTDOWN })
}
55 changes: 55 additions & 0 deletions src/actions/Calls.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import * as Constants from './constants'
import { removeAllMedia } from './Media'
import { getClient } from '../reducers/api'
import { getJoinedCalls } from '../reducers/calls'

export const startCall = () => {}
export const endCall = () => {}

export const joinCall = (roomAddress, desiredMedia) =>
(dispatch, getState) => {
dispatch({
payload: {
desiredMedia: desiredMedia,
roomAddress: roomAddress
},
type: Constants.JOIN_CALL
})

const client = getClient(getState())
if (client) {
client.sendRoomPresence(roomAddress)
client.mesh.updateConnections()
}
}

export const leaveCall = (roomAddress) =>
(dispatch, getState) => {
const state = getState()
const originalCalls = getJoinedCalls(state)
dispatch({
payload: {
roomAddress: roomAddress
},
type: Constants.LEAVE_CALL
})
const updatedState = getState()
const remainingCalls = getJoinedCalls(updatedState)
const client = getClient(state)
if (client) {
client.sendRoomPresence(roomAddress)
client.mesh.updateConnections()
// const speaking = Selectors.userIsSpeaking(state)
// if (speaking) {
// client.sendAllCallsSpeakingUpdate(true)
// }
}
if (originalCalls.length > 0 && remainingCalls.length === 0) {
dispatch(removeAllMedia())
}
}

export const pauseCall = () => {}
export const resumeCall = () => {}
export const setDesiredMediaForCall = () => {}
export const updateCallState = () => {}
26 changes: 26 additions & 0 deletions src/actions/Connections.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import * as Constants from './constants'

export const addConnection = (peerAddress, sessionId) => ({
payload: {
id: sessionId,
peerAddress: peerAddress
},
type: Constants.PEER_CONNECTION_ADDED
})

export const removeConnection = (peerAddress, sessionId) => ({
payload: {
id: sessionId,
peerAddress: peerAddress
},
type: Constants.PEER_CONNECTION_REMOVED
})

export const updateConnection = (peerAddress, sessionId, updated) => ({
payload: {
id: sessionId,
peerAddress: peerAddress,
updated: updated
},
type: Constants.PEER_CONNECTION_UPDATED
})
87 changes: 87 additions & 0 deletions src/actions/Devices.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import * as Constants from './constants'

let deviceListener
let devicePollInterval

export const listenForDevices = () =>
(dispatch) => {
if (!navigator.mediaDevices) {
return
}

if (!deviceListener) {
deviceListener = () => {
dispatch(fetchDevices())
}
}

deviceListener()
navigator.mediaDevices.addEventListener('devicechange', deviceListener)
// Safari 12.0 does not emit device change events, but does update its
// list of devices current.
if (window.safari) {
devicePollInterval = setInterval(() => {
if (deviceListener) {
deviceListener()
}
}, 1000)
}
}

export const fetchDevices = () => async (dispatch) => {
if (!navigator.mediaDevices) {
return
}

const devices = await navigator.mediaDevices.enumerateDevices()
dispatch(deviceList(devices))
}

export const stopListeningForDevices = () => {
if (deviceListener) {
navigator.mediaDevices.removeEventListener('devicechange', deviceListener)
deviceListener = undefined
}
if (devicePollInterval) {
clearInterval(devicePollInterval)
devicePollInterval = undefined
}
}

export const deviceList = (devices) => {
devices = devices.filter(function (d) {
// Work around Safari reporting the built-in speakers as a microphone
if (d.kind === 'audioinput' && d.label === 'MacBook Pro Speakers') {
return false
}

return true
})

return {
payload: devices,
type: Constants.DEVICES
}
}

export const cameraPermissionDenied = (error) => ({
payload: {
error: error
},
type: Constants.CAMERA_PERMISSION_DENIED
})

export const microphonePermissionDenied = (error) => ({
payload: {
error: error
},
type: Constants.MICROPHONE_PERMISSION_DENIED
})

export const deviceCaptureRequest = (camera, microphone) => ({
payload: {
camera: camera,
microphone: microphone
},
type: Constants.DEVICE_CAPTURE
})
Loading