Connect the received reactions to redux 1 at a time

This commit is contained in:
Lyubo Marinov 2018-02-08 22:06:21 -06:00
parent d24cd88a8a
commit 44b36561b4
7 changed files with 121 additions and 12 deletions

View File

@ -0,0 +1,11 @@
/**
* The type of (redux) action which signals that a specific reaction has been
* received by the local participant from a specific remote participant.
*
* {
* type: ADD_RECEIVED_REACTION,
* participant: Object,
* reaction: string
* }
*/
export const ADD_RECEIVED_REACTION = Symbol('ADD_RECEIVED_REACTION');

View File

@ -1,5 +1,27 @@
// @flow
import { ADD_RECEIVED_REACTION } from './actionTypes';
/**
* Creates a redux action which signals that a specific reaction has been
* received by the local participant from a specific remote participant.
*
* @param {string} reaction - The reaction which has been received.
* @param {Object} participant - The remote participant who sent the reaction.
* @returns {{
* type: ADD_RECEIVED_REACTION,
* participant: Object,
* reaction: string
* }}
*/
export function addReceivedReaction(reaction: string, participant: Object) {
return {
type: ADD_RECEIVED_REACTION,
participant,
reaction
};
}
/**
* Sends a specific reaction of the local participant to the remote
* participants.

View File

@ -1,9 +1,13 @@
/* @flow */
// @flow
import React, { Component } from 'react';
import { connect } from 'react-redux';
import EmojiIcon from './EmojiIcon';
type Props = {
_reaction: string
};
/**
* Implements a React {@link Component} which represents the large video (a.k.a.
@ -11,7 +15,7 @@ import EmojiIcon from './EmojiIcon';
*
* @extends Component
*/
export default class ReactionsCanvas extends Component<*> {
class ReactionsCanvas extends Component<Props> {
/**
* Implements React's {@link Component#render()}.
@ -20,12 +24,51 @@ export default class ReactionsCanvas extends Component<*> {
* @returns {ReactElement}
*/
render() {
const reaction = this.props._reaction;
if (!reaction) {
return null;
}
// FIXME The use of key bellow is somewhat of a hack/workaround for
// EmojiIcon: EmojiIcon doesn't seem to restart its animation upon
// changing its emojiName value. So the key will force a new EmojiIcon
// instance upon different reactions.
return (
<div className = 'emotionsCanvas'>
<EmojiIcon
emojiName = 'thumbsup' />
emojiName = { reaction }
key = { reaction } />
</div>
);
}
}
/**
* Maps (parts of) the redux state to the associated ReactionsCanvas' props.
*
* @param {Object} state - The redux state.
* @private
* @returns {{
* _reaction: string
* }}
*/
function _mapStateToProps(state) { // eslint-disable-line no-unused-vars
const stateFeatureReactions = state['features/reactions'];
const receivedReactions
= stateFeatureReactions && stateFeatureReactions.receivedReactions;
// TODO Eventually and wherever appropriate (which is definitely not here),
// pop reactions which have been rendered.
const reaction
= receivedReactions && receivedReactions.length
? receivedReactions[0]
: undefined;
return {
_reaction: reaction
};
}
export default connect(_mapStateToProps)(ReactionsCanvas);

View File

@ -3,3 +3,4 @@ export * from './actionTypes';
export * from './components';
import './middleware';
import './reducer';

View File

@ -3,6 +3,8 @@
import { CONFERENCE_JOINED } from '../base/conference';
import { MiddlewareRegistry } from '../base/redux';
import { addReceivedReaction } from './actions';
MiddlewareRegistry.register(store => next => action => {
switch (action.type) {
case CONFERENCE_JOINED:
@ -26,17 +28,18 @@ MiddlewareRegistry.register(store => next => action => {
* @returns {Object} The new state that is the result of the reduction of the
* specified {@code action}.
*/
function _conferenceJoined({ getState }, next, action) {
function _conferenceJoined({ dispatch, getState }, next, action) {
const result = next(action);
getState()['features/base/conference'].conference.on(
'conference.endpoint_message_received',
(participant, payload) => {
if (payload
&& payload.payload
&& payload.payload.type === 'reaction') {
// TODO Utilize payload (and maybe participant).
console.log('Received:', payload);
(participant, message) => {
let payload;
if (message
&& (payload = message.payload)
&& payload.type === 'reaction') {
dispatch(addReceivedReaction(payload.reaction, participant));
}
});

View File

@ -0,0 +1,28 @@
// @flow
import { ReducerRegistry } from '../base/redux';
import { ADD_RECEIVED_REACTION } from './actionTypes';
const _INITIAL_STATE = {
receivedReactions: []
};
ReducerRegistry.register(
'features/reactions', (state = _INITIAL_STATE, action) => {
switch (action.type) {
case ADD_RECEIVED_REACTION:
return {
...state,
receivedReactions: [
// FIXME Push the latest reaction at the top because I'm
// currently rendering only the first reaction.
action.reaction,
...state.receivedReactions
]
};
}
return state;
});

View File

@ -183,8 +183,9 @@ module.exports = [
* target, undefined; otherwise, the path to the local file to be served.
*/
function devServerProxyBypass({ path }) {
if (path.startsWith('/css/') || path.startsWith('/doc/')
|| path.startsWith('/images/')) {
if (path.startsWith('/css/')
|| path.startsWith('/doc/')
|| path.startsWith('/images/')) {
return path;
}