From e070b586c401c24f8221831842f563d90086fcc2 Mon Sep 17 00:00:00 2001 From: Joao Victor Date: Fri, 13 May 2022 10:42:19 -0300 Subject: [PATCH] [2.5] fix: popover menus in RTL mode --- .../actions-bar/actions-dropdown/component.jsx | 7 ++++--- .../actions-bar/actions-dropdown/container.jsx | 4 +++- .../components/audio/audio-controls/component.jsx | 4 ++-- .../components/audio/audio-controls/container.jsx | 4 +++- .../input-stream-live-selector/component.jsx | 11 +++++++++++ .../breakout-room/breakout-dropdown/component.jsx | 5 +++-- .../ui/components/breakout-room/component.jsx | 2 ++ .../ui/components/breakout-room/container.jsx | 5 +++-- .../ui/components/chat/chat-dropdown/component.jsx | 5 +++-- .../ui/components/chat/chat-dropdown/container.jsx | 4 +++- .../components/common/button/button-emoji/styles.js | 10 ++++++++++ .../imports/ui/components/common/menu/component.jsx | 9 +++++---- .../imports/ui/components/layout/initState.js | 4 ++-- .../nav-bar/settings-dropdown/component.jsx | 13 ++++++++++++- .../nav-bar/settings-dropdown/container.jsx | 5 +++-- .../user-participants/user-options/component.jsx | 12 +++++++++++- .../user-participants/user-options/container.jsx | 4 ++++ .../video-list/video-list-item/component.jsx | 3 ++- .../video-list/video-list-item/container.jsx | 2 ++ .../video-list-item/user-actions/component.jsx | 7 ++++--- 20 files changed, 92 insertions(+), 28 deletions(-) diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/actions-dropdown/component.jsx b/bigbluebutton-html5/imports/ui/components/actions-bar/actions-dropdown/component.jsx index 7e9d16002a..b815510135 100755 --- a/bigbluebutton-html5/imports/ui/components/actions-bar/actions-dropdown/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/actions-bar/actions-dropdown/component.jsx @@ -251,6 +251,7 @@ class ActionsDropdown extends PureComponent { isMeteorConnected, isDropdownOpen, isMobile, + isRTL, } = this.props; const availableActions = this.getAvailableActions(); @@ -263,7 +264,7 @@ class ActionsDropdown extends PureComponent { || !isMeteorConnected) { return null; } - const customStyles = { top: '-3rem' }; + const customStyles = { top: '-1rem' }; return ( ); diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/actions-dropdown/container.jsx b/bigbluebutton-html5/imports/ui/components/actions-bar/actions-dropdown/container.jsx index 985c0911f5..c29f13c4c2 100644 --- a/bigbluebutton-html5/imports/ui/components/actions-bar/actions-dropdown/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/actions-bar/actions-dropdown/container.jsx @@ -4,7 +4,7 @@ import Presentations from '/imports/api/presentations'; import PresentationUploaderService from '/imports/ui/components/presentation/presentation-uploader/service'; import PresentationPodService from '/imports/ui/components/presentation-pod/service'; import ActionsDropdown from './component'; -import { layoutSelectInput, layoutDispatch } from '../../layout/context'; +import { layoutSelectInput, layoutDispatch, layoutSelect } from '../../layout/context'; import getFromUserSettings from '/imports/ui/services/users-settings'; import { SMALL_VIEWPORT_BREAKPOINT } from '../../layout/enums'; @@ -14,6 +14,7 @@ const ActionsDropdownContainer = (props) => { const { width: browserWidth } = layoutSelectInput((i) => i.browser); const isMobile = browserWidth <= SMALL_VIEWPORT_BREAKPOINT; const layoutContextDispatch = layoutDispatch(); + const isRTL = layoutSelect((i) => i.isRTL); return ( { sidebarContent, sidebarNavigation, isMobile, + isRTL, ...props, }} /> diff --git a/bigbluebutton-html5/imports/ui/components/audio/audio-controls/component.jsx b/bigbluebutton-html5/imports/ui/components/audio/audio-controls/component.jsx index f42e44b1d2..a5adaf4892 100755 --- a/bigbluebutton-html5/imports/ui/components/audio/audio-controls/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/audio/audio-controls/component.jsx @@ -79,9 +79,9 @@ class AudioControls extends PureComponent { } static renderLeaveButtonWithLiveStreamSelector(props) { - const { handleLeaveAudio } = props; + const { handleLeaveAudio, isRTL } = props; return ( - + ); } diff --git a/bigbluebutton-html5/imports/ui/components/audio/audio-controls/container.jsx b/bigbluebutton-html5/imports/ui/components/audio/audio-controls/container.jsx index a6bdc71692..d1f56b4805 100755 --- a/bigbluebutton-html5/imports/ui/components/audio/audio-controls/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/audio/audio-controls/container.jsx @@ -14,6 +14,7 @@ import { setUserSelectedMicrophone, setUserSelectedListenOnly, } from '../audio-modal/service'; +import { layoutSelect } from '/imports/ui/components/layout/context'; import Service from '../service'; import AppService from '/imports/ui/components/app/service'; @@ -25,7 +26,8 @@ const AudioControlsContainer = (props) => { const { users, lockSettings, userLocks, children, ...newProps } = props; - return ; + const isRTL = layoutSelect((i) => i.isRTL); + return ; }; const handleLeaveAudio = () => { diff --git a/bigbluebutton-html5/imports/ui/components/audio/audio-controls/input-stream-live-selector/component.jsx b/bigbluebutton-html5/imports/ui/components/audio/audio-controls/input-stream-live-selector/component.jsx index 16be3f8bf1..8da5c5339d 100644 --- a/bigbluebutton-html5/imports/ui/components/audio/audio-controls/input-stream-live-selector/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/audio/audio-controls/input-stream-live-selector/component.jsx @@ -263,6 +263,7 @@ class InputStreamLiveSelector extends Component { currentInputDeviceId, currentOutputDeviceId, isListenOnly, + isRTL, } = this.props; const inputDeviceList = !isListenOnly @@ -313,6 +314,16 @@ class InputStreamLiveSelector extends Component { )} actions={dropdownListComplete} + opts={{ + id: 'default-dropdown-menu', + keepMounted: true, + transitionDuration: 0, + elevation: 3, + getContentAnchorEl: null, + fullwidth: 'true', + anchorOrigin: { vertical: 'top', horizontal: isRTL ? 'left' : 'right' }, + transformOrigin: { vertical: 'bottom', horizontal: isRTL ? 'right' : 'left' }, + }} /> ); } diff --git a/bigbluebutton-html5/imports/ui/components/breakout-room/breakout-dropdown/component.jsx b/bigbluebutton-html5/imports/ui/components/breakout-room/breakout-dropdown/component.jsx index d486604c09..06a02b49a5 100644 --- a/bigbluebutton-html5/imports/ui/components/breakout-room/breakout-dropdown/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/breakout-room/breakout-dropdown/component.jsx @@ -65,6 +65,7 @@ class BreakoutDropdown extends PureComponent { render() { const { intl, + isRTL, } = this.props; return ( @@ -91,8 +92,8 @@ class BreakoutDropdown extends PureComponent { elevation: 3, getContentAnchorEl: null, fullwidth: "true", - anchorOrigin: { vertical: 'bottom', horizontal: 'left' }, - transformorigin: { vertical: 'bottom', horizontal: 'left' }, + anchorOrigin: { vertical: 'bottom', horizontal: isRTL ? 'right' : 'left' }, + transformOrigin: { vertical: 'top', horizontal: isRTL ? 'right' : 'left' }, }} actions={this.getAvailableActions()} /> diff --git a/bigbluebutton-html5/imports/ui/components/breakout-room/component.jsx b/bigbluebutton-html5/imports/ui/components/breakout-room/component.jsx index cc15d5f3bd..28bcd852f6 100644 --- a/bigbluebutton-html5/imports/ui/components/breakout-room/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/breakout-room/component.jsx @@ -547,6 +547,7 @@ class BreakoutRoom extends PureComponent { intl, endAllBreakouts, amIModerator, + isRTL, } = this.props; return ( this.panel = n}> @@ -568,6 +569,7 @@ class BreakoutRoom extends PureComponent { }} isMeteorConnected={isMeteorConnected} amIModerator={amIModerator} + isRTL={isRTL} /> ) } diff --git a/bigbluebutton-html5/imports/ui/components/breakout-room/container.jsx b/bigbluebutton-html5/imports/ui/components/breakout-room/container.jsx index 55e63ec158..59734a682c 100644 --- a/bigbluebutton-html5/imports/ui/components/breakout-room/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/breakout-room/container.jsx @@ -4,7 +4,7 @@ import AudioService from '/imports/ui/components/audio/service'; import AudioManager from '/imports/ui/services/audio-manager'; import BreakoutComponent from './component'; import Service from './service'; -import { layoutDispatch } from '../layout/context'; +import { layoutDispatch, layoutSelect } from '../layout/context'; import Auth from '/imports/ui/services/auth'; import { UsersContext } from '/imports/ui/components/components-data/users-context/context'; import { @@ -18,10 +18,11 @@ const BreakoutContainer = (props) => { const usingUsersContext = useContext(UsersContext); const { users } = usingUsersContext; const amIPresenter = users[Auth.meetingID][Auth.userID].presenter; + const isRTL = layoutSelect((i) => i.isRTL); return ; }; diff --git a/bigbluebutton-html5/imports/ui/components/chat/chat-dropdown/component.jsx b/bigbluebutton-html5/imports/ui/components/chat/chat-dropdown/component.jsx index b694f53751..70a57770ea 100755 --- a/bigbluebutton-html5/imports/ui/components/chat/chat-dropdown/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/chat/chat-dropdown/component.jsx @@ -131,6 +131,7 @@ class ChatDropdown extends PureComponent { const { intl, amIModerator, + isRTL, } = this.props; if (!amIModerator && !ENABLE_SAVE_AND_COPY_PUBLIC_CHAT) return null; @@ -158,8 +159,8 @@ class ChatDropdown extends PureComponent { elevation: 3, getContentAnchorEl: null, fullwidth: "true", - anchorOrigin: { vertical: 'bottom', horizontal: 'left' }, - transformorigin: { vertical: 'bottom', horizontal: 'left' }, + anchorOrigin: { vertical: 'bottom', horizontal: isRTL ? 'right' : 'left' }, + transformOrigin: { vertical: 'top', horizontal: isRTL ? 'right' : 'left' }, }} actions={this.getAvailableActions()} /> diff --git a/bigbluebutton-html5/imports/ui/components/chat/chat-dropdown/container.jsx b/bigbluebutton-html5/imports/ui/components/chat/chat-dropdown/container.jsx index c822a3a8ee..7888bb64c1 100644 --- a/bigbluebutton-html5/imports/ui/components/chat/chat-dropdown/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/chat/chat-dropdown/container.jsx @@ -4,12 +4,14 @@ import Auth from '/imports/ui/services/auth'; import Meetings from '/imports/api/meetings'; import { UsersContext } from '/imports/ui/components/components-data/users-context/context'; import ChatDropdown from './component'; +import { layoutSelect } from '../../layout/context'; const ChatDropdownContainer = ({ ...props }) => { const usingUsersContext = useContext(UsersContext); const { users } = usingUsersContext; + const isRTL = layoutSelect((i) => i.isRTL); - return ; + return ; }; export default withTracker(() => { diff --git a/bigbluebutton-html5/imports/ui/components/common/button/button-emoji/styles.js b/bigbluebutton-html5/imports/ui/components/common/button/button-emoji/styles.js index 682f8f9378..12d93e36ec 100644 --- a/bigbluebutton-html5/imports/ui/components/common/button/button-emoji/styles.js +++ b/bigbluebutton-html5/imports/ui/components/common/button/button-emoji/styles.js @@ -45,6 +45,11 @@ const EmojiButton = styled.button` z-index: 2; border: none; + [dir="rtl"] & { + right: initial; + left: -.2em; + } + &:hover { transform: scale(1.5); transition-duration: 150ms; @@ -70,6 +75,11 @@ const EmojiButtonSpace = styled.div` right: -.4em; bottom: -.2em; border-radius: 50%; + + [dir="rtl"] & { + right: initial; + left: -.4em; + } `; export default { diff --git a/bigbluebutton-html5/imports/ui/components/common/menu/component.jsx b/bigbluebutton-html5/imports/ui/components/common/menu/component.jsx index 93b1b51ded..c09695ac9c 100644 --- a/bigbluebutton-html5/imports/ui/components/common/menu/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/common/menu/component.jsx @@ -26,7 +26,7 @@ class BBBMenu extends React.Component { anchorEl: null, }; - this.opts = props.opts; + this.optsToMerge = {}; this.autoFocus = false; this.handleClick = this.handleClick.bind(this); @@ -112,7 +112,7 @@ class BBBMenu extends React.Component { render() { const { anchorEl } = this.state; - const { trigger, intl, customStyles, dataTest } = this.props; + const { trigger, intl, customStyles, dataTest, opts } = this.props; const actionsItems = this.makeMenuItems(); let menuStyles = { zIndex: 9999 }; @@ -129,7 +129,7 @@ class BBBMenu extends React.Component { const firefoxInputSource = !([1, 5].includes(e.nativeEvent.mozInputSource)); // 1 = mouse, 5 = touch (firefox only) const chromeInputSource = !(['mouse', 'touch'].includes(e.nativeEvent.pointerType)); - this.opts.autoFocus = firefoxInputSource && chromeInputSource; + this.optsToMerge.autoFocus = firefoxInputSource && chromeInputSource; this.handleClick(e); }} onKeyPress={(e) => { @@ -144,7 +144,8 @@ class BBBMenu extends React.Component { )} actions={this.renderMenuItems()} + opts={{ + id: "default-dropdown-menu", + keepMounted: true, + transitionDuration: 0, + elevation: 3, + getContentAnchorEl: null, + fullwidth: "true", + anchorOrigin: { vertical: 'bottom', horizontal: isRTL ? 'left' : 'right' }, + transformorigin: { vertical: 'top', horizontal: isRTL ? 'left' : 'right' }, + }} /> ); } diff --git a/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/container.jsx b/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/container.jsx index d476bf3003..7872351b8a 100755 --- a/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/container.jsx @@ -5,7 +5,7 @@ import browserInfo from '/imports/utils/browserInfo'; import SettingsDropdown from './component'; import FullscreenService from '/imports/ui/components/common/fullscreen-button/service'; import { meetingIsBreakout } from '/imports/ui/components/app/service'; -import { layoutSelectInput } from '../../layout/context'; +import { layoutSelectInput, layoutSelect } from '../../layout/context'; import { SMALL_VIEWPORT_BREAKPOINT } from '../../layout/enums'; const { isIphone } = deviceInfo; @@ -16,9 +16,10 @@ const noIOSFullscreen = !!(((isSafari && !isValidSafariVersion) || isIphone)); const SettingsDropdownContainer = (props) => { const { width: browserWidth } = layoutSelectInput((i) => i.browser); const isMobile = browserWidth <= SMALL_VIEWPORT_BREAKPOINT; + const isRTL = layoutSelect((i) => i.isRTL); return ( - + ); }; diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-options/component.jsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-options/component.jsx index 217b1e6b9a..e69d052191 100755 --- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-options/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-options/component.jsx @@ -343,7 +343,7 @@ class UserOptions extends PureComponent { } render() { - const { intl } = this.props; + const { intl, isRTL } = this.props; return ( )} actions={this.renderMenuItems()} + opts={{ + id: "default-dropdown-menu", + keepMounted: true, + transitionDuration: 0, + elevation: 3, + getContentAnchorEl: null, + fullwidth: "true", + anchorOrigin: { vertical: 'bottom', horizontal: isRTL ? 'right' : 'left' }, + transformOrigin: { vertical: 'top', horizontal: isRTL ? 'right' : 'left' }, + }} /> ); } diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-options/container.jsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-options/container.jsx index 8b719def02..ef90cedbd4 100755 --- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-options/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-options/container.jsx @@ -10,6 +10,7 @@ import logger from '/imports/startup/client/logger'; import { defineMessages, injectIntl } from 'react-intl'; import { notify } from '/imports/ui/services/notification'; import UserOptions from './component'; +import { layoutSelect } from '/imports/ui/components/layout/context'; const propTypes = { users: PropTypes.arrayOf(Object).isRequired, @@ -60,6 +61,8 @@ const UserOptionsContainer = withTracker((props) => { return name; }; + const isRTL = layoutSelect((i) => i.isRTL); + return { toggleMuteAllUsers: () => { UserListService.muteAllUsers(Auth.userID); @@ -92,6 +95,7 @@ const UserOptionsContainer = withTracker((props) => { meetingName: getMeetingName(), openLearningDashboardUrl: LearningDashboardService.openLearningDashboardUrl, dynamicGuestPolicy, + isRTL, }; })(UserOptions); diff --git a/bigbluebutton-html5/imports/ui/components/video-provider/video-list/video-list-item/component.jsx b/bigbluebutton-html5/imports/ui/components/video-provider/video-list/video-list-item/component.jsx index 1a123f04ac..3fdca05e02 100755 --- a/bigbluebutton-html5/imports/ui/components/video-provider/video-list/video-list-item/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/video-provider/video-list/video-list-item/component.jsx @@ -17,7 +17,7 @@ import Styled from './styles'; const VideoListItem = (props) => { const { name, voiceUser, isFullscreenContext, layoutContextDispatch, user, onHandleVideoFocus, - cameraId, numOfStreams, focused, onVideoItemMount, onVideoItemUnmount, + cameraId, numOfStreams, focused, onVideoItemMount, onVideoItemUnmount, isRTL, } = props; const [videoIsReady, setVideoIsReady] = useState(false); @@ -124,6 +124,7 @@ const VideoListItem = (props) => { onHandleVideoFocus={onHandleVideoFocus} focused={focused} onHandleMirror={() => setIsMirrored((value) => !value)} + isRTL={isRTL} /> { const { element } = fullscreen; const isFullscreenContext = (element === cameraId); const layoutContextDispatch = layoutDispatch(); + const isRTL = layoutSelect((i) => i.isRTL); return ( { {...{ isFullscreenContext, layoutContextDispatch, + isRTL, }} /> ); diff --git a/bigbluebutton-html5/imports/ui/components/video-provider/video-list/video-list-item/user-actions/component.jsx b/bigbluebutton-html5/imports/ui/components/video-provider/video-list/video-list-item/user-actions/component.jsx index e96e597bb0..d763cd4361 100644 --- a/bigbluebutton-html5/imports/ui/components/video-provider/video-list/video-list-item/user-actions/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/video-provider/video-list/video-list-item/user-actions/component.jsx @@ -41,7 +41,8 @@ const intlMessages = defineMessages({ const UserActions = (props) => { const { - name, cameraId, numOfStreams, onHandleVideoFocus, user, focused, onHandleMirror, + name, cameraId, numOfStreams, onHandleVideoFocus, + user, focused, onHandleMirror, isRTL, } = props; const intl = useIntl(); @@ -103,8 +104,8 @@ const UserActions = (props) => { elevation: 3, getContentAnchorEl: null, fullwidth: 'true', - anchorOrigin: { vertical: 'bottom', horizontal: 'left' }, - transformorigin: { vertical: 'bottom', horizontal: 'left' }, + anchorOrigin: { vertical: 'bottom', horizontal: isRTL ? 'right' : 'left' }, + transformOrigin: { vertical: 'top', horizontal: isRTL ? 'right' : 'left' }, }} /> )