diff --git a/doc/api.md b/doc/api.md index 4cc8c69e3..372545127 100644 --- a/doc/api.md +++ b/doc/api.md @@ -222,6 +222,11 @@ api.executeCommand('toggleChat'); api.executeCommand('toggleShareScreen'); ``` +* **toggleTileView** - Enter / exit tile view layout mode. No arguments are required. +```javascript +api.executeCommand('toggleTileView'); +``` + * **hangup** - Hangups the call. No arguments are required. ```javascript api.executeCommand('hangup'); @@ -296,6 +301,13 @@ changes. The listener will receive an object with the following structure: } ``` +* **tileViewChanged** - event notifications about tile view layout mode being entered or exited. The listener will receive object with the following structure: +```javascript +{ + enabled: boolean, // whether tile view is not displayed or not +} +``` + * **incomingMessage** - Event notifications about incoming messages. The listener will receive an object with the following structure: ```javascript diff --git a/modules/API/API.js b/modules/API/API.js index b6c25bdc6..fe45efef6 100644 --- a/modules/API/API.js +++ b/modules/API/API.js @@ -8,6 +8,7 @@ import { import { setSubject } from '../../react/features/base/conference'; import { parseJWTFromURLParams } from '../../react/features/base/jwt'; import { invite } from '../../react/features/invite'; +import { toggleTileView } from '../../react/features/video-layout'; import { getJitsiMeetTransport } from '../transport'; import { API_ID } from './constants'; @@ -97,6 +98,11 @@ function initCommands() { sendAnalytics(createApiEvent('screen.sharing.toggled')); toggleScreenSharing(); }, + 'toggle-tile-view': () => { + sendAnalytics(createApiEvent('tile-view.toggled')); + + APP.store.dispatch(toggleTileView()); + }, 'video-hangup': () => { sendAnalytics(createApiEvent('video.hangup')); APP.conference.hangup(true); @@ -622,6 +628,21 @@ class API { }); } + /** + * Notify external application (if API is enabled) that tile view has been + * entered or exited. + * + * @param {string} enabled - True if tile view is currently displayed, false + * otherwise. + * @returns {void} + */ + notifyTileViewChanged(enabled: boolean) { + this._sendEvent({ + name: 'tile-view-changed', + enabled + }); + } + /** * Disposes the allocated resources. * diff --git a/modules/API/external/external_api.js b/modules/API/external/external_api.js index 6b00879da..d7ae31387 100644 --- a/modules/API/external/external_api.js +++ b/modules/API/external/external_api.js @@ -39,6 +39,7 @@ const commands = { toggleChat: 'toggle-chat', toggleFilmStrip: 'toggle-film-strip', toggleShareScreen: 'toggle-share-screen', + toggleTileView: 'toggle-tile-view', toggleVideo: 'toggle-video' }; @@ -67,7 +68,8 @@ const events = { 'video-availability-changed': 'videoAvailabilityChanged', 'video-mute-status-changed': 'videoMuteStatusChanged', 'screen-sharing-status-changed': 'screenSharingStatusChanged', - 'subject-change': 'subjectChange' + 'subject-change': 'subjectChange', + 'tile-view-changed': 'tileViewChanged' }; /** diff --git a/react/features/video-layout/actions.js b/react/features/video-layout/actions.js index 517d5fadb..bf743ad4d 100644 --- a/react/features/video-layout/actions.js +++ b/react/features/video-layout/actions.js @@ -1,5 +1,7 @@ // @flow +import type { Dispatch } from 'redux'; + import { SCREEN_SHARE_PARTICIPANTS_UPDATED, SET_TILE_VIEW @@ -39,3 +41,17 @@ export function setTileView(enabled: boolean) { enabled }; } + +/** + * Creates a (redux) action which signals either to exit tile view if currently + * enabled or enter tile view if currently disabled. + * + * @returns {Function} + */ +export function toggleTileView() { + return (dispatch: Dispatch, getState: Function) => { + const { tileViewEnabled } = getState()['features/video-layout']; + + dispatch(setTileView(!tileViewEnabled)); + }; +} diff --git a/react/features/video-layout/subscriber.js b/react/features/video-layout/subscriber.js index 2075e7958..b9d8230a7 100644 --- a/react/features/video-layout/subscriber.js +++ b/react/features/video-layout/subscriber.js @@ -13,6 +13,7 @@ import { selectParticipant } from '../large-video'; import { shouldDisplayTileView } from './functions'; import { setParticipantsWithScreenShare } from './actions'; +declare var APP: Object; declare var interfaceConfig: Object; /** @@ -35,6 +36,10 @@ StateListenerRegistry.register( _updateAutoPinnedParticipant(store); } } + + if (typeof APP === 'object') { + APP.API.notifyTileViewChanged(displayTileView); + } } );