diff --git a/css/filmstrip/_tile_view.scss b/css/filmstrip/_tile_view.scss index f0f303fc0..a382faa24 100644 --- a/css/filmstrip/_tile_view.scss +++ b/css/filmstrip/_tile_view.scss @@ -121,3 +121,15 @@ align-self: baseline; } } + +.shift-right #filmstripRemoteVideosContainer { + /** + * Max-width corresponding to the ASPECT_RATIO_BREAKPOINT from features/filmstrip/constants, + * from which we subtract the chat size. + */ + @media only screen and (max-width: calc(500px + #{$sidebarWidth})) { + video { + object-fit: cover; + } + } +} diff --git a/package.json b/package.json index 439050dd0..5f14c297d 100644 --- a/package.json +++ b/package.json @@ -48,10 +48,10 @@ "i18next": "17.0.6", "i18next-browser-languagedetector": "3.0.1", "i18next-xhr-backend": "3.0.0", - "jQuery-Impromptu": "github:trentrichardson/jQuery-Impromptu#v6.0.0", "jitsi-meet-logger": "github:jitsi/jitsi-meet-logger#v1.0.0", "jquery": "3.5.1", "jquery-i18next": "1.2.1", + "jQuery-Impromptu": "github:trentrichardson/jQuery-Impromptu#v6.0.0", "js-md5": "0.6.1", "jwt-decode": "2.2.0", "lib-jitsi-meet": "github:jitsi/lib-jitsi-meet#4191198233ae64e3cb12349069c582724d09537c", diff --git a/react/features/base/responsive-ui/actions.js b/react/features/base/responsive-ui/actions.js index aeb2767ba..882a1749e 100644 --- a/react/features/base/responsive-ui/actions.js +++ b/react/features/base/responsive-ui/actions.js @@ -2,6 +2,8 @@ import type { Dispatch } from 'redux'; +import { CHAT_SIZE } from '../../chat/constants'; + import { CLIENT_RESIZED, SET_ASPECT_RATIO, SET_REDUCED_UI } from './actionTypes'; import { ASPECT_RATIO_NARROW, ASPECT_RATIO_WIDE } from './constants'; @@ -24,10 +26,20 @@ const REDUCED_UI_THRESHOLD = 300; * @returns {Object} */ export function clientResized(clientWidth: number, clientHeight: number) { - return { - type: CLIENT_RESIZED, - clientHeight, - clientWidth + return (dispatch: Dispatch, getState: Function) => { + const state = getState(); + const { isOpen } = state['features/chat']; + let availableWidth = clientWidth; + + if (isOpen && navigator.product !== 'ReactNative') { + availableWidth -= CHAT_SIZE; + } + + return dispatch({ + type: CLIENT_RESIZED, + clientHeight, + clientWidth: availableWidth + }); }; } diff --git a/react/features/filmstrip/actions.web.js b/react/features/filmstrip/actions.web.js index 79c774884..c9e21e93c 100644 --- a/react/features/filmstrip/actions.web.js +++ b/react/features/filmstrip/actions.web.js @@ -2,7 +2,6 @@ import { pinParticipant } from '../base/participants'; import { toState } from '../base/redux'; -import { CHAT_SIZE } from '../chat/constants'; import { SET_HORIZONTAL_VIEW_DIMENSIONS, SET_TILE_VIEW_DIMENSIONS } from './actionTypes'; import { calculateThumbnailSizeForHorizontalView, calculateThumbnailSizeForTileView } from './functions'; @@ -27,19 +26,12 @@ const TILE_VIEW_SIDE_MARGINS = 20; export function setTileViewDimensions(dimensions: Object, windowSize: Object, stateful: Object | Function) { const state = toState(stateful); const { clientWidth, clientHeight } = windowSize; - const heightToUse = clientHeight; - let widthToUse = clientWidth; - const { isOpen } = state['features/chat']; const { disableResponsiveTiles } = state['features/base/config']; - if (isOpen) { - widthToUse -= CHAT_SIZE; - } - const thumbnailSize = calculateThumbnailSizeForTileView({ ...dimensions, - clientWidth: widthToUse, - clientHeight: heightToUse, + clientWidth, + clientHeight, disableResponsiveTiles }); const filmstripWidth = dimensions.columns * (TILE_VIEW_SIDE_MARGINS + thumbnailSize.width); diff --git a/react/features/filmstrip/subscriber.web.js b/react/features/filmstrip/subscriber.web.js index fbf1cd09b..dc306d417 100644 --- a/react/features/filmstrip/subscriber.web.js +++ b/react/features/filmstrip/subscriber.web.js @@ -1,6 +1,7 @@ // @flow import { StateListenerRegistry, equals } from '../base/redux'; +import { clientResized } from '../base/responsive-ui'; import { setFilmstripVisible } from '../filmstrip/actions'; import { setOverflowDrawer } from '../toolbox/actions.web'; import { getCurrentLayout, getTileViewGridDimensions, shouldDisplayTileView, LAYOUTS } from '../video-layout'; @@ -73,12 +74,12 @@ StateListenerRegistry.register( }); /** - * Listens for changes in the chat state to calculate the dimensions of the tile view grid and the tiles. + * Listens for changes in the chat state to recompute available width. */ StateListenerRegistry.register( /* selector */ state => state['features/chat'].isOpen, /* listener */ (isChatOpen, store) => { - const state = store.getState(); + const { innerWidth, innerHeight } = window; if (isChatOpen) { // $FlowFixMe @@ -88,21 +89,7 @@ StateListenerRegistry.register( document.body.classList.remove('shift-right'); } - if (shouldDisplayTileView(state)) { - const gridDimensions = getTileViewGridDimensions(state); - const { clientHeight, clientWidth } = state['features/base/responsive-ui']; - - store.dispatch( - setTileViewDimensions( - gridDimensions, - { - clientHeight, - clientWidth - }, - store - ) - ); - } + store.dispatch(clientResized(innerWidth, innerHeight)); }); /** diff --git a/react/features/toolbox/components/web/Toolbox.js b/react/features/toolbox/components/web/Toolbox.js index 8d1080dcf..cf3b852b3 100644 --- a/react/features/toolbox/components/web/Toolbox.js +++ b/react/features/toolbox/components/web/Toolbox.js @@ -35,7 +35,7 @@ import { connect } from '../../../base/redux'; import { OverflowMenuItem } from '../../../base/toolbox/components'; import { getLocalVideoTrack, toggleScreensharing } from '../../../base/tracks'; import { isVpaasMeeting } from '../../../billing-counter/functions'; -import { CHAT_SIZE, ChatCounter, toggleChat } from '../../../chat'; +import { ChatCounter, toggleChat } from '../../../chat'; import { InviteMore } from '../../../conference'; import { EmbedMeetingDialog } from '../../../embed-meeting'; import { SharedDocumentButton } from '../../../etherpad'; @@ -100,6 +100,11 @@ type Props = { */ _chatOpen: boolean, + /** + * The width of the client. + */ + _clientWidth: number, + /** * The {@code JitsiConference} for the current conference. */ @@ -208,17 +213,6 @@ type Props = { t: Function }; -/** - * The type of the React {@code Component} state of {@link Toolbox}. - */ -type State = { - - /** - * The width of the browser's window. - */ - windowWidth: number -}; - declare var APP: Object; /** @@ -226,7 +220,7 @@ declare var APP: Object; * * @extends Component */ -class Toolbox extends Component { +class Toolbox extends Component { /** * Initializes a new {@code Toolbox} instance. * @@ -239,7 +233,6 @@ class Toolbox extends Component { // Bind event handlers so they are only bound once per instance. this._onMouseOut = this._onMouseOut.bind(this); this._onMouseOver = this._onMouseOver.bind(this); - this._onResize = this._onResize.bind(this); this._onSetOverflowVisible = this._onSetOverflowVisible.bind(this); this._onTabIn = this._onTabIn.bind(this); @@ -261,10 +254,6 @@ class Toolbox extends Component { this._onToolbarToggleScreenshare = this._onToolbarToggleScreenshare.bind(this); this._onToolbarOpenLocalRecordingInfoDialog = this._onToolbarOpenLocalRecordingInfoDialog.bind(this); this._onShortcutToggleTileView = this._onShortcutToggleTileView.bind(this); - - this.state = { - windowWidth: window.innerWidth - }; } /** @@ -316,8 +305,6 @@ class Toolbox extends Component { shortcut.helpDescription); } }); - - window.addEventListener('resize', this._onResize); } /** @@ -337,10 +324,6 @@ class Toolbox extends Component { this._onSetOverflowVisible(false); this.props.dispatch(setToolbarHovered(false)); } - - if (this.props._chatOpen !== prevProps._chatOpen) { - this._onResize(); - } } /** @@ -352,8 +335,6 @@ class Toolbox extends Component { componentWillUnmount() { [ 'A', 'C', 'D', 'R', 'S' ].forEach(letter => APP.keyboardshortcut.unregisterShortcut(letter)); - - window.removeEventListener('resize', this._onResize); } /** @@ -558,28 +539,6 @@ class Toolbox extends Component { this.props.dispatch(setToolbarHovered(true)); } - _onResize: () => void; - - /** - * A window resize handler used to calculate the number of buttons we can - * fit in the toolbar. - * - * @private - * @returns {void} - */ - _onResize() { - let widthToUse = window.innerWidth; - - // Take chat size into account when resizing toolbox. - if (this.props._chatOpen) { - widthToUse -= CHAT_SIZE; - } - - if (this.state.windowWidth !== widthToUse) { - this.setState({ windowWidth: widthToUse }); - } - } - _onSetOverflowVisible: (boolean) => void; @@ -1251,12 +1210,13 @@ class Toolbox extends Component { */ _renderToolboxContent() { const { + _clientWidth, _isMobile, _overflowMenuVisible, t } = this.props; - const buttonSet = getToolbarAdditionalButtons(this.state.windowWidth, _isMobile); + const buttonSet = getToolbarAdditionalButtons(_clientWidth, _isMobile); const toolbarAccLabel = 'toolbar.accessibilityLabel.moreActionsMenu'; const showOverflowMenuButton = buttonSet.has('overflow'); const containerClassName = `toolbox-content${_isMobile ? ' toolbox-content-mobile' : ''}`; @@ -1331,6 +1291,7 @@ function _mapStateToProps(state) { const localParticipant = getLocalParticipant(state); const localRecordingStates = state['features/local-recording']; const localVideo = getLocalVideoTrack(state['features/base/tracks']); + const { clientWidth } = state['features/base/responsive-ui']; let desktopSharingDisabledTooltipKey; @@ -1345,6 +1306,7 @@ function _mapStateToProps(state) { return { _chatOpen: state['features/chat'].isOpen, + _clientWidth: clientWidth, _conference: conference, _desktopSharingEnabled: desktopSharingEnabled, _desktopSharingDisabledTooltipKey: desktopSharingDisabledTooltipKey, diff --git a/react/features/video-layout/functions.js b/react/features/video-layout/functions.js index b17065eaa..ea8c6bf9d 100644 --- a/react/features/video-layout/functions.js +++ b/react/features/video-layout/functions.js @@ -2,7 +2,6 @@ import { getFeatureFlag, TILE_VIEW_ENABLED } from '../base/flags'; import { getPinnedParticipant, getParticipantCount } from '../base/participants'; -import { CHAT_SIZE } from '../chat/constants'; import { ASPECT_RATIO_BREAKPOINT, DEFAULT_MAX_COLUMNS, @@ -46,26 +45,20 @@ export function getMaxColumnCount(state: Object) { if (!disableResponsiveTiles) { const { clientWidth } = state['features/base/responsive-ui']; - let availableWidth = clientWidth; const participantCount = getParticipantCount(state); - const { isOpen } = state['features/chat']; - - if (isOpen) { - availableWidth -= CHAT_SIZE; - } // If there are just two participants in a conference, enforce single-column view for mobile size. - if (participantCount === 2 && availableWidth < ASPECT_RATIO_BREAKPOINT) { + if (participantCount === 2 && clientWidth < ASPECT_RATIO_BREAKPOINT) { return Math.min(1, Math.max(configuredMax, 1)); } // Enforce single column view at very small screen widths. - if (availableWidth < SINGLE_COLUMN_BREAKPOINT) { + if (clientWidth < SINGLE_COLUMN_BREAKPOINT) { return Math.min(1, Math.max(configuredMax, 1)); } // Enforce two column view below breakpoint. - if (availableWidth < TWO_COLUMN_BREAKPOINT) { + if (clientWidth < TWO_COLUMN_BREAKPOINT) { return Math.min(2, Math.max(configuredMax, 1)); } }