From f1dbc8a8eb451080721bc9b6296418e22b507e00 Mon Sep 17 00:00:00 2001 From: AtilaU19 Date: Mon, 18 Sep 2023 19:02:21 -0300 Subject: [PATCH 1/8] feat(reactions): port new reations --- .../reactions-button/component.jsx | 2 +- .../imports/ui/components/app/component.jsx | 2 + .../ui/components/emoji-rain/component.jsx | 111 ++++++++++++++++++ .../ui/components/emoji-rain/container.jsx | 11 ++ .../ui/components/emoji-rain/service.js | 9 ++ .../private/config/settings.yml | 8 ++ 6 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 bigbluebutton-html5/imports/ui/components/emoji-rain/component.jsx create mode 100644 bigbluebutton-html5/imports/ui/components/emoji-rain/container.jsx create mode 100644 bigbluebutton-html5/imports/ui/components/emoji-rain/service.js diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/reactions-button/component.jsx b/bigbluebutton-html5/imports/ui/components/actions-bar/reactions-button/component.jsx index d39e8cd2e5..da65ee50ec 100644 --- a/bigbluebutton-html5/imports/ui/components/actions-bar/reactions-button/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/actions-bar/reactions-button/component.jsx @@ -140,7 +140,7 @@ const ReactionsButton = (props) => { return ( + {this.renderActionsBar()} + {customStyleUrl ? : null} {customStyle ? : null} {isRandomUserSelectModalOpen ? { + const containerRef = useRef(null); + const [isAnimating, setIsAnimating] = useState(false); + const EMOJI_SIZE = Meteor.settings.public.app.emojiRain.emojiSize; + const NUMBER_OF_EMOJIS = Meteor.settings.public.app.emojiRain.numberOfEmojis; + const EMOJI_RAIN_ENABLED = Meteor.settings.public.app.emojiRain.enabled; + + const { animations } = Settings.application; + + function createEmojiRain(emoji) { + const coord = Service.getInteractionsButtonCoordenates(); + const flyingEmojis = []; + + for (i = 0; i < NUMBER_OF_EMOJIS; i++) { + const initialPosition = { + x: coord.x + coord.width / 8, + y: coord.y + coord.height / 5, + }; + const endPosition = { + x: Math.floor(Math.random() * 100) + coord.x - 100 / 2, + y: Math.floor(Math.random() * 300) + coord.y / 2, + }; + const scale = Math.floor(Math.random() * (8 - 4 + 1)) - 40; + const sec = Math.floor(Math.random() * 1700) + 2000; + + const shapeElement = document.createElement('svg'); + const emojiElement = document.createElement('text'); + emojiElement.setAttribute('x', '50%'); + emojiElement.setAttribute('y', '50%'); + emojiElement.innerHTML = emoji; + + shapeElement.style.position = 'absolute'; + shapeElement.style.left = `${initialPosition.x}px`; + shapeElement.style.top = `${initialPosition.y}px`; + shapeElement.style.transform = `scaleX(0.${scale}) scaleY(0.${scale})`; + shapeElement.style.transition = `${sec}ms`; + shapeElement.style.fontSize = `${EMOJI_SIZE}em`; + shapeElement.style.pointerEvents = 'none'; + + shapeElement.appendChild(emojiElement); + containerRef.current.appendChild(shapeElement); + + flyingEmojis.push({ shapeElement, endPosition }); + } + + requestAnimationFrame(() => setTimeout(() => flyingEmojis.forEach((emoji) => { + const { shapeElement, endPosition } = emoji; + shapeElement.style.left = `${endPosition.x}px`; + shapeElement.style.top = `${endPosition.y}px`; + shapeElement.style.transform = 'scaleX(0) scaleY(0)'; + }), 0)); + + setTimeout(() => { + flyingEmojis.forEach((emoji) => emoji.shapeElement.remove()); + flyingEmojis.length = 0; + }, 2000); + } + + const handleVisibilityChange = () => { + if (document.hidden) { + setIsAnimating(false); + } else if (EMOJI_RAIN_ENABLED && animations) { + setIsAnimating(true); + } + }; + + useEffect(() => { + document.addEventListener('visibilitychange', handleVisibilityChange); + + return () => { + document.removeEventListener('visibilitychange', handleVisibilityChange); + }; + }, []); + + useEffect(() => { + if (EMOJI_RAIN_ENABLED && animations && !isAnimating && !document.hidden) { + setIsAnimating(true); + } else if (!animations) { + setIsAnimating(false); + } + }, [EMOJI_RAIN_ENABLED, animations, isAnimating]); + + useEffect(() => { + if (isAnimating) { + reactions.forEach((reaction) => { + if (Date() == reaction.creationDate && (reaction.reaction !== 'none')) { + createEmojiRain(reaction.reaction); + } + }); + } + }, [isAnimating, reactions]); + + const containerStyle = { + width: '100vw', + height: '100vh', + position: 'fixed', + top: 0, + left: 0, + overflow: 'hidden', + pointerEvents: 'none', + zIndex: 2, + }; + + return
; +}; + +export default EmojiRain; diff --git a/bigbluebutton-html5/imports/ui/components/emoji-rain/container.jsx b/bigbluebutton-html5/imports/ui/components/emoji-rain/container.jsx new file mode 100644 index 0000000000..d6f24ef798 --- /dev/null +++ b/bigbluebutton-html5/imports/ui/components/emoji-rain/container.jsx @@ -0,0 +1,11 @@ +import React from 'react'; +import { withTracker } from 'meteor/react-meteor-data'; +import EmojiRain from './component'; +import UserReaction from '/imports/api/user-reaction'; +import Auth from '/imports/ui/services/auth'; + +const EmojiRainContainer = (props) => ; + +export default withTracker(() => ({ + reactions: UserReaction.find({ meetingId: Auth.meetingID }).fetch(), +}))(EmojiRainContainer); diff --git a/bigbluebutton-html5/imports/ui/components/emoji-rain/service.js b/bigbluebutton-html5/imports/ui/components/emoji-rain/service.js new file mode 100644 index 0000000000..69b221e8d4 --- /dev/null +++ b/bigbluebutton-html5/imports/ui/components/emoji-rain/service.js @@ -0,0 +1,9 @@ +const getInteractionsButtonCoordenates = () => { + const el = document.getElementById('interactionsButton'); + const coordenada = el.getBoundingClientRect(); + return coordenada; +}; + +export default { + getInteractionsButtonCoordenates, +}; diff --git a/bigbluebutton-html5/private/config/settings.yml b/bigbluebutton-html5/private/config/settings.yml index fe33f90ece..1f2fd1bae4 100755 --- a/bigbluebutton-html5/private/config/settings.yml +++ b/bigbluebutton-html5/private/config/settings.yml @@ -152,6 +152,14 @@ public: # Enables the new raiseHand icon inside of the reaction menu (introduced in BBB 2.7) # If both reactionsButton and raiseHandActionButton are enabled, reactionsButton takes precedence. enabled: true + emojiRain: + # If true, new reactions will be activated + enabled: false + # Can set the throttle, the number of emojis that will be displayed and their size + intervalEmojis: 2000 + numberOfEmojis: 5 + # emojiSize: size of the emoji in 'em' units + emojiSize: 2 # If enabled, before joining microphone the client will perform a trickle # ICE against Kurento and use the information about successfull # candidate-pairs to filter out local candidates in SIP.js's SDP. From ac3c7790d4781ab5af77d5150c21915ceadd1be4 Mon Sep 17 00:00:00 2001 From: AtilaU19 Date: Mon, 16 Oct 2023 14:17:11 -0300 Subject: [PATCH 2/8] refactor(emoji-picker): update emoji-mart to latest version --- .../ui/components/actions-bar/styles.js | 29 ++------ .../chat/message-form/component.jsx | 4 +- .../ui/components/chat/message-form/styles.js | 18 ++--- .../ui/components/emoji-picker/component.jsx | 34 +++------- .../reactions-picker/component.jsx | 66 ++++++------------- bigbluebutton-html5/package.json | 4 +- .../private/config/settings.yml | 3 +- 7 files changed, 46 insertions(+), 112 deletions(-) diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/styles.js b/bigbluebutton-html5/imports/ui/components/actions-bar/styles.js index 5691c23702..30d42e0c31 100644 --- a/bigbluebutton-html5/imports/ui/components/actions-bar/styles.js +++ b/bigbluebutton-html5/imports/ui/components/actions-bar/styles.js @@ -101,28 +101,13 @@ const ReactionsDropdown = styled.div` `; const Wrapper = styled.div` - .emoji-mart-bar { - display: none; - } - .emoji-mart-search { - display: none; - } - .emoji-mart-category[aria-label="Frequently Used"] { - display: none; - } - .emoji-mart-category-label{ - display: none; - } - .emoji-mart{ - border: none; - } - @media(min-width: 600px) { - .emoji-mart-scroll{ - overflow:hidden; - padding: 0; - height: 270px; - width: 280px; - } + overflow: hidden; + padding: 5px; + text-align: center; + max-height: 270px; + width: 270px; + em-emoji { + cursor: pointer; } `; diff --git a/bigbluebutton-html5/imports/ui/components/chat/message-form/component.jsx b/bigbluebutton-html5/imports/ui/components/chat/message-form/component.jsx index 178d10de2f..21da509dae 100755 --- a/bigbluebutton-html5/imports/ui/components/chat/message-form/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/chat/message-form/component.jsx @@ -249,7 +249,7 @@ class MessageForm extends PureComponent { stopUserTyping, } = this.props; const { message } = this.state; - let msg = message.trim(); + const msg = message.trim(); if (msg.length < minMessageLength) return; @@ -289,8 +289,6 @@ class MessageForm extends PureComponent { this.handleEmojiSelect(emojiObject)} - showPreview={false} - showSkinTones={false} /> ); diff --git a/bigbluebutton-html5/imports/ui/components/chat/message-form/styles.js b/bigbluebutton-html5/imports/ui/components/chat/message-form/styles.js index 343552b51c..d8d91d50b9 100644 --- a/bigbluebutton-html5/imports/ui/components/chat/message-form/styles.js +++ b/bigbluebutton-html5/imports/ui/components/chat/message-form/styles.js @@ -109,21 +109,11 @@ const EmojiButton = styled(Button)` `; const EmojiPickerWrapper = styled.div` - .emoji-mart { - max-width: 100% !important; - } - .emoji-mart-anchor { - cursor: pointer; - } - .emoji-mart-emoji { - cursor: pointer !important; - } - .emoji-mart-category-list { - span { - cursor: pointer !important; - display: inline-block !important; - } + em-emoji-picker { + width: 100%; + max-height: 300px; } + padding-bottom: 5px; `; const EmojiPicker = styled(EmojiPickerComponent)``; diff --git a/bigbluebutton-html5/imports/ui/components/emoji-picker/component.jsx b/bigbluebutton-html5/imports/ui/components/emoji-picker/component.jsx index 2c630fbda2..0b3b015db4 100644 --- a/bigbluebutton-html5/imports/ui/components/emoji-picker/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/emoji-picker/component.jsx @@ -1,26 +1,16 @@ import React from 'react'; import PropTypes from 'prop-types'; import { injectIntl } from 'react-intl'; -import { Picker } from 'emoji-mart'; -import 'emoji-mart/css/emoji-mart.css'; +import data from '@emoji-mart/data'; +import Picker from '@emoji-mart/react'; const DISABLE_EMOJIS = Meteor.settings.public.chat.disableEmojis; -const FREQUENT_SORT_ON_CLICK = Meteor.settings.public.chat.emojiPicker.frequentEmojiSortOnClick; const propTypes = { intl: PropTypes.shape({ formatMessage: PropTypes.func.isRequired, }).isRequired, onEmojiSelect: PropTypes.func.isRequired, - style: PropTypes.shape({}), - showPreview: PropTypes.bool, - showSkinTones: PropTypes.bool, -}; - -const defaultProps = { - style: null, - showPreview: true, - showSkinTones: true, }; const emojisToExclude = [ @@ -31,8 +21,6 @@ const EmojiPicker = (props) => { const { intl, onEmojiSelect, - showPreview, - showSkinTones, } = props; const i18n = { @@ -65,23 +53,19 @@ const EmojiPicker = (props) => { return ( onEmojiSelect(emojiObject, event)} - enableFrequentEmojiSort={FREQUENT_SORT_ON_CLICK} - native - title="" + data={data} + onEmojiSelect={(emojiObject, event) => onEmojiSelect(emojiObject, event)} emojiSize={24} - emojiTooltip i18n={i18n} - showPreview={showPreview} - showSkinTones={showSkinTones} - useButton - emojisToShowFilter={(emoji) => !emojisToExclude.includes(emoji.unified)} + previewPosition="none" + skinTonePosition="none" + theme="light" + dynamicWidth + exceptEmojis={emojisToExclude} /> ); }; EmojiPicker.propTypes = propTypes; -EmojiPicker.defaultProps = defaultProps; export default injectIntl(EmojiPicker); diff --git a/bigbluebutton-html5/imports/ui/components/emoji-picker/reactions-picker/component.jsx b/bigbluebutton-html5/imports/ui/components/emoji-picker/reactions-picker/component.jsx index 01731e7ee4..dfa6ab616d 100644 --- a/bigbluebutton-html5/imports/ui/components/emoji-picker/reactions-picker/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/emoji-picker/reactions-picker/component.jsx @@ -1,71 +1,47 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { injectIntl } from 'react-intl'; -import { Picker } from 'emoji-mart'; -import 'emoji-mart/css/emoji-mart.css'; +import data from '@emoji-mart/data'; +import { init } from 'emoji-mart'; const propTypes = { - intl: PropTypes.shape({ - formatMessage: PropTypes.func.isRequired, - }).isRequired, onEmojiSelect: PropTypes.func.isRequired, }; const defaultProps = { }; -const emojisToExclude = [ +const emojisToInclude = [ // reactions - '1F605', '1F61C', '1F604', '1F609', '1F602', '1F92A', - '1F634', '1F62C', '1F633', '1F60D', '02665', '1F499', - '1F615', '1F61F', '1F928', '1F644', '1F612', '1F621', - '1F614', '1F625', '1F62D', '1F62F', '1F631', '1F630', - '1F44F', '1F44C', '1F44D', '1F44E', '1F4AA', '1F44A', - '1F64C', '1F64F', '1F440', '1F4A9', '1F921', '1F480', + '๐Ÿ˜„', '๐Ÿ˜…', '๐Ÿ˜‚', '๐Ÿ˜‰', '๐Ÿ˜', '๐Ÿ˜œ', + '๐Ÿคช', '๐Ÿคจ', '๐Ÿ˜’', '๐Ÿ™„', '๐Ÿ˜ฌ', '๐Ÿ˜”', + '๐Ÿ˜ด', '๐Ÿ˜•', '๐Ÿ˜Ÿ', '๐Ÿ˜ฏ', '๐Ÿ˜ณ', '๐Ÿ˜ฐ', + '๐Ÿ˜ฅ', '๐Ÿ˜ญ', '๐Ÿ˜ฑ', '๐Ÿ˜ก', '๐Ÿ’€', '๐Ÿ’ฉ', + '๐Ÿคก', '๐Ÿ‘Œ', '๐Ÿ‘', '๐Ÿ‘Ž', '๐Ÿ‘Š', '๐Ÿ‘', + '๐Ÿ™Œ', '๐Ÿ™', '๐Ÿ’ช', '๐Ÿ‘€', 'โค๏ธ', '๐Ÿ’™', ]; -const inlineStyle = { - margin: '.5rem 0', - alignSelf: 'center', - width: '100%', -}; - const ReactionsPicker = (props) => { const { - intl, onEmojiSelect, - style, } = props; - const i18n = { - notfound: intl.formatMessage({ id: 'app.emojiPicker.notFound' }), - clear: intl.formatMessage({ id: 'app.emojiPicker.clear' }), - skintext: intl.formatMessage({ id: 'app.emojiPicker.skintext' }), - categories: { - reactions: intl.formatMessage({ id: 'app.emojiPicker.categories.reactions' }), - }, - categorieslabel: intl.formatMessage({ id: 'app.emojiPicker.categories.label' }), - }; + init({ data }); return ( - onEmojiSelect(emojiObject, event)} - native - emoji="" - title="" - emojiSize={30} - emojiTooltip - style={Object.assign(inlineStyle, style)} - i18n={i18n} - showPreview={false} - showSkinTones={false} - emojisToShowFilter={(emoji) => emojisToExclude.includes(emoji.unified)} - /> - + <> + {emojisToInclude.map((native) => ( + onEmojiSelect({ native })} + /> + ))} + ); }; ReactionsPicker.propTypes = propTypes; ReactionsPicker.defaultProps = defaultProps; -export default injectIntl(ReactionsPicker); +export default ReactionsPicker; diff --git a/bigbluebutton-html5/package.json b/bigbluebutton-html5/package.json index fe779c1fa5..c188f1eaaf 100644 --- a/bigbluebutton-html5/package.json +++ b/bigbluebutton-html5/package.json @@ -31,6 +31,8 @@ "dependencies": { "@babel/runtime": "^7.17.9", "@browser-bunyan/server-stream": "^1.8.0", + "@emoji-mart/data": "^1.1.2", + "@emoji-mart/react": "^1.1.1", "@emotion/react": "^11.10.8", "@emotion/styled": "^11.10.8", "@jitsi/sdp-interop": "0.1.14", @@ -45,7 +47,7 @@ "browser-bunyan": "^1.8.0", "classnames": "^2.2.6", "darkreader": "^4.9.46", - "emoji-mart": "^3.0.1", + "emoji-mart": "^5.5.2", "eventemitter2": "~6.4.6", "fastdom": "^1.0.10", "fibers": "^4.0.2", diff --git a/bigbluebutton-html5/private/config/settings.yml b/bigbluebutton-html5/private/config/settings.yml index 1f2fd1bae4..983fbad872 100755 --- a/bigbluebutton-html5/private/config/settings.yml +++ b/bigbluebutton-html5/private/config/settings.yml @@ -597,8 +597,7 @@ public: autoConvertEmoji: true emojiPicker: enable: false - frequentEmojiSortOnClick: false - # e.g.: disableEmojis: ['1F595','1F922'] + # e.g.: disableEmojis: ['grin','laughing'] disableEmojis: [] userReaction: enabled: true From 11f5481b5a2e048a21a8b1f797756fec877afc10 Mon Sep 17 00:00:00 2001 From: AtilaU19 Date: Mon, 16 Oct 2023 14:31:32 -0300 Subject: [PATCH 3/8] fix(reactions): New style for emoji reactions and visual cooldown --- .../ui/components/actions-bar/styles.js | 2 +- .../reactions-picker/component.jsx | 31 ++++++++++++---- .../emoji-picker/reactions-picker/styles.js | 35 +++++++++++++++++++ 3 files changed, 60 insertions(+), 8 deletions(-) create mode 100644 bigbluebutton-html5/imports/ui/components/emoji-picker/reactions-picker/styles.js diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/styles.js b/bigbluebutton-html5/imports/ui/components/actions-bar/styles.js index 30d42e0c31..5ca77665bd 100644 --- a/bigbluebutton-html5/imports/ui/components/actions-bar/styles.js +++ b/bigbluebutton-html5/imports/ui/components/actions-bar/styles.js @@ -102,7 +102,7 @@ const ReactionsDropdown = styled.div` const Wrapper = styled.div` overflow: hidden; - padding: 5px; + margin: 0.2em 0.2em 0.2em 0.2em; text-align: center; max-height: 270px; width: 270px; diff --git a/bigbluebutton-html5/imports/ui/components/emoji-picker/reactions-picker/component.jsx b/bigbluebutton-html5/imports/ui/components/emoji-picker/reactions-picker/component.jsx index dfa6ab616d..07b99610be 100644 --- a/bigbluebutton-html5/imports/ui/components/emoji-picker/reactions-picker/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/emoji-picker/reactions-picker/component.jsx @@ -1,7 +1,10 @@ -import React from 'react'; +import React, { useState } from 'react'; import PropTypes from 'prop-types'; import data from '@emoji-mart/data'; import { init } from 'emoji-mart'; +import Styled from './styles'; + +const DISABLED_INTERVAL = Meteor.settings.public.app.emojiRain.intervalEmojis; const propTypes = { onEmojiSelect: PropTypes.func.isRequired, @@ -25,17 +28,31 @@ const ReactionsPicker = (props) => { onEmojiSelect, } = props; + const [selected, setSelected] = useState(null); + + const onEmojiClick = (native) => { + onEmojiSelect({ native }); + setSelected(native); + + setTimeout(() => { + setSelected(null); + }, DISABLED_INTERVAL); + }; + init({ data }); return ( <> {emojisToInclude.map((native) => ( - onEmojiSelect({ native })} - /> + + !selected && onEmojiClick(native)} + /> + ))} ); diff --git a/bigbluebutton-html5/imports/ui/components/emoji-picker/reactions-picker/styles.js b/bigbluebutton-html5/imports/ui/components/emoji-picker/reactions-picker/styles.js new file mode 100644 index 0000000000..fda0dd7df3 --- /dev/null +++ b/bigbluebutton-html5/imports/ui/components/emoji-picker/reactions-picker/styles.js @@ -0,0 +1,35 @@ +import styled, { css } from 'styled-components'; + +const EmojiWrapper = styled.span` + padding-top: 0.9em; + padding-bottom: 0.1em; + ${({ selected }) => !selected && css` + :hover { + border-radius:100%; + outline-color: transparent; + outline-style:solid; + box-shadow: 0 0 0 0.25em #eee; + background-color: #eee; + opacity: 0.75; + } + `} + ${({ selected }) => selected && css` + em-emoji { + cursor: not-allowed; + } + `} + ${({ selected, emoji }) => selected && selected !== emoji && css` + opacity: 0.75; + `} + ${({ selected, emoji }) => selected && selected === emoji && css` + border-radius:100%; + outline-color: transparent; + outline-style:solid; + box-shadow: 0 0 0 0.25em #eee; + background-color: #eee; + `} +`; + +export default { + EmojiWrapper, +}; From 5f1bed6d444c1dd55033ba330d5b21c35a559238 Mon Sep 17 00:00:00 2001 From: Lucas Fialho Zawacki Date: Tue, 17 Oct 2023 16:08:14 -0300 Subject: [PATCH 4/8] fix(reactions): Fix react errors on new emoji-mart version --- .../reactions-button/component.jsx | 20 +++++++++++++------ .../user-list-item/component.jsx | 17 ++++++++++++---- bigbluebutton-html5/package-lock.json | 20 ++++++++++++------- 3 files changed, 40 insertions(+), 17 deletions(-) diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/reactions-button/component.jsx b/bigbluebutton-html5/imports/ui/components/actions-bar/reactions-button/component.jsx index da65ee50ec..a97290e04f 100644 --- a/bigbluebutton-html5/imports/ui/components/actions-bar/reactions-button/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/actions-bar/reactions-button/component.jsx @@ -4,8 +4,9 @@ import PropTypes from 'prop-types'; import BBBMenu from '/imports/ui/components/common/menu/component'; import UserReactionService from '/imports/ui/components/user-reaction/service'; import UserListService from '/imports/ui/components/user-list/service'; -import { Emoji } from 'emoji-mart'; import { convertRemToPixels } from '/imports/utils/dom-utils'; +import data from '@emoji-mart/data'; +import { init } from 'emoji-mart'; import Styled from './styles'; @@ -20,6 +21,9 @@ const ReactionsButton = (props) => { autoCloseReactionsBar, } = props; + // initialize emoji-mart data, need for the new version + init({ data }); + const [showEmojiPicker, setShowEmojiPicker] = useState(false); const intlMessages = defineMessages({ @@ -74,11 +78,15 @@ const ReactionsButton = (props) => { }; const emojiProps = { - native: true, size: convertRemToPixels(1.5), padding: '4px', }; + const handReaction = { + id: 'hand', + native: 'โœ‹', + }; + const reactions = [ { id: 'smiley', @@ -110,7 +118,7 @@ const ReactionsButton = (props) => { reactions.forEach(({ id, native }) => { actions.push({ - label: , + label: , key: id, onClick: () => handleReactionSelect(native), customStyles: actionCustomStyles, @@ -118,7 +126,7 @@ const ReactionsButton = (props) => { }); actions.push({ - label: {RaiseHandButtonLabel()}, + label: {RaiseHandButtonLabel()}, key: 'hand', onClick: () => handleRaiseHandButtonClick(), customStyles: {...actionCustomStyles, width: 'auto'}, @@ -130,10 +138,10 @@ const ReactionsButton = (props) => { let customIcon = null; if (raiseHand) { - customIcon = ; + customIcon = ; } else { if (!icon) { - customIcon = ; + customIcon = ; } } diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/component.jsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/component.jsx index 598191108d..5cfb8695b6 100644 --- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-item/component.jsx @@ -4,7 +4,6 @@ import { injectIntl, defineMessages } from 'react-intl'; import TooltipContainer from '/imports/ui/components/common/tooltip/container'; import { Session } from 'meteor/session'; import { findDOMNode } from 'react-dom'; -import { Emoji } from 'emoji-mart'; import UserAvatar from '/imports/ui/components/user-avatar/component'; import Icon from '/imports/ui/components/common/icon/component'; import lockContextContainer from '/imports/ui/components/lock-viewers/context/container'; @@ -634,20 +633,30 @@ class UserListItem extends PureComponent { } = this.props; const emojiProps = { - native: true, size: '1.3rem', }; let userAvatarFiltered = user.avatar; + const emojiIcons = [ + { + id: 'hand', + native: 'โœ‹', + }, + { + id: 'clock7', + native: 'โฐ', + }, + ]; + const getIconUser = () => { if (user.raiseHand === true) { return isReactionsEnabled - ? + ? : ; } if (user.away === true) { return isReactionsEnabled - ? + ? : ; } if (user.emoji !== 'none' && user.emoji !== 'notAway') { return ; diff --git a/bigbluebutton-html5/package-lock.json b/bigbluebutton-html5/package-lock.json index 7f842168cf..52833bfa19 100644 --- a/bigbluebutton-html5/package-lock.json +++ b/bigbluebutton-html5/package-lock.json @@ -337,6 +337,16 @@ "kuler": "^2.0.0" } }, + "@emoji-mart/data": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@emoji-mart/data/-/data-1.1.2.tgz", + "integrity": "sha512-1HP8BxD2azjqWJvxIaWAMyTySeZY0Osr83ukYjltPVkNXeJvTz7yDrPLBtnrD5uqJ3tg4CcLuuBW09wahqL/fg==" + }, + "@emoji-mart/react": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@emoji-mart/react/-/react-1.1.1.tgz", + "integrity": "sha512-NMlFNeWgv1//uPsvLxvGQoIerPuVdXwK/EUek8OOkJ6wVOWPUizRBJU0hDqWZCOROVpfBgCemaC3m6jDOXi03g==" + }, "@emotion/babel-plugin": { "version": "11.11.0", "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", @@ -2808,13 +2818,9 @@ "integrity": "sha512-ypZHxY+Sf/PXu7LVN+xoeanyisnJeSOy8Ki439L/oLueZb4c72FI45zXcK3gPpmTwyufh9m6NnbMLXnJh/0Fxg==" }, "emoji-mart": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/emoji-mart/-/emoji-mart-3.0.1.tgz", - "integrity": "sha512-sxpmMKxqLvcscu6mFn9ITHeZNkGzIvD0BSNFE/LJESPbCA8s1jM6bCDPjWbV31xHq7JXaxgpHxLB54RCbBZSlg==", - "requires": { - "@babel/runtime": "^7.0.0", - "prop-types": "^15.6.0" - } + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/emoji-mart/-/emoji-mart-5.5.2.tgz", + "integrity": "sha512-Sqc/nso4cjxhOwWJsp9xkVm8OF5c+mJLZJFoFfzRuKO+yWiN7K8c96xmtughYb0d/fZ8UC6cLIQ/p4BR6Pv3/A==" }, "emoji-regex": { "version": "8.0.0", From b2f25decd6ef18ccf5331d94fd190f5e07e85663 Mon Sep 17 00:00:00 2001 From: Lucas Fialho Zawacki Date: Tue, 17 Oct 2023 18:44:05 -0300 Subject: [PATCH 5/8] fix(reactions): Get reaction emoji list from settings.yml --- .../reactions-button/component.jsx | 33 +++---------------- .../private/config/settings.yml | 13 ++++++++ 2 files changed, 17 insertions(+), 29 deletions(-) diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/reactions-button/component.jsx b/bigbluebutton-html5/imports/ui/components/actions-bar/reactions-button/component.jsx index a97290e04f..efc1fd658b 100644 --- a/bigbluebutton-html5/imports/ui/components/actions-bar/reactions-button/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/actions-bar/reactions-button/component.jsx @@ -10,6 +10,8 @@ import { init } from 'emoji-mart'; import Styled from './styles'; +const REACTIONS = Meteor.settings.public.userReaction.reactions; + const ReactionsButton = (props) => { const { intl, @@ -87,36 +89,9 @@ const ReactionsButton = (props) => { native: 'โœ‹', }; - const reactions = [ - { - id: 'smiley', - native: '๐Ÿ˜ƒ', - }, - { - id: 'neutral_face', - native: '๐Ÿ˜', - }, - { - id: 'slightly_frowning_face', - native: '๐Ÿ™', - }, - { - id: '+1', - native: '๐Ÿ‘', - }, - { - id: '-1', - native: '๐Ÿ‘Ž', - }, - { - id: 'clap', - native: '๐Ÿ‘', - }, - ]; - let actions = []; - reactions.forEach(({ id, native }) => { + REACTIONS.forEach(({ id, native }) => { actions.push({ label: , key: id, @@ -133,7 +108,7 @@ const ReactionsButton = (props) => { }); const icon = !raiseHand && currentUserReaction === 'none' ? 'hand' : null; - const currentUserReactionEmoji = reactions.find(({ native }) => native === currentUserReaction); + const currentUserReactionEmoji = REACTIONS.find(({ native }) => native === currentUserReaction); let customIcon = null; diff --git a/bigbluebutton-html5/private/config/settings.yml b/bigbluebutton-html5/private/config/settings.yml index 983fbad872..4193a4ffc9 100755 --- a/bigbluebutton-html5/private/config/settings.yml +++ b/bigbluebutton-html5/private/config/settings.yml @@ -602,6 +602,19 @@ public: userReaction: enabled: true expire: 60 + reactions: + - id: 'smiley' + native: '๐Ÿ˜ƒ' + - id: 'neutral_face' + native: '๐Ÿ˜' + - id: 'slightly_frowning_face' + native: '๐Ÿ™' + - id: '+1' + native: '๐Ÿ‘' + - id: '-1' + native: '๐Ÿ‘Ž' + - id: 'clap' + native: '๐Ÿ‘' userStatus: enabled: false notes: From cb075137b3a84e4f881f2b6025785ad38568a313 Mon Sep 17 00:00:00 2001 From: germanocaumo Date: Tue, 26 Sep 2023 15:18:40 -0300 Subject: [PATCH 6/8] fix(emoji-rain): increase date comparison trigger The date comparison check was too strict/wrong, increase it to show the emojis created in the last second to account for delays in connection. --- .../imports/ui/components/emoji-rain/component.jsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bigbluebutton-html5/imports/ui/components/emoji-rain/component.jsx b/bigbluebutton-html5/imports/ui/components/emoji-rain/component.jsx index 180e37e921..0860915141 100644 --- a/bigbluebutton-html5/imports/ui/components/emoji-rain/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/emoji-rain/component.jsx @@ -87,7 +87,10 @@ const EmojiRain = ({ reactions }) => { useEffect(() => { if (isAnimating) { reactions.forEach((reaction) => { - if (Date() == reaction.creationDate && (reaction.reaction !== 'none')) { + //if (Date() == reaction.creationDate && (reaction.reaction !== 'none')) { + const currentTime = new Date().getTime(); + const secondsSinceCreated = (currentTime - reaction.creationDate.getTime()) / 1000; + if (secondsSinceCreated <= 1 && (reaction.reaction !== 'none')) { createEmojiRain(reaction.reaction); } }); From 20b4ffe7dd707a210e9e276a9a75e208469cc589 Mon Sep 17 00:00:00 2001 From: Lucas Fialho Zawacki Date: Tue, 17 Oct 2023 19:06:37 -0300 Subject: [PATCH 7/8] fix(reactions): Remove unused file --- .../reactions-picker/component.jsx | 64 ------------------- 1 file changed, 64 deletions(-) delete mode 100644 bigbluebutton-html5/imports/ui/components/emoji-picker/reactions-picker/component.jsx diff --git a/bigbluebutton-html5/imports/ui/components/emoji-picker/reactions-picker/component.jsx b/bigbluebutton-html5/imports/ui/components/emoji-picker/reactions-picker/component.jsx deleted file mode 100644 index 07b99610be..0000000000 --- a/bigbluebutton-html5/imports/ui/components/emoji-picker/reactions-picker/component.jsx +++ /dev/null @@ -1,64 +0,0 @@ -import React, { useState } from 'react'; -import PropTypes from 'prop-types'; -import data from '@emoji-mart/data'; -import { init } from 'emoji-mart'; -import Styled from './styles'; - -const DISABLED_INTERVAL = Meteor.settings.public.app.emojiRain.intervalEmojis; - -const propTypes = { - onEmojiSelect: PropTypes.func.isRequired, -}; - -const defaultProps = { -}; - -const emojisToInclude = [ - // reactions - '๐Ÿ˜„', '๐Ÿ˜…', '๐Ÿ˜‚', '๐Ÿ˜‰', '๐Ÿ˜', '๐Ÿ˜œ', - '๐Ÿคช', '๐Ÿคจ', '๐Ÿ˜’', '๐Ÿ™„', '๐Ÿ˜ฌ', '๐Ÿ˜”', - '๐Ÿ˜ด', '๐Ÿ˜•', '๐Ÿ˜Ÿ', '๐Ÿ˜ฏ', '๐Ÿ˜ณ', '๐Ÿ˜ฐ', - '๐Ÿ˜ฅ', '๐Ÿ˜ญ', '๐Ÿ˜ฑ', '๐Ÿ˜ก', '๐Ÿ’€', '๐Ÿ’ฉ', - '๐Ÿคก', '๐Ÿ‘Œ', '๐Ÿ‘', '๐Ÿ‘Ž', '๐Ÿ‘Š', '๐Ÿ‘', - '๐Ÿ™Œ', '๐Ÿ™', '๐Ÿ’ช', '๐Ÿ‘€', 'โค๏ธ', '๐Ÿ’™', -]; - -const ReactionsPicker = (props) => { - const { - onEmojiSelect, - } = props; - - const [selected, setSelected] = useState(null); - - const onEmojiClick = (native) => { - onEmojiSelect({ native }); - setSelected(native); - - setTimeout(() => { - setSelected(null); - }, DISABLED_INTERVAL); - }; - - init({ data }); - - return ( - <> - {emojisToInclude.map((native) => ( - - !selected && onEmojiClick(native)} - /> - - ))} - - ); -}; - -ReactionsPicker.propTypes = propTypes; -ReactionsPicker.defaultProps = defaultProps; - -export default ReactionsPicker; From 577ed647d9c6ce315c73067f24f16037a76b9ef7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C3=B3n=20Souza?= Date: Wed, 18 Oct 2023 09:28:30 -0300 Subject: [PATCH 8/8] Update bigbluebutton-html5/imports/ui/components/emoji-rain/component.jsx --- .../imports/ui/components/emoji-rain/component.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/bigbluebutton-html5/imports/ui/components/emoji-rain/component.jsx b/bigbluebutton-html5/imports/ui/components/emoji-rain/component.jsx index 0860915141..8cca52e402 100644 --- a/bigbluebutton-html5/imports/ui/components/emoji-rain/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/emoji-rain/component.jsx @@ -87,7 +87,6 @@ const EmojiRain = ({ reactions }) => { useEffect(() => { if (isAnimating) { reactions.forEach((reaction) => { - //if (Date() == reaction.creationDate && (reaction.reaction !== 'none')) { const currentTime = new Date().getTime(); const secondsSinceCreated = (currentTime - reaction.creationDate.getTime()) / 1000; if (secondsSinceCreated <= 1 && (reaction.reaction !== 'none')) {