From c416d0c4028ce86d70110dc909ecfe6035f5bc9f Mon Sep 17 00:00:00 2001 From: Torjus Date: Wed, 18 Jul 2018 12:00:55 +0200 Subject: [PATCH 1/7] Add images to chat --- app/lib/RoomClient.js | 7 +- app/lib/components/Chat/Chat.jsx | 12 +- app/lib/components/Chat/MessageList.jsx | 8 +- app/lib/redux/reducers/chatmessages.js | 4 +- app/lib/redux/reducers/helper.js | 7 +- app/lib/redux/reducers/me.js | 8 +- app/lib/redux/reducers/peers.js | 150 +++++++++--------------- app/lib/redux/requestActions.js | 4 +- app/lib/redux/stateActions.js | 6 + 9 files changed, 94 insertions(+), 112 deletions(-) diff --git a/app/lib/RoomClient.js b/app/lib/RoomClient.js index 93ac56a..12bd07c 100644 --- a/app/lib/RoomClient.js +++ b/app/lib/RoomClient.js @@ -1051,7 +1051,7 @@ export default class RoomClient break; } - // This means: server wants to change MY displayName + // This means: server wants to change MY user information case 'auth': { logger.debug('got auth event from server', request.data); @@ -1060,6 +1060,9 @@ export default class RoomClient if (request.data.verified == true) { this.changeDisplayName(request.data.name); + + this._dispatch(stateActions.setPicture(request.data.picture)); + this._dispatch(requestActions.notify( { text : `Authenticated successfully: ${request.data}` @@ -1102,7 +1105,7 @@ export default class RoomClient logger.debug('Got chat from "%s"', peerName); this._dispatch( - stateActions.addResponseMessage(chatMessage)); + stateActions.addResponseMessage({ ...chatMessage, peerName })); break; } diff --git a/app/lib/components/Chat/Chat.jsx b/app/lib/components/Chat/Chat.jsx index e678a3d..7b31245 100644 --- a/app/lib/components/Chat/Chat.jsx +++ b/app/lib/components/Chat/Chat.jsx @@ -14,7 +14,8 @@ class Chat extends Component onSendMessage, disabledInput, autofocus, - displayName + displayName, + picture } = this.props; return ( @@ -22,7 +23,7 @@ class Chat extends Component
{ onSendMessage(e, displayName); }} + onSubmit={(e) => { onSendMessage(e, displayName, picture); }} > { return { disabledInput : state.chatbehavior.disabledInput, - displayName : state.me.displayName + displayName : state.me.displayName, + picture : state.me.picture }; }; const mapDispatchToProps = (dispatch) => { return { - onSendMessage : (event, displayName) => + onSendMessage : (event, displayName, picture) => { event.preventDefault(); const userInput = event.target.message.value; @@ -74,7 +76,7 @@ const mapDispatchToProps = (dispatch) => if (userInput) { dispatch(stateActions.addUserMessage(userInput)); - dispatch(requestActions.sendChatMessage(userInput, displayName)); + dispatch(requestActions.sendChatMessage(userInput, displayName, picture)); } event.target.message.value = ''; } diff --git a/app/lib/components/Chat/MessageList.jsx b/app/lib/components/Chat/MessageList.jsx index d0bbf7b..22fa38c 100644 --- a/app/lib/components/Chat/MessageList.jsx +++ b/app/lib/components/Chat/MessageList.jsx @@ -50,9 +50,14 @@ class MessageList extends Component { const messageTime = new Date(message.time); + const picture = message.sender === 'response' ? + message.picture : this.props.myPicture; + return (
+ {picture && } +
{ return { - chatmessages : state.chatmessages + chatmessages : state.chatmessages, + myPicture : state.me.picture }; }; diff --git a/app/lib/redux/reducers/chatmessages.js b/app/lib/redux/reducers/chatmessages.js index e95789e..020908e 100644 --- a/app/lib/redux/reducers/chatmessages.js +++ b/app/lib/redux/reducers/chatmessages.js @@ -3,9 +3,7 @@ import createNewMessage } from './helper'; -const initialState = []; - -const chatmessages = (state = initialState, action) => +const chatmessages = (state = [], action) => { switch (action.type) { diff --git a/app/lib/redux/reducers/helper.js b/app/lib/redux/reducers/helper.js index 1423eb1..db17859 100644 --- a/app/lib/redux/reducers/helper.js +++ b/app/lib/redux/reducers/helper.js @@ -1,10 +1,11 @@ -export function createNewMessage(text, sender, name) +export function createNewMessage(text, sender, name, picture) { return { type : 'message', text, time : Date.now(), name, - sender + sender, + picture }; -} +} \ No newline at end of file diff --git a/app/lib/redux/reducers/me.js b/app/lib/redux/reducers/me.js index 75e89ae..0b8db12 100644 --- a/app/lib/redux/reducers/me.js +++ b/app/lib/redux/reducers/me.js @@ -21,7 +21,8 @@ const initialState = audioOnlyInProgress : false, raiseHand : false, raiseHandInProgress : false, - restartIceInProgress : false + restartIceInProgress : false, + picture : null }; const me = (state = initialState, action) => @@ -164,6 +165,11 @@ const me = (state = initialState, action) => return { ...state, restartIceInProgress: flag }; } + case 'SET_PICTURE': + { + return { ...state, picture: action.payload.picture }; + } + default: return state; } diff --git a/app/lib/redux/reducers/peers.js b/app/lib/redux/reducers/peers.js index d7174d5..884d39a 100644 --- a/app/lib/redux/reducers/peers.js +++ b/app/lib/redux/reducers/peers.js @@ -1,126 +1,86 @@ -const initialState = {}; +import omit from 'lodash/omit'; -const peers = (state = initialState, action) => +const peer = (state, action) => +{ + switch (action.type) + { + case 'ADD_PEER': + return action.payload.peer; + + case 'SET_PEER_DISPLAY_NAME': + return { ...state, displayName: action.payload.displayName }; + + case 'SET_PEER_VIDEO_IN_PROGRESS': + return { ...state, peerVideoInProgress: action.payload.flag }; + + case 'SET_PEER_AUDIO_IN_PROGRESS': + return { ...state, peerAudioInProgress: action.payload.flag }; + + case 'SET_PEER_SCREEN_IN_PROGRESS': + return { ...state, peerScreenInProgress: action.payload.flag }; + + case 'SET_PEER_RAISE_HAND_STATE': + return { ...state, raiseHandState: action.payload.raiseHandState }; + + case 'ADD_CONSUMER': + { + const consumers = [ ...state.consumers, action.payload.consumer.id ]; + + return { ...state, consumers }; + } + + case 'REMOVE_CONSUMER': + { + const consumers = state.consumers.filter((consumer) => consumer !== action.payload.consumerId); + + return { ...state, consumers }; + } + + default: + return state; + } +}; + +const peers = (state = {}, action) => { switch (action.type) { case 'ADD_PEER': { - const { peer } = action.payload; - - return { ...state, [peer.name]: peer }; + return { ...state, [action.payload.peer.name]: peer(undefined, action) }; } case 'REMOVE_PEER': { - const { peerName } = action.payload; - const newState = { ...state }; - - delete newState[peerName]; - - return newState; + return omit(state, [ action.payload.peerName ]); } case 'SET_PEER_DISPLAY_NAME': - { - const { displayName, peerName } = action.payload; - const peer = state[peerName]; - - if (!peer) - throw new Error('no Peer found'); - - const newPeer = { ...peer, displayName }; - - return { ...state, [newPeer.name]: newPeer }; - } - case 'SET_PEER_VIDEO_IN_PROGRESS': - { - const { peerName, flag } = action.payload; - const peer = state[peerName]; - - if (!peer) - throw new Error('no Peer found'); - - const newPeer = { ...peer, peerVideoInProgress: flag }; - - return { ...state, [newPeer.name]: newPeer }; - } - case 'SET_PEER_AUDIO_IN_PROGRESS': - { - const { peerName, flag } = action.payload; - const peer = state[peerName]; - - if (!peer) - throw new Error('no Peer found'); - - const newPeer = { ...peer, peerAudioInProgress: flag }; - - return { ...state, [newPeer.name]: newPeer }; - } - case 'SET_PEER_SCREEN_IN_PROGRESS': - { - const { peerName, flag } = action.payload; - const peer = state[peerName]; - - if (!peer) - throw new Error('no Peer found'); - - const newPeer = { ...peer, peerScreenInProgress: flag }; - - 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; - const peer = state[peerName]; + const oldPeer = state[action.payload.peerName]; - if (!peer) - throw new Error('no Peer found for new Consumer'); + if (!oldPeer) + { + throw new Error('no Peer found'); + } - const newConsumers = [ ...peer.consumers, consumer.id ]; - const newPeer = { ...peer, consumers: newConsumers }; - - return { ...state, [newPeer.name]: newPeer }; + return { ...state, [oldPeer.name]: peer(oldPeer, action) }; } - + case 'REMOVE_CONSUMER': { - const { consumerId, peerName } = action.payload; - const peer = state[peerName]; + const oldPeer = state[action.payload.peerName]; // NOTE: This means that the Peer was closed before, so it's ok. - if (!peer) + if (!oldPeer) return state; - const idx = peer.consumers.indexOf(consumerId); - - if (idx === -1) - throw new Error('Consumer not found'); - - const newConsumers = peer.consumers.slice(); - - newConsumers.splice(idx, 1); - - const newPeer = { ...peer, consumers: newConsumers }; - - return { ...state, [newPeer.name]: newPeer }; + return { ...state, [oldPeer.name]: peer(oldPeer, action) }; } default: diff --git a/app/lib/redux/requestActions.js b/app/lib/redux/requestActions.js index 5d9a240..6d54490 100644 --- a/app/lib/redux/requestActions.js +++ b/app/lib/redux/requestActions.js @@ -184,9 +184,9 @@ export const installExtension = () => }; }; -export const sendChatMessage = (text, name) => +export const sendChatMessage = (text, name, picture) => { - const message = createNewMessage(text, 'response', name); + const message = createNewMessage(text, 'response', name, picture); return { type : 'SEND_CHAT_MESSAGE', diff --git a/app/lib/redux/stateActions.js b/app/lib/redux/stateActions.js index f9a88d4..3d4229f 100644 --- a/app/lib/redux/stateActions.js +++ b/app/lib/redux/stateActions.js @@ -418,3 +418,9 @@ export const dropMessages = () => type : 'DROP_MESSAGES' }; }; + +export const setPicture = (picture) => + ({ + type : 'SET_PICTURE', + payload : { picture } + }); \ No newline at end of file From 3a43443011a41709bab093d53c43877c605d88cc Mon Sep 17 00:00:00 2001 From: Torjus Date: Wed, 18 Jul 2018 13:59:52 +0200 Subject: [PATCH 2/7] Add avatars to user list --- app/lib/RoomClient.js | 22 +++++++++++++++ app/lib/components/Chat/MessageList.jsx | 4 +-- .../components/ParticipantList/ListPeer.jsx | 5 +++- app/lib/redux/reducers/peers.js | 8 +++++- app/lib/redux/stateActions.js | 6 +++++ app/resources/images/avatar-empty.jpeg | Bin 0 -> 10286 bytes app/stylus/components/ParticipantList.styl | 25 +++++++----------- 7 files changed, 51 insertions(+), 19 deletions(-) create mode 100644 app/resources/images/avatar-empty.jpeg diff --git a/app/lib/RoomClient.js b/app/lib/RoomClient.js index 12bd07c..02a2fb6 100644 --- a/app/lib/RoomClient.js +++ b/app/lib/RoomClient.js @@ -174,6 +174,16 @@ export default class RoomClient }); } + changeProfilePicture(picture) + { + logger.debug('changeProfilePicture() [picture: "%s"]', picture); + + this._protoo.send('change-profile-picture', { picture }).catch((error) => + { + logger.error('shareProfilePicure() | failed: %o', error); + }); + } + sendChatMessage(chatMessage) { logger.debug('sendChatMessage() [chatMessage:"%s"]', chatMessage); @@ -1051,6 +1061,17 @@ export default class RoomClient break; } + case 'profile-picture-changed': + { + accept(); + + const { peerName, picture } = request.data; + + this._dispatch(stateActions.setPeerPicture(peerName, picture)); + + break; + } + // This means: server wants to change MY user information case 'auth': { @@ -1061,6 +1082,7 @@ export default class RoomClient { this.changeDisplayName(request.data.name); + this.changeProfilePicture(request.data.picture); this._dispatch(stateActions.setPicture(request.data.picture)); this._dispatch(requestActions.notify( diff --git a/app/lib/components/Chat/MessageList.jsx b/app/lib/components/Chat/MessageList.jsx index 22fa38c..b8b5099 100644 --- a/app/lib/components/Chat/MessageList.jsx +++ b/app/lib/components/Chat/MessageList.jsx @@ -50,8 +50,8 @@ class MessageList extends Component { const messageTime = new Date(message.time); - const picture = message.sender === 'response' ? - message.picture : this.props.myPicture; + const picture = (message.sender === 'response' ? + message.picture : this.props.myPicture) || 'resources/images/avatar-empty.jpeg'; return (
diff --git a/app/lib/components/ParticipantList/ListPeer.jsx b/app/lib/components/ParticipantList/ListPeer.jsx index 2fb666c..c9f07d1 100644 --- a/app/lib/components/ParticipantList/ListPeer.jsx +++ b/app/lib/components/ParticipantList/ListPeer.jsx @@ -38,9 +38,12 @@ const ListPeer = (props) => !screenConsumer.remotelyPaused ); + const picture = peer.picture || 'resources/images/avatar-empty.jpeg'; + return (
- + +
{peer.displayName}
diff --git a/app/lib/redux/reducers/peers.js b/app/lib/redux/reducers/peers.js index 884d39a..e477c48 100644 --- a/app/lib/redux/reducers/peers.js +++ b/app/lib/redux/reducers/peers.js @@ -1,6 +1,6 @@ import omit from 'lodash/omit'; -const peer = (state, action) => +const peer = (state = {}, action) => { switch (action.type) { @@ -36,6 +36,11 @@ const peer = (state, action) => return { ...state, consumers }; } + case 'SET_PEER_PICTURE': + { + return { ...state, picture: action.payload.picture }; + } + default: return state; } @@ -60,6 +65,7 @@ const peers = (state = {}, action) => case 'SET_PEER_AUDIO_IN_PROGRESS': case 'SET_PEER_SCREEN_IN_PROGRESS': case 'SET_PEER_RAISE_HAND_STATE': + case 'SET_PEER_PICTURE': case 'ADD_CONSUMER': { const oldPeer = state[action.payload.peerName]; diff --git a/app/lib/redux/stateActions.js b/app/lib/redux/stateActions.js index 3d4229f..fa47832 100644 --- a/app/lib/redux/stateActions.js +++ b/app/lib/redux/stateActions.js @@ -423,4 +423,10 @@ export const setPicture = (picture) => ({ type : 'SET_PICTURE', payload : { picture } + }); + +export const setPeerPicture = (peerName, picture) => + ({ + type : 'SET_PEER_PICTURE', + payload : { peerName, picture } }); \ No newline at end of file diff --git a/app/resources/images/avatar-empty.jpeg b/app/resources/images/avatar-empty.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..56c4679a6bc92fd73f7456835b405a0fa9b0c855 GIT binary patch literal 10286 zcmdUUbyOAI`|r$2y1NcYN_R@kdPEa=}@|)LDar;1&TgZ4Imj0D>T(1swox3CL9s zadQR$Jw1RI002Ay2~q%X2!YT6fD8cgCk6m*knt}z0!08AL??z$%j<3c;&&TYs6H)F z&!=zys(n4}1N>M6Jlp~uPM^b50RRov2w_nX;R4v-ccTj6|6=GlfZGP74P1Q!eF9v4 zd|AZ=g#l?5tRCX@TTuClIe$X3SIkMTQ-H^a^(g%8t$mdU+&j7+tg5Q5fswujR#zQj z7Xaw$?0tPbVPpW{*d?jPp*KM z0;hfb*CzjGBDteefCDrw22hhrjsXr{5UztxA_rgpKmdSsK=kq8Kwk)-P7y%m4-F8) z#i!Wi7j8Pmmww^lpKVNxRG~JDkl={y?fqQ&_5WaJe+{EQ z*f&t+Kd^zxA9|>(>iIv|DM0;iKkoM0r!xE5zkiUC=^q?$*;xG#4s|uT@CQ3Osr{up zyJ=wm(A@&Df4}A7qw{wRfG(g8r~#~iD&Piq15SV!U=Q7?L3aUwFW?E?T?upwf#eAQ zsy@C~{M}q!16h@!73jpziuHC7n{`LRTID8-#1nH-?9ETwP%fI?VoK{GH0NT@306oA0ume1R03ZrT z0&;*7G}GFEK41b^02cuVz!jQne;^pR3Pc0(zzrZ3$OLkMe4q#@10Dj8fkvPW=mh$J z=fF5H3CsbDzzVPl>;T_@ACL+~gTx>uNDpE_PLK~21*Jg+P#x3-jX(>~4s-#%!65J| zcn!P(rh~cQeXty?1)IT6a1eX}z6O`Tb?`HI2!q3jU{o+>7#BA*~2HZT{M zA1o9W3%d!+h84o9U=6TN*mKwA1!N_=I7V-hI9@&eWM6Mvep-?Cq6gNr=rG>IUxue2RNvON18dL}B z1!@_!heo66(R^rmv_9G%9f*!c=b)?5&(IU-74$wHAsz-#6i)-s63-hi1}_V*0`Do_ z1l}s%4}3CwPJCH>eSAm!EBGn+#rQ4wWB4ohKM2SPxC!J5ObFZwq6xAIstI}t<_W$K z5)z&vlp!=EbR&!+%qDz9I6$~WctAu!#7m?~WK9%Abd#u*sDtP=(HCN3VlHAOVoTyc z;+w?f#NEVii1$e-Nd!r-B#tDJBzYtaBoibbN%2WJNtH=2l7^CIkv<_EBi$myC*vYh zC9@}sAj>0bCYvVPBc~)6A=fAOB2OZ(ARi=Oqd-$|QK(ZmQp8deQFK!*Q^G0PDOD*Q zD6df#Q}$A>P@$-}sjyV;R5z#|QjJpWP*YHgQ=3tTQ0Gy%Q!moMX}D;xG@djmG>>Vf zXbx$aX_aZ6XcK6wX(wpE(=pO1(K*p2($&yS(jC&X(yP;Z(5KNi(l0O|7ZlGwm_6Fl#dVGUqUNGjFlbuqd&(vt+P5 zWm(5iViYiLm<-G_%mynpt1_!6Yc^{S>kb&zPQxIa70Hft`R| zn%$W_gT0G=hXcc*$8nXTl4F(=pHrICmGd@dKj(KYZmtVl*SQ+G*0|}ovD~5DmE7|@ z#5{^TemsRdug;>*N}u&Od-v=(FN{}$*OfPqcZ?6lC&}l=cbD%4KayXD-lJu9XmRy(Okg}7yBQ-5eC2b&` zBt0O5lu?n1lxdSWkd>4TlzlAwNlrk{L#{$@?Hu%EOZ~i>zdGGU$`hY%G|CauO0k?slL8~Fk(7-Uy@Pm+ z#ahBT-g?T0+a|8F_dCf)M<(A93tDz13UTdv!#yOw*t`*#n0k5Uhu=LOFi zFFY?huV!xwZx8Pt9~PewpBKJ-zVW_`ezJa5tBxfh%ZaUu_O_5Bwmx@aDPMu0qOe;$#PY+FBzNL4o zA%is|G2?5dZRTK>cvk*xg4;p27qfMFx^SG^Zl;l-HCfj z_p0-m^KaxI7PuA6+}FI{P{>u7RfHY#V)gCrg3sm2)p{cp?2zV6qXrtDycIvUt+aN3 z)+aWA4Obd=8eJO~n=G1MG;23^waB&9w+gnFwz0M4wNtmJJSBJ<`xN&q^x0mAZ^u@r zOXqTzZP#44dH1Ux!=BMzo!)^yjlS-F<^E>_@&j#yvV+Y-(nF2UC7(A8OAObKNQ~5v zN{%*+NsTp)%Z#_YIQQb|gyKZ!OSPAMuduJ4PoAHAF=aY6Gi^P+IO908_S*CH?(F5+ zA9GRj$oa$tvW2WSOm7O`o_$-hD7o0aq_#Bt&iLKjvcvM``+)aHE3qGlKV+?9R?F8! z*V@)K*2g!jHdZ!$H-Bu!Zroamg)hZK+y5aH~!fIa-E^j;53pk1KGhxFbg;}{5_%;nT+y68{(bA=Omybq#(j0 zMv$OM$;qh6St$4^6{yZryU>KvCe!89S2Hv-_A$*d?_x+;h1iVF_^~H)+~us{YUS?b z89zJ2`-X3ce??$j@RQIN;UA(1F(Pp)2}a2?Qe4t!W%y+Uhm7;nekooI|`r*6b#b5 zY#$sJl5wRnv^#9}>P`eQk}irTS|Ud2nr5tCoMF7_^$Y)4CRiuh+_;!@G5O+6yA;P% z&$O`go3|chJk6ZS+RjGgFysp7so$}@>wWK9es00z`y+*$#rP%M4>U?0%c9HkE7~e& zs=ii})^I{`TCW z#FEfEzGd$B94o9Jm{;l7Xx1q=EyeoP#d9Y>s);COL3NdA04510wbp8`IB$Up|5jL_V8_;_FO=Lnt?_7Jra zH;^=uHj%ZG_fR~ioTJ*H{zi+SBcrEhU|~GN#LFzjavtN(8pU?|OgVc4M;GTH*C_WG z&x^A!Alo;>|6HJ7uv@58xI?5vv{S58yi?+tWSdlrbc0N-Y^7Y$xm@{lg#^V&r9fp5 z6+2ZEH4Swc4L(g~En=->?3VVd&VX*cUg7yv{Rjg;Lnk9EVouGCi!W>k?RxCHFZDSLI*vF^I8V8}cAa;7qb#1A)ClHMgR z-CRsrPF+viyM@T0$>hnByRDmjF~=u2Dlhd;!QI+>UHOv*8-?&9=33Z{xmXy|8ZCUNPPxGHW=&0@N=$hzW z>pAJ8>gOF$8Z;a7cpf#JF;X_#Ha0Ro_hMyY>*da?uan=W4yTW2aI@eXd>*lYe1m$6 zUL;r|dq=m-{$6NB?t{jv;hOcj%ZA@(*jC(j%E#Z<9Xxj6G#(ch!8}(#498-q=RI= z*XKi_1`F!~= z3xo+q3tbmZ5=j@$5i1Zcm8g<@BvmKfDAOd{DA#bVPX3X?L&XP5_my*1QdO_3MX390 zxM*5x>0;%zg>+bSiFJ?kHqX!MKR0MMtTie#&NsPjnrwFM!WDCGi%XVfR$A7wHvAVc zwv=`R_Q*?c2bd$=3F(Y-LA#>eQ0_<%geS}k@H+86_QCm~{7C~C1J4FYU)BsZ39-N8 z9eO1!?&{6(?1=l352DJW%VJ8d6~yMoWyB|6kNqb+Au!SNhC`A?vcXNQ6qQuPH05-y zTZS1nnXXv@wZcoCHBK~*HIK9mwf495w0Ax2eAd;`-#Om3(7oMr+(**S zG9Wl8KcxHIYS?Wgc=X!X&GD=kxf6F@=Do_9%$mxWPMt}9oiH0W7c(ER5cVeIZOCHS zQuMnU%h~TAtkiwzUL9Y1v%a~pzlGeU_=x!=u%ozZ`q}SG+Sez0li$AY(;vtkTK@*s1<(P^0J|U|$OWoGabYA_0Cs^Npr}tA ziu2-OwXk_O9$W(M2+xEM!f^;Ggg>GNv5gc&`XL*UCn!x+8tM%cU4^2b>{OEkf#lkhsZN!7v)7Y!P`m*LZS>%_fXqt1#~L3G9ntHc%lPh zAL0)rb|ed=Hl%OK9LYAxFH^uNGAOwrJ!M9%{Fo7Cc6#?0ml$$GM6zoBlicMy0fvo7x?)3;rz1#wSw_NmcoJ} z2$6Zw2C;N;KM5mANhv02r1Y-LqU?m+;JF_89)*6zF{RhaA5^}n;ivSe{_s&!3^BZUw+8Ko#=b5ydE?q!Fa<{fjv}(5AxX5IyXBTe&@X~@KiIcK(uuF~W zx;vMLvuBytwvVK5jNhvO{=lT5-C&!L;ZTLJC*gb%52Dzki?4CVK8%;R{xm@&aVSYA zc`!vIwL4w)R&ORYYdqUBXEiVAF8W?xf!O`=qCiL^y(&woIA2BfaI)rZt?Lu1dc1~( zruvqYHqWQn4vx;F?up*A{-{B#=Q1MTK+;0mpu!-EOK%wbWma@Yjy2+j>RfnS5y!`BfQggGJ|F@_{T>Lb&U(TDn*h^xi#H86|$Yl|- zM{)<}juhaEq)HfNQ57xKOOOS-tMN?pJ(fsYQsK_}j8mSt)LH=v2*}6Hs zg|20cRjc*4i(KJ`lkeZ3^KXg86tk= zVHn@l$_SyzhG?aj;aIDTx|8_X_pA9g)qRmewj;_Dyi@rH zIE#rw#^W@duL7kX-{5dxxS-!0=>Tw?hQs|R#Nm#MpkQMj06IK><=sykqsRatT@vO6 z2YPpYr!P;*zYDGdAjboufG9Xf4#3DkI5~*xffg75BBA6XRQ@ysVQ>Tzg~r1tAcPv! zlL0Ug4u>J&NaX3y5-=Qk4j{;p6l@~OC`v8_YI^4N z?9#jC_bVS(*VZ?7KY#hU2U+8T!&AOM$d>*ozc~Bf_<|+@gdq@c1p1UO5EcxbaB>8a zO$0@uY>2k^qdX%TjYp-DcE7e0pIyvohx(HL3j!Jr@g>gPQ`UZR_J7A%%>Rh9zl{CM z*Bq48|HIV(w8lZ5{7>Kg`yOrq`ng7in+1rVh!;iG(vc*7sb zsy&UhRVk%&S{j>SbVhpT4^aDs@pDqz;KA8l%<@>TZQ^Y)?7L?)8;Y;1x9oR5B#X}q zT^DfR{^yqNi9I2WQnd{np%>RaQS8skg zg$WMEr`2FrH(DHr+SEAHPddV<9uou`pf~%w6q6zd_s5pTws8RdMd{pEy(EqIZ9Q*T z?i{}_Z}zGu3=Gzcx2g85Cv@OU{(RQeiG+m%*t0y9 PjFaFNa!Iy7o`>%a=bUG;A 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 literal 0 HcmV?d00001 diff --git a/app/stylus/components/ParticipantList.styl b/app/stylus/components/ParticipantList.styl index 1f0bd98..ddd53ba 100644 --- a/app/stylus/components/ParticipantList.styl +++ b/app/stylus/components/ParticipantList.styl @@ -15,6 +15,8 @@ } [data-component='ListPeer'] { + display: flex; + > .controls { float: right; display: flex; @@ -110,23 +112,16 @@ } > .avatar { - padding: 8px 16px; - float: left; - width: auto; - border: none; - display: block; - outline: 0; - border-radius: 50%; - vertical-align: middle; + border-radius: 50%; + height: 2rem; } > .peer-info { - font-size: 1.4vmin; - float: left; - width: auto; - border: none; - display: block; - outline: 0; - padding: 0.6vmin; + font-size: 1.4vmin; + border: none; + display: flex; + padding: 0.6vmin; + flex-grow: 1; + align-items: center; } } From 1275e6fef4debeaee870b062c48aef6959013d28 Mon Sep 17 00:00:00 2001 From: Torjus Date: Wed, 18 Jul 2018 14:15:06 +0200 Subject: [PATCH 3/7] Style chat pictures --- app/lib/components/Chat/Chat.jsx | 3 +- app/lib/components/Chat/MessageList.jsx | 30 ++++++++++-------- app/lib/redux/reducers/peers.js | 3 +- app/stylus/components/Chat.styl | 42 ++++++++++--------------- 4 files changed, 38 insertions(+), 40 deletions(-) diff --git a/app/lib/components/Chat/Chat.jsx b/app/lib/components/Chat/Chat.jsx index 7b31245..898bf75 100644 --- a/app/lib/components/Chat/Chat.jsx +++ b/app/lib/components/Chat/Chat.jsx @@ -46,7 +46,8 @@ Chat.propTypes = onSendMessage : PropTypes.func, disabledInput : PropTypes.bool, autofocus : PropTypes.bool, - displayName : PropTypes.string + displayName : PropTypes.string, + picture : PropTypes.string }; Chat.defaultProps = diff --git a/app/lib/components/Chat/MessageList.jsx b/app/lib/components/Chat/MessageList.jsx index b8b5099..3f59d1a 100644 --- a/app/lib/components/Chat/MessageList.jsx +++ b/app/lib/components/Chat/MessageList.jsx @@ -56,19 +56,22 @@ class MessageList extends Component return (
- {picture && } + -
- - {message.name} - {this.getTimeString(messageTime)} - +
+
+ + + {message.name} - {this.getTimeString(messageTime)} + +
); @@ -81,7 +84,8 @@ class MessageList extends Component MessageList.propTypes = { - chatmessages : PropTypes.arrayOf(PropTypes.object).isRequired + chatmessages : PropTypes.arrayOf(PropTypes.object).isRequired, + myPicture : PropTypes.string }; const mapStateToProps = (state) => diff --git a/app/lib/redux/reducers/peers.js b/app/lib/redux/reducers/peers.js index e477c48..ea9cb44 100644 --- a/app/lib/redux/reducers/peers.js +++ b/app/lib/redux/reducers/peers.js @@ -31,7 +31,8 @@ const peer = (state = {}, action) => case 'REMOVE_CONSUMER': { - const consumers = state.consumers.filter((consumer) => consumer !== action.payload.consumerId); + const consumers = state.consumers.filter((consumer) => + consumer !== action.payload.consumerId); return { ...state, consumers }; } diff --git a/app/stylus/components/Chat.styl b/app/stylus/components/Chat.styl index 6cfe785..28d69bc 100644 --- a/app/stylus/components/Chat.styl +++ b/app/stylus/components/Chat.styl @@ -74,40 +74,32 @@ color: rgba(#000, 1.0) > .client { - background-color: rgba(#fff, 0.9); - border-radius: 5px; - padding: 6px; - max-width: 215px; - text-align: left; margin-left: auto; - - > .message-text { - font-size: 1.3vmin; - color: rgba(#000, 1.0); - } - - > .message-time { - font-size: 1vmin; - color: rgba(#777, 1.0) - } } - > .response { + > .client, > .response { background-color: rgba(#fff, 0.9); border-radius: 5px; - padding: 6px; max-width: 215px; - text-align: left; - font-size: 1.3vmin; + display: flex; + align-items: center; - > .message-text { - font-size: 1.3vmin; - color: rgba(#000, 1.0); + > .message-avatar { + height: 2rem; } - > .message-time { - font-size: 1vmin; - color: rgba(#777, 1.0); + > .message-content { + padding: 6px; + + > .message-text { + font-size: 1.3vmin; + color: rgba(#000, 1.0); + } + + > .message-time { + font-size: 1vmin; + color: rgba(#777, 1.0); + } } } } From 89465e71f976eda1bd69718030d04e05cd633198 Mon Sep 17 00:00:00 2001 From: Torjus Date: Wed, 18 Jul 2018 14:23:34 +0200 Subject: [PATCH 4/7] Add profile pic spreading to protoo server --- server/lib/Room.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/server/lib/Room.js b/server/lib/Room.js index c6b5089..c7f8bfa 100644 --- a/server/lib/Room.js +++ b/server/lib/Room.js @@ -228,6 +228,19 @@ class Room extends EventEmitter break; } + case 'change-profile-picture': + { + accept(); + + console.log('YES LAWD les cghange tat prifule pic!!') + this._protooRoom.spread('profile-picture-changed', { + peerName: protooPeer.id, + picture: request.data.picture + }); + + break; + } + case 'chat-message': { accept(); From a1fad12b5ce35776618273e2b7871c24bfb2d3a5 Mon Sep 17 00:00:00 2001 From: Torjus Date: Wed, 18 Jul 2018 14:35:55 +0200 Subject: [PATCH 5/7] Merge develop and remove comments --- app/lib/RoomClient.js | 67 ++++++++++++++++++- app/lib/components/Me.jsx | 1 + .../components/ParticipantList/ListPeer.jsx | 4 +- app/lib/components/Peer.jsx | 37 +++++----- app/lib/components/PeerView.jsx | 43 +----------- app/lib/components/Peers.jsx | 6 +- .../components/ToolArea/ToolAreaButton.jsx | 2 +- app/lib/redux/reducers/consumers.js | 9 +++ app/lib/redux/reducers/producers.js | 9 +++ app/lib/redux/stateActions.js | 16 +++++ app/package-lock.json | 19 ++++-- app/stylus/components/Chat.styl | 17 +++-- app/stylus/components/Me.styl | 5 +- app/stylus/components/ParticipantList.styl | 4 +- app/stylus/components/Peer.styl | 7 +- app/stylus/components/Room.styl | 2 +- app/stylus/components/ToolArea.styl | 8 ++- app/stylus/index.styl | 1 - app/stylus/keyframes.styl | 23 ------- server/lib/Room.js | 1 - 20 files changed, 161 insertions(+), 120 deletions(-) delete mode 100644 app/stylus/keyframes.styl diff --git a/app/lib/RoomClient.js b/app/lib/RoomClient.js index 02a2fb6..700e52d 100644 --- a/app/lib/RoomClient.js +++ b/app/lib/RoomClient.js @@ -1,6 +1,7 @@ import protooClient from 'protoo-client'; import * as mediasoupClient from 'mediasoup-client'; import Logger from './Logger'; +import hark from 'hark'; import ScreenShare from './ScreenShare'; import { getProtooUrl } from './urlFactory'; import * as cookiesManager from './cookiesManager'; @@ -1405,7 +1406,33 @@ export default class RoomClient }) .then(() => { + const stream = new MediaStream; + logger.debug('_setMicProducer() succeeded'); + stream.addTrack(producer.track); + if (!stream.getAudioTracks()[0]) + throw new Error('_setMicProducer(): given stream has no audio track'); + producer.hark = hark(stream, { play: false }); + + // eslint-disable-next-line no-unused-vars + producer.hark.on('volume_change', (dBs, threshold) => + { + // The exact formula to convert from dBs (-100..0) to linear (0..1) is: + // Math.pow(10, dBs / 20) + // However it does not produce a visually useful output, so let exagerate + // it a bit. Also, let convert it from 0..1 to 0..10 and avoid value 1 to + // minimize component renderings. + let volume = Math.round(Math.pow(10, dBs / 85) * 10); + + if (volume === 1) + volume = 0; + + if (volume !== producer.volume) + { + producer.volume = volume; + this._dispatch(stateActions.setProducerVolume(producer.id, volume)); + } + }); }) .catch((error) => { @@ -1848,7 +1875,8 @@ export default class RoomClient track : null, codec : codec ? codec.name : null }, - consumer.peer.name)); + consumer.peer.name) + ); consumer.on('close', (originator) => { @@ -1860,6 +1888,43 @@ export default class RoomClient consumer.id, consumer.peer.name)); }); + consumer.on('handled', (originator) => + { + logger.debug( + 'consumer "handled" event [id:%s, originator:%s, consumer:%o]', + consumer.id, originator, consumer); + if (consumer.kind === 'audio') + { + const stream = new MediaStream; + + stream.addTrack(consumer.track); + if (!stream.getAudioTracks()[0]) + throw new Error('consumer.on("handled" | given stream has no audio track'); + + consumer.hark = hark(stream, { play: false }); + + // eslint-disable-next-line no-unused-vars + consumer.hark.on('volume_change', (dBs, threshold) => + { + // The exact formula to convert from dBs (-100..0) to linear (0..1) is: + // Math.pow(10, dBs / 20) + // However it does not produce a visually useful output, so let exagerate + // it a bit. Also, let convert it from 0..1 to 0..10 and avoid value 1 to + // minimize component renderings. + let volume = Math.round(Math.pow(10, dBs / 85) * 10); + + if (volume === 1) + volume = 0; + + if (volume !== consumer.volume) + { + consumer.volume = volume; + this._dispatch(stateActions.setConsumerVolume(consumer.id, volume)); + } + }); + } + }); + consumer.on('pause', (originator) => { logger.debug( diff --git a/app/lib/components/Me.jsx b/app/lib/components/Me.jsx index 38dc747..dcedb94 100644 --- a/app/lib/components/Me.jsx +++ b/app/lib/components/Me.jsx @@ -140,6 +140,7 @@ class Me extends React.Component advancedMode={advancedMode} peer={me} audioTrack={micProducer ? micProducer.track : null} + volume={micProducer ? micProducer.volume : null} videoTrack={webcamProducer ? webcamProducer.track : null} videoVisible={videoVisible} audioCodec={micProducer ? micProducer.codec : null} diff --git a/app/lib/components/ParticipantList/ListPeer.jsx b/app/lib/components/ParticipantList/ListPeer.jsx index c9f07d1..8308f79 100644 --- a/app/lib/components/ParticipantList/ListPeer.jsx +++ b/app/lib/components/ParticipantList/ListPeer.jsx @@ -70,6 +70,8 @@ const ListPeer = (props) => off : !micEnabled, disabled : peer.peerAudioInProgress })} + style={{ opacity : micEnabled && micConsumer ? (micConsumer.volume/10) + + 0.2 :1 }} onClick={(e) => { e.stopPropagation(); @@ -143,7 +145,7 @@ const mapDispatchToProps = (dispatch) => }, onEnableWebcam : (peerName) => { - + dispatch(requestActions.resumePeerVideo(peerName)); }, onDisableWebcam : (peerName) => diff --git a/app/lib/components/Peer.jsx b/app/lib/components/Peer.jsx index d3961ae..2b06f13 100644 --- a/app/lib/components/Peer.jsx +++ b/app/lib/components/Peer.jsx @@ -8,27 +8,27 @@ import * as stateActions from '../redux/stateActions'; import PeerView from './PeerView'; import ScreenView from './ScreenView'; -class Peer extends Component +class Peer extends Component { state = { controlsVisible : false }; - handleMouseOver = () => + handleMouseOver = () => { this.setState({ controlsVisible : true }); }; - handleMouseOut = () => + handleMouseOut = () => { this.setState({ controlsVisible : false }); }; - render() + render() { const { advancedMode, @@ -45,35 +45,35 @@ class Peer extends Component toggleConsumerFullscreen, style } = this.props; - + const micEnabled = ( Boolean(micConsumer) && !micConsumer.locallyPaused && !micConsumer.remotelyPaused ); - + const videoVisible = ( Boolean(webcamConsumer) && !webcamConsumer.locallyPaused && !webcamConsumer.remotelyPaused ); - + const screenVisible = ( Boolean(screenConsumer) && !screenConsumer.locallyPaused && !screenConsumer.remotelyPaused ); - + let videoProfile; - + if (webcamConsumer) videoProfile = webcamConsumer.profile; - + let screenProfile; - + if (screenConsumer) screenProfile = screenConsumer.profile; - + return (
:null } - +
- +
- +
@@ -136,6 +136,7 @@ class Peer extends Component advancedMode={advancedMode} peer={peer} audioTrack={micConsumer ? micConsumer.track : null} + volume={micConsumer ? micConsumer.volume : null} videoTrack={webcamConsumer ? webcamConsumer.track : null} videoVisible={videoVisible} videoProfile={videoProfile} @@ -143,7 +144,7 @@ class Peer extends Component videoCodec={webcamConsumer ? webcamConsumer.codec : null} />
- + {screenConsumer ?
@@ -160,7 +161,7 @@ class Peer extends Component onDisableScreen(peer.name) : onEnableScreen(peer.name); }} /> - +
@@ -236,7 +237,7 @@ const mapDispatchToProps = (dispatch) => }, onEnableWebcam : (peerName) => { - + dispatch(requestActions.resumePeerVideo(peerName)); }, onDisableWebcam : (peerName) => diff --git a/app/lib/components/PeerView.jsx b/app/lib/components/PeerView.jsx index c258584..4a512a6 100644 --- a/app/lib/components/PeerView.jsx +++ b/app/lib/components/PeerView.jsx @@ -2,7 +2,6 @@ import React from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import Spinner from 'react-spinner'; -import hark from 'hark'; import * as appPropTypes from './appPropTypes'; import EditableInput from './EditableInput'; @@ -27,10 +26,6 @@ export default class PeerView extends React.Component // @type {MediaStreamTrack} this._videoTrack = null; - // Hark instance. - // @type {Object} - this._hark = null; - // Periodic timer for showing video resolution. this._videoResolutionTimer = null; } @@ -40,6 +35,7 @@ export default class PeerView extends React.Component const { isMe, peer, + volume, advancedMode, videoVisible, videoProfile, @@ -49,7 +45,6 @@ export default class PeerView extends React.Component } = this.props; const { - volume, videoWidth, videoHeight } = this.state; @@ -149,9 +144,6 @@ export default class PeerView extends React.Component componentWillUnmount() { - if (this._hark) - this._hark.stop(); - clearInterval(this._videoResolutionTimer); } @@ -160,6 +152,7 @@ export default class PeerView extends React.Component const { audioTrack, videoTrack } = nextProps; this._setTracks(audioTrack, videoTrack); + } _setTracks(audioTrack, videoTrack) @@ -170,9 +163,6 @@ export default class PeerView extends React.Component this._audioTrack = audioTrack; this._videoTrack = videoTrack; - if (this._hark) - this._hark.stop(); - clearInterval(this._videoResolutionTimer); this._hideVideoResolution(); @@ -190,9 +180,6 @@ export default class PeerView extends React.Component video.srcObject = stream; - if (audioTrack) - this._runHark(stream); - if (videoTrack) this._showVideoResolution(); } @@ -202,31 +189,6 @@ export default class PeerView extends React.Component } } - _runHark(stream) - { - if (!stream.getAudioTracks()[0]) - throw new Error('_runHark() | given stream has no audio track'); - - this._hark = hark(stream, { play: false }); - - // eslint-disable-next-line no-unused-vars - this._hark.on('volume_change', (dBs, threshold) => - { - // The exact formula to convert from dBs (-100..0) to linear (0..1) is: - // Math.pow(10, dBs / 20) - // However it does not produce a visually useful output, so let exagerate - // it a bit. Also, let convert it from 0..1 to 0..10 and avoid value 1 to - // minimize component renderings. - let volume = Math.round(Math.pow(10, dBs / 85) * 10); - - if (volume === 1) - volume = 0; - - if (volume !== this.state.volume) - this.setState({ volume: volume }); - }); - } - _showVideoResolution() { this._videoResolutionTimer = setInterval(() => @@ -259,6 +221,7 @@ PeerView.propTypes = [ appPropTypes.Me, appPropTypes.Peer ]).isRequired, advancedMode : PropTypes.bool, audioTrack : PropTypes.any, + volume : PropTypes.number, videoTrack : PropTypes.any, videoVisible : PropTypes.bool.isRequired, videoProfile : PropTypes.string, diff --git a/app/lib/components/Peers.jsx b/app/lib/components/Peers.jsx index 14a11b0..67036f5 100644 --- a/app/lib/components/Peers.jsx +++ b/app/lib/components/Peers.jsx @@ -62,12 +62,12 @@ class Peers extends React.Component observer.observe(this.refs.peers); } - componentWillUnmount() + componentWillUnmount() { window.removeEventListener('resize', this.updateDimensions); } - componentDidUpdate() + componentDidUpdate() { this.updateDimensions(); } @@ -81,7 +81,7 @@ class Peers extends React.Component toolAreaOpen } = this.props; - const style = + const style = { 'width' : this.state.peerWidth, 'height' : this.state.peerHeight diff --git a/app/lib/components/ToolArea/ToolAreaButton.jsx b/app/lib/components/ToolArea/ToolAreaButton.jsx index 14e7d92..ea9fa09 100644 --- a/app/lib/components/ToolArea/ToolAreaButton.jsx +++ b/app/lib/components/ToolArea/ToolAreaButton.jsx @@ -41,7 +41,7 @@ ToolAreaButton.propTypes = { toolAreaOpen : PropTypes.bool.isRequired, toggleToolArea : PropTypes.func.isRequired, - unread : PropTypes.bool.isRequired, + unread : PropTypes.number.isRequired, visible : PropTypes.bool.isRequired }; diff --git a/app/lib/redux/reducers/consumers.js b/app/lib/redux/reducers/consumers.js index 81f0e1c..117cdc5 100644 --- a/app/lib/redux/reducers/consumers.js +++ b/app/lib/redux/reducers/consumers.js @@ -35,6 +35,15 @@ const consumers = (state = initialState, action) => return { ...state, [consumerId]: newConsumer }; } + case 'SET_CONSUMER_VOLUME': + { + const { consumerId, volume } = action.payload; + const consumer = state[consumerId]; + const newConsumer = { ...consumer, volume }; + + return { ...state, [consumerId]: newConsumer }; + } + case 'SET_CONSUMER_RESUMED': { const { consumerId, originator } = action.payload; diff --git a/app/lib/redux/reducers/producers.js b/app/lib/redux/reducers/producers.js index 4562b8b..736f70b 100644 --- a/app/lib/redux/reducers/producers.js +++ b/app/lib/redux/reducers/producers.js @@ -35,6 +35,15 @@ const producers = (state = initialState, action) => return { ...state, [producerId]: newProducer }; } + case 'SET_PRODUCER_VOLUME': + { + const { producerId, volume } = action.payload; + const producer = state[producerId]; + const newProducer = { ...producer, volume }; + + return { ...state, [producerId]: newProducer }; + } + case 'SET_PRODUCER_RESUMED': { const { producerId, originator } = action.payload; diff --git a/app/lib/redux/stateActions.js b/app/lib/redux/stateActions.js index fa47832..9dcbb41 100644 --- a/app/lib/redux/stateActions.js +++ b/app/lib/redux/stateActions.js @@ -331,6 +331,22 @@ export const setConsumerTrack = (consumerId, track) => }; }; +export const setConsumerVolume = (consumerId, volume) => +{ + return { + type : 'SET_CONSUMER_VOLUME', + payload : { consumerId, volume } + }; +}; + +export const setProducerVolume = (producerId, volume) => +{ + return { + type : 'SET_PRODUCER_VOLUME', + payload : { producerId, volume } + }; +}; + export const addNotification = (notification) => { return { diff --git a/app/package-lock.json b/app/package-lock.json index cf150d1..5c87dfe 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -4771,7 +4771,8 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", @@ -4782,7 +4783,8 @@ "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -4899,7 +4901,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -4911,6 +4914,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -4940,6 +4944,7 @@ "version": "2.2.4", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -4958,6 +4963,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -5058,6 +5064,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -5179,6 +5186,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -5602,7 +5610,6 @@ "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -5745,8 +5752,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -5772,7 +5778,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } diff --git a/app/stylus/components/Chat.styl b/app/stylus/components/Chat.styl index 28d69bc..037257f 100644 --- a/app/stylus/components/Chat.styl +++ b/app/stylus/components/Chat.styl @@ -61,7 +61,7 @@ } [data-component='MessageList'] { - background-color: rgba(#fff, 0.9); + background-color: rgba(#000, 0.1); height: 91vmin; overflow-y: scroll; padding-top: 5px; @@ -71,34 +71,33 @@ margin: 5px; display: flex; word-wrap: break-word; - color: rgba(#000, 1.0) > .client { margin-left: auto; } > .client, > .response { - background-color: rgba(#fff, 0.9); + background-color: rgba(#000, 0.1); border-radius: 5px; max-width: 215px; display: flex; align-items: center; + padding: 6px; > .message-avatar { height: 2rem; } > .message-content { - padding: 6px; + padding-left: 6px; > .message-text { font-size: 1.3vmin; - color: rgba(#000, 1.0); } > .message-time { font-size: 1vmin; - color: rgba(#777, 1.0); + opacity: 0.8; } } } @@ -108,7 +107,7 @@ [data-component='Sender'] { align-items: center; display: flex; - background-color: rgba(#fff, 0.9); + background-color: rgba(#000, 0.1); height: 6vmin; padding: 0.5vmin; border-radius: 0 0 5px 5px; @@ -117,8 +116,8 @@ width: 100%; border: 0; border-radius: 5px; - background-color: rgba(#fff, 0.9); - color: #000; + background-color: rgba(#000, 0.1); + color: #fff; height: 30px; padding-left: 10px; font-size: 1.4vmin; diff --git a/app/stylus/components/Me.styl b/app/stylus/components/Me.styl index 2f21d71..7df0c0d 100644 --- a/app/stylus/components/Me.styl +++ b/app/stylus/components/Me.styl @@ -27,14 +27,11 @@ justify-content: flex-start; align-items: center; padding: 0.4vmin; - visibility: hidden; opacity: 0; - animation: fade-out 0.3s; + transition: opacity 0.3s; &.visible { - visibility: visible; opacity: 1; - animation: fade-in 0.3s; } > .button { diff --git a/app/stylus/components/ParticipantList.styl b/app/stylus/components/ParticipantList.styl index ddd53ba..7f4328a 100644 --- a/app/stylus/components/ParticipantList.styl +++ b/app/stylus/components/ParticipantList.styl @@ -120,8 +120,8 @@ font-size: 1.4vmin; border: none; display: flex; - padding: 0.6vmin; + padding: 1vmin; flex-grow: 1; align-items: center; } -} +} \ No newline at end of file diff --git a/app/stylus/components/Peer.styl b/app/stylus/components/Peer.styl index a6567d6..5a9e762 100644 --- a/app/stylus/components/Peer.styl +++ b/app/stylus/components/Peer.styl @@ -41,14 +41,11 @@ justify-content: flex-start; align-items: center; padding: 0.4vmin; - visibility: hidden; opacity: 0; - animation: fade-out 0.3s; - + transition: opacity 0.3s; + &.visible { - visibility: visible; opacity: 1; - animation: fade-in 0.3s; } > .button { diff --git a/app/stylus/components/Room.styl b/app/stylus/components/Room.styl index 16a5f5d..932406c 100644 --- a/app/stylus/components/Room.styl +++ b/app/stylus/components/Room.styl @@ -271,7 +271,7 @@ right: 0; width: 20%; height: 100%; - background-color: #FFF; + background-color: rgba(0,0,0,0.1); transition: width 0.3s; } } diff --git a/app/stylus/components/ToolArea.styl b/app/stylus/components/ToolArea.styl index b6f3a7f..e424e8b 100644 --- a/app/stylus/components/ToolArea.styl +++ b/app/stylus/components/ToolArea.styl @@ -73,6 +73,7 @@ [data-component='ToolArea'] { width: 100%; height: 100%; + color: #fff; > .tabs { display: flex; @@ -84,7 +85,7 @@ display: block; padding: 1vmin 0 0.8vmin 0; cursor: pointer; - background: rgba(#000, 0.3); + background: rgba(0,0,0,0.3); font-weight: bold; transition: background ease 0.2s; text-align: center; @@ -111,7 +112,7 @@ height: 100%; display: none; padding: 1vmin; - background: #fff; + background: rgba(0,0,0,0.1); } > input[type="radio"] { @@ -119,11 +120,12 @@ } > input[type="radio"]:checked + label { - background: #fff; + background: rgba(0,0,0,0.1); } > input[type="radio"]:checked + label + .tab { display: block; + background: rgba(0,0,0,0.1); } } } diff --git a/app/stylus/index.styl b/app/stylus/index.styl index a9a58f8..dbc11ba 100644 --- a/app/stylus/index.styl +++ b/app/stylus/index.styl @@ -5,7 +5,6 @@ global-reset(); @import './mixins'; @import './fonts'; @import './reset'; -@import './keyframes'; html { height: 100%; diff --git a/app/stylus/keyframes.styl b/app/stylus/keyframes.styl deleted file mode 100644 index 9d200f7..0000000 --- a/app/stylus/keyframes.styl +++ /dev/null @@ -1,23 +0,0 @@ -@keyframes fade-in { - from { - opacity: 0; - visibility: hidden; - } - - to { - opacity: 1; - visibility: visible; - } -} - -@keyframes fade-out { - from { - opacity: 1; - visibility: visible; - } - - to { - opacity: 0; - visibility: hidden; - } -} \ No newline at end of file diff --git a/server/lib/Room.js b/server/lib/Room.js index c7f8bfa..c6a5921 100644 --- a/server/lib/Room.js +++ b/server/lib/Room.js @@ -232,7 +232,6 @@ class Room extends EventEmitter { accept(); - console.log('YES LAWD les cghange tat prifule pic!!') this._protooRoom.spread('profile-picture-changed', { peerName: protooPeer.id, picture: request.data.picture From 48b2668f0b847aaab6f6104e8bd04176f1a47731 Mon Sep 17 00:00:00 2001 From: Torjus Date: Wed, 18 Jul 2018 14:46:19 +0200 Subject: [PATCH 6/7] Consistent avatar styling in chat and users tabs --- app/stylus/components/Chat.styl | 1 + 1 file changed, 1 insertion(+) diff --git a/app/stylus/components/Chat.styl b/app/stylus/components/Chat.styl index 037257f..0541e70 100644 --- a/app/stylus/components/Chat.styl +++ b/app/stylus/components/Chat.styl @@ -86,6 +86,7 @@ > .message-avatar { height: 2rem; + border-radius: 50%; } > .message-content { From 73f608aa50d77a744ebe86c279db0d3f1259c16c Mon Sep 17 00:00:00 2001 From: Torjus Date: Wed, 18 Jul 2018 15:02:40 +0200 Subject: [PATCH 7/7] Do not attempt setting own profile picture as peer picture --- server/lib/Room.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/lib/Room.js b/server/lib/Room.js index c6a5921..1f6d13c 100644 --- a/server/lib/Room.js +++ b/server/lib/Room.js @@ -235,7 +235,7 @@ class Room extends EventEmitter this._protooRoom.spread('profile-picture-changed', { peerName: protooPeer.id, picture: request.data.picture - }); + }, [ protooPeer ]); break; }