From edd10bf0347a68fb5bc5b6756b2f91fd147ff7be Mon Sep 17 00:00:00 2001 From: Stefan Otto Date: Fri, 16 Mar 2018 11:20:48 +0100 Subject: [PATCH 1/3] Raise hand first step (no signalling yet) --- app/lib/RoomClient.js | 29 +++++++++++++++++++++++++++ app/lib/components/Room.jsx | 19 ++++++++++++++++++ app/lib/redux/reducers/me.js | 16 +++++++++++++++ app/lib/redux/requestActions.js | 14 +++++++++++++ app/lib/redux/roomClientMiddleware.js | 14 +++++++++++++ app/lib/redux/stateActions.js | 16 +++++++++++++++ app/stylus/components/Room.styl | 4 ++++ 7 files changed, 112 insertions(+) diff --git a/app/lib/RoomClient.js b/app/lib/RoomClient.js index c9ebcf7..833ef3e 100644 --- a/app/lib/RoomClient.js +++ b/app/lib/RoomClient.js @@ -486,6 +486,35 @@ export default class RoomClient }); } + raiseHand() + { + logger.debug('raiseHand()'); + + this._dispatch( + stateActions.setRaiseHandInProgress(true)); + + this._dispatch( + stateActions.setRaiseHandState(true)); + + this._dispatch( + stateActions.setRaiseHandInProgress(false)); + + } + + lowerHand() + { + logger.debug('lowerHand()'); + + this._dispatch( + stateActions.setRaiseHandInProgress(true)); + + this._dispatch( + stateActions.setRaiseHandState(false)); + + this._dispatch( + stateActions.setRaiseHandInProgress(false)); + } + restartIce() { logger.debug('restartIce()'); diff --git a/app/lib/components/Room.jsx b/app/lib/components/Room.jsx index 74284bc..ca0663b 100644 --- a/app/lib/components/Room.jsx +++ b/app/lib/components/Room.jsx @@ -23,6 +23,7 @@ class Room extends React.Component onRoomLinkCopy, onSetAudioMode, onRestartIce, + onToggleHand, onLeaveMeeting } = this.props; @@ -98,6 +99,16 @@ class Room extends React.Component onClick={() => onRestartIce()} /> +
onToggleHand(!me.raiseHand)} + /> +
{ dispatch(requestActions.restartIce()); }, + onToggleHand : (enable) => + { + if (enable) + dispatch(requestActions.raiseHand()); + else + dispatch(requestActions.lowerHand()); + }, onLeaveMeeting : () => { dispatch(requestActions.leaveRoom()); diff --git a/app/lib/redux/reducers/me.js b/app/lib/redux/reducers/me.js index b692b1d..f50d082 100644 --- a/app/lib/redux/reducers/me.js +++ b/app/lib/redux/reducers/me.js @@ -10,6 +10,8 @@ const initialState = webcamInProgress : false, audioOnly : false, audioOnlyInProgress : false, + raiseHand : false, + raiseHandInProgress : false, restartIceInProgress : false }; @@ -70,6 +72,20 @@ const me = (state = initialState, action) => return { ...state, audioOnlyInProgress: flag }; } + case 'SET_RAISE_HAND_STATE': + { + const { enabled } = action.payload; + + return { ...state, raiseHand: enabled }; + } + + case 'SET_RAISE_HAND_STATE_IN_PROGRESS': + { + const { flag } = action.payload; + + return { ...state, raiseHandInProgress: flag }; + } + case 'SET_RESTART_ICE_IN_PROGRESS': { const { flag } = action.payload; diff --git a/app/lib/redux/requestActions.js b/app/lib/redux/requestActions.js index 14210ef..074d315 100644 --- a/app/lib/redux/requestActions.js +++ b/app/lib/redux/requestActions.js @@ -78,6 +78,20 @@ export const disableAudioOnly = () => }; }; +export const raiseHand = () => +{ + return { + type : 'RAISE_HAND' + }; +}; + +export const lowerHand = () => +{ + return { + type : 'LOWER_HAND' + }; +}; + export const restartIce = () => { return { diff --git a/app/lib/redux/roomClientMiddleware.js b/app/lib/redux/roomClientMiddleware.js index 271d700..caab57f 100644 --- a/app/lib/redux/roomClientMiddleware.js +++ b/app/lib/redux/roomClientMiddleware.js @@ -102,6 +102,20 @@ export default ({ dispatch, getState }) => (next) => break; } + case 'RAISE_HAND': + { + client.raiseHand(); + + break; + } + + case 'LOWER_HAND': + { + client.lowerHand(); + + break; + } + case 'RESTART_ICE': { client.restartIce(); diff --git a/app/lib/redux/stateActions.js b/app/lib/redux/stateActions.js index bd19225..48fd0d1 100644 --- a/app/lib/redux/stateActions.js +++ b/app/lib/redux/stateActions.js @@ -70,6 +70,22 @@ export const setAudioOnlyInProgress = (flag) => }; }; +export const setRaiseHandState = (enabled) => +{ + return { + type : 'SET_RAISE_HAND_STATE', + payload : { enabled } + }; +}; + +export const setRaiseHandInProgress = (flag) => +{ + return { + type : 'SET_RAISE_HAND_STATE_IN_PROGRESS', + payload : { flag } + }; +}; + export const setRestartIceInProgress = (flag) => { return { diff --git a/app/stylus/components/Room.styl b/app/stylus/components/Room.styl index 5cd6b26..717df68 100644 --- a/app/stylus/components/Room.styl +++ b/app/stylus/components/Room.styl @@ -232,6 +232,10 @@ } } + &.raise-hand { + background-image: url('/resources/images/leave-meeting.svg'); + } + &.leave-meeting { background-image: url('/resources/images/leave-meeting.svg'); } From bd30a54958e099d3308da6892218670ea67ca1cf Mon Sep 17 00:00:00 2001 From: Stefan Otto Date: Tue, 10 Apr 2018 10:51:12 +0200 Subject: [PATCH 2/3] raise-hand works local... --- app/stylus/components/Room.styl | 2 +- server/lib/Room.js | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/app/stylus/components/Room.styl b/app/stylus/components/Room.styl index 717df68..6acc3ba 100644 --- a/app/stylus/components/Room.styl +++ b/app/stylus/components/Room.styl @@ -233,7 +233,7 @@ } &.raise-hand { - background-image: url('/resources/images/leave-meeting.svg'); +// background-image: url('/resources/images/leave-meeting.svg'); } &.leave-meeting { diff --git a/server/lib/Room.js b/server/lib/Room.js index a2bad3f..ec15ab5 100644 --- a/server/lib/Room.js +++ b/server/lib/Room.js @@ -260,6 +260,24 @@ class Room extends EventEmitter break; } + case 'raisehand-message': + { + accept(); + + const { raiseHandMessage } = request.data; + + // Spread to others via protoo. + this._protooRoom.spread( + 'raisehand-message-receive', + { + peerName : protooPeer.id, + raiseHandMessage : raiseHandMessage + }, + [ protooPeer ]); + + break; + } + default: { logger.error('unknown request.method "%s"', request.method); From 63b48ebd71c387fe6396dad1e809140feeaa2f78 Mon Sep 17 00:00:00 2001 From: Stefan Otto Date: Tue, 24 Apr 2018 10:05:54 +0200 Subject: [PATCH 3/3] Raise hand over network - still no state on server (new participants don't get the raised hand state of others until the others change their raised hand state) --- app/lib/RoomClient.js | 59 ++++++++++++------- app/lib/components/Peer.jsx | 4 ++ app/lib/redux/STATE.md | 9 +-- app/lib/redux/reducers/me.js | 8 +-- app/lib/redux/reducers/peers.js | 13 ++++ app/lib/redux/roomClientMiddleware.js | 4 +- app/lib/redux/stateActions.js | 18 ++++-- app/resources/images/icon-hand-black.svg | 26 ++++++++ app/resources/images/icon-hand-white.svg | 26 ++++++++ .../images/icon_remote_raise_hand.svg | 26 ++++++++ app/stylus/components/Peer.styl | 4 ++ app/stylus/components/Room.styl | 6 +- server/lib/Room.js | 9 ++- 13 files changed, 173 insertions(+), 39 deletions(-) create mode 100644 app/resources/images/icon-hand-black.svg create mode 100644 app/resources/images/icon-hand-white.svg create mode 100644 app/resources/images/icon_remote_raise_hand.svg diff --git a/app/lib/RoomClient.js b/app/lib/RoomClient.js index 833ef3e..4a15805 100644 --- a/app/lib/RoomClient.js +++ b/app/lib/RoomClient.js @@ -486,33 +486,41 @@ export default class RoomClient }); } - raiseHand() + sendRaiseHandState(state) { - logger.debug('raiseHand()'); + logger.debug('sendRaiseHandState: ', state); this._dispatch( - stateActions.setRaiseHandInProgress(true)); + stateActions.setMyRaiseHandStateInProgress(true)); - this._dispatch( - stateActions.setRaiseHandState(true)); + return this._protoo.send('raisehand-message', { raiseHandState: state }) + .then(() => + { + this._dispatch( + stateActions.setMyRaiseHandState(state)); - this._dispatch( - stateActions.setRaiseHandInProgress(false)); + this._dispatch(requestActions.notify( + { + text : 'raiseHand state changed' + })); + this._dispatch( + stateActions.setMyRaiseHandStateInProgress(false)); + }) + .catch((error) => + { + logger.error('sendRaiseHandState() | failed: %o', error); - } + this._dispatch(requestActions.notify( + { + type : 'error', + text : `Could not change raise hand state: ${error}` + })); - lowerHand() - { - logger.debug('lowerHand()'); - - this._dispatch( - stateActions.setRaiseHandInProgress(true)); - - this._dispatch( - stateActions.setRaiseHandState(false)); - - this._dispatch( - stateActions.setRaiseHandInProgress(false)); + // We need to refresh the component for it to render changed state + this._dispatch(stateActions.setMyRaiseHandState(!state)); + this._dispatch( + stateActions.setMyRaiseHandStateInProgress(false)); + }); } restartIce() @@ -641,6 +649,17 @@ export default class RoomClient break; } + case 'raisehand-message': + { + accept(); + const { peerName, raiseHandState } = request.data; + + logger.debug('Got raiseHandState from "%s"', peerName); + + this._dispatch( + stateActions.setPeerRaiseHandState(peerName, raiseHandState)); + break; + } case 'chat-message-receive': { diff --git a/app/lib/components/Peer.jsx b/app/lib/components/Peer.jsx index 61ed633..389d1d1 100644 --- a/app/lib/components/Peer.jsx +++ b/app/lib/components/Peer.jsx @@ -31,6 +31,10 @@ const Peer = (props) => return (
+ {peer.raiseHandState ? +
+ :null + } {!micEnabled ?
:null diff --git a/app/lib/redux/STATE.md b/app/lib/redux/STATE.md index 3171af9..26b0773 100644 --- a/app/lib/redux/STATE.md +++ b/app/lib/redux/STATE.md @@ -49,10 +49,11 @@ { 'alice' : { - name : 'alice', - displayName : 'Alice Thomsom', - device : { flag: 'chrome', name: 'Chrome', version: '58' }, - consumers : [ 5551, 5552 ] + name : 'alice', + displayName : 'Alice Thomsom', + raiseHandState : false, + device : { flag: 'chrome', name: 'Chrome', version: '58' }, + consumers : [ 5551, 5552 ] } }, consumers : diff --git a/app/lib/redux/reducers/me.js b/app/lib/redux/reducers/me.js index f50d082..3e009ad 100644 --- a/app/lib/redux/reducers/me.js +++ b/app/lib/redux/reducers/me.js @@ -72,14 +72,14 @@ const me = (state = initialState, action) => return { ...state, audioOnlyInProgress: flag }; } - case 'SET_RAISE_HAND_STATE': + case 'SET_MY_RAISE_HAND_STATE': { - const { enabled } = action.payload; + const { flag } = action.payload; - return { ...state, raiseHand: enabled }; + return { ...state, raiseHand: flag }; } - case 'SET_RAISE_HAND_STATE_IN_PROGRESS': + case 'SET_MY_RAISE_HAND_STATE_IN_PROGRESS': { const { flag } = action.payload; diff --git a/app/lib/redux/reducers/peers.js b/app/lib/redux/reducers/peers.js index 59761e2..8ff36bd 100644 --- a/app/lib/redux/reducers/peers.js +++ b/app/lib/redux/reducers/peers.js @@ -34,6 +34,19 @@ const peers = (state = initialState, action) => return { ...state, [newPeer.name]: newPeer }; } + case 'SET_PEER_RAISE_HAND_STATE': + { + const { peerName, raiseHandState } = action.payload; + const peer = state[peerName]; + + if (!peer) + throw new Error('no Peer found'); + + const newPeer = { ...peer, raiseHandState }; + + return { ...state, [newPeer.name]: newPeer }; + } + case 'ADD_CONSUMER': { const { consumer, peerName } = action.payload; diff --git a/app/lib/redux/roomClientMiddleware.js b/app/lib/redux/roomClientMiddleware.js index caab57f..3e491e8 100644 --- a/app/lib/redux/roomClientMiddleware.js +++ b/app/lib/redux/roomClientMiddleware.js @@ -104,14 +104,14 @@ export default ({ dispatch, getState }) => (next) => case 'RAISE_HAND': { - client.raiseHand(); + client.sendRaiseHandState(true); break; } case 'LOWER_HAND': { - client.lowerHand(); + client.sendRaiseHandState(false); break; } diff --git a/app/lib/redux/stateActions.js b/app/lib/redux/stateActions.js index 48fd0d1..0829645 100644 --- a/app/lib/redux/stateActions.js +++ b/app/lib/redux/stateActions.js @@ -70,22 +70,30 @@ export const setAudioOnlyInProgress = (flag) => }; }; -export const setRaiseHandState = (enabled) => +export const setMyRaiseHandState = (flag) => { return { - type : 'SET_RAISE_HAND_STATE', - payload : { enabled } + type : 'SET_MY_RAISE_HAND_STATE', + payload : { flag } }; }; -export const setRaiseHandInProgress = (flag) => +export const setMyRaiseHandStateInProgress = (flag) => { return { - type : 'SET_RAISE_HAND_STATE_IN_PROGRESS', + type : 'SET_MY_RAISE_HAND_STATE_IN_PROGRESS', payload : { flag } }; }; +export const setPeerRaiseHandState = (peerName, raiseHandState) => +{ + return { + type : 'SET_PEER_RAISE_HAND_STATE', + payload : { peerName, raiseHandState } + }; +}; + export const setRestartIceInProgress = (flag) => { return { diff --git a/app/resources/images/icon-hand-black.svg b/app/resources/images/icon-hand-black.svg new file mode 100644 index 0000000..8f0f065 --- /dev/null +++ b/app/resources/images/icon-hand-black.svg @@ -0,0 +1,26 @@ + + + + image/svg+xml + + + diff --git a/app/resources/images/icon-hand-white.svg b/app/resources/images/icon-hand-white.svg new file mode 100644 index 0000000..0e2f05f --- /dev/null +++ b/app/resources/images/icon-hand-white.svg @@ -0,0 +1,26 @@ + + + + image/svg+xml + + + diff --git a/app/resources/images/icon_remote_raise_hand.svg b/app/resources/images/icon_remote_raise_hand.svg new file mode 100644 index 0000000..0e2f05f --- /dev/null +++ b/app/resources/images/icon_remote_raise_hand.svg @@ -0,0 +1,26 @@ + + + + image/svg+xml + + + diff --git a/app/stylus/components/Peer.styl b/app/stylus/components/Peer.styl index 8426b0f..3c32d99 100644 --- a/app/stylus/components/Peer.styl +++ b/app/stylus/components/Peer.styl @@ -38,6 +38,10 @@ opacity: 0.85; } + &.raise-hand { + background-image: url('/resources/images/icon_remote_raise_hand.svg'); + } + &.mic-off { background-image: url('/resources/images/icon_remote_mic_white_off.svg'); } diff --git a/app/stylus/components/Room.styl b/app/stylus/components/Room.styl index 6acc3ba..061af50 100644 --- a/app/stylus/components/Room.styl +++ b/app/stylus/components/Room.styl @@ -233,7 +233,11 @@ } &.raise-hand { -// background-image: url('/resources/images/leave-meeting.svg'); + background-image: url('/resources/images/icon-hand-white.svg'); + + &.on { + background-image: url('/resources/images/icon-hand-black.svg'); + } } &.leave-meeting { diff --git a/server/lib/Room.js b/server/lib/Room.js index ec15ab5..4a72188 100644 --- a/server/lib/Room.js +++ b/server/lib/Room.js @@ -264,14 +264,17 @@ class Room extends EventEmitter { accept(); - const { raiseHandMessage } = request.data; + const { raiseHandState } = request.data; + const { mediaPeer } = protooPeer.data; + + mediaPeer.appData.raiseHand = request.data.raiseHandState; // Spread to others via protoo. this._protooRoom.spread( - 'raisehand-message-receive', + 'raisehand-message', { peerName : protooPeer.id, - raiseHandMessage : raiseHandMessage + raiseHandState : raiseHandState }, [ protooPeer ]);