diff --git a/react/features/reactions/actionTypes.js b/react/features/reactions/actionTypes.js new file mode 100644 index 000000000..e69de29bb diff --git a/react/features/reactions/actions.js b/react/features/reactions/actions.js new file mode 100644 index 000000000..76983a830 --- /dev/null +++ b/react/features/reactions/actions.js @@ -0,0 +1,27 @@ +// @flow + +/** + * Sends a specific reaction of the local participant to the remote + * participants. + * + * @param {string} reaction - The reaction of the local participant to send to + * the remote participants. + * @returns {Function} + */ +export function sendReaction(reaction: string) { + // reaction = 'thumbsup', 'heart', etc + + return (dispatch: Dispatch, getState: Function) => { + const payload = { + type: 'reaction', + reaction, + targetEndpoint: 'target' // TODO use the selectedEndpoint + }; + + getState()['features/base/conference'].conference.sendTextMessage( + JSON.stringify({ + 'jitsi-meet-muc-msg-topic': 'xxx', + payload + })); + }; +} diff --git a/react/features/reactions/components/ReactionsDialog.web.js b/react/features/reactions/components/ReactionsDialog.web.js index 01b2cca9e..083a36e5f 100644 --- a/react/features/reactions/components/ReactionsDialog.web.js +++ b/react/features/reactions/components/ReactionsDialog.web.js @@ -1,8 +1,13 @@ // @flow import React, { Component } from 'react'; +import { connect } from 'react-redux'; + +import { sendReaction } from '../actions'; type Props = { + _onSendReaction: Function, + onClose: Function }; @@ -21,7 +26,7 @@ for (let i = 1; i < 21; ++i) { * Represents the dialog in the terms of {@link ToolbarButtonWithDialog} which * renders the list of supported reactions (i.e. reaction buttons). */ -export default class ReactionsDialog extends Component { +class ReactionsDialog extends Component { /** * Implements React's {@link Component#render()}. * @@ -47,9 +52,9 @@ export default class ReactionsDialog extends Component { * @param {*} reaction - The reaction (button) which was clicked. * @returns {void} */ - _onClick(reaction) { // eslint-disable-line no-unused-vars - // Close this ReactionsDialog. + _onClick(reaction) { this.props.onClose(); + this.props._onSendReaction(reaction); } /** @@ -76,3 +81,43 @@ export default class ReactionsDialog extends Component { return contents; } } + +/** + * Maps dispatching of some action to React component props. + * + * @param {Function} dispatch - Redux action dispatcher. + * @private + * @returns {{ + * }} + */ +function _mapDispatchToProps(dispatch) { + return { + /** + * Sends a specific reaction of the local participant to the remote + * participants. + * + * @param {string} reaction - The reaction of the local participant to + * send to the remote participants. + * @private + * @returns {void} + */ + _onSendReaction(reaction) { + dispatch(sendReaction(reaction)); + } + }; +} + +/** + * Maps (parts of) the redux state to the associated ReactionsDialog's props. + * + * @param {Object} state - The redux state. + * @private + * @returns {{ + * }} + */ +function _mapStateToProps(state) { // eslint-disable-line no-unused-vars + return { + }; +} + +export default connect(_mapStateToProps, _mapDispatchToProps)(ReactionsDialog); diff --git a/react/features/reactions/index.js b/react/features/reactions/index.js index 07635cbbc..f4ab4e579 100644 --- a/react/features/reactions/index.js +++ b/react/features/reactions/index.js @@ -1 +1,5 @@ +export * from './actions'; +export * from './actionTypes'; export * from './components'; + +import './middleware'; diff --git a/react/features/reactions/middleware.js b/react/features/reactions/middleware.js new file mode 100644 index 000000000..a33ae2c72 --- /dev/null +++ b/react/features/reactions/middleware.js @@ -0,0 +1,44 @@ +// @flow + +import { CONFERENCE_JOINED } from '../base/conference'; +import { MiddlewareRegistry } from '../base/redux'; + +MiddlewareRegistry.register(store => next => action => { + switch (action.type) { + case CONFERENCE_JOINED: + return _conferenceJoined(store, next, action); + } + + return next(action); +}); + +/** + * Notifies the feature app that the action {@link CONFERENCE_JOINED} is being + * dispatched within a specific redux {@code store}. + * + * @param {Store} store - The redux store in which the specified {@code action} + * is being dispatched. + * @param {Dispatch} next - The redux {@code dispatch} function to dispatch the + * specified {@code action} to the specified {@code store}. + * @param {Action} action - The redux action {@code CONFERENCE_JOINED} which is + * being dispatched in the specified {@code store}. + * @private + * @returns {Object} The new state that is the result of the reduction of the + * specified {@code action}. + */ +function _conferenceJoined({ 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); + } + }); + + return result; +}