Sfoglia il codice sorgente

feat: add toggleWhiteboard to Jitsi API (#13292)

* add toggleWhiteboard to Jitsi API

* eslint recommendations applied

* Prevent to send whiteboard status change notifications for mobile

* Fix code style errors (eslint)

* Requested changes (by mihhu) have been made.

---------

Co-authored-by: Fikret Huseynkhanov <fikret.huseynkhanov@simbrella.com>
factor2
FIKRAT HUSEYNKHANOV 2 anni fa
parent
commit
aaeb1a90e5
Nessun account collegato all'indirizzo email del committer

+ 19
- 0
modules/API/API.js Vedi File

@@ -113,6 +113,8 @@ import { isAudioMuteButtonDisabled } from '../../react/features/toolbox/function
113 113
 import { setTileView, toggleTileView } from '../../react/features/video-layout/actions.any';
114 114
 import { muteAllParticipants } from '../../react/features/video-menu/actions';
115 115
 import { setVideoQuality } from '../../react/features/video-quality/actions';
116
+import { toggleWhiteboard } from '../../react/features/whiteboard/actions.any';
117
+import { WhiteboardStatus } from '../../react/features/whiteboard/types';
116 118
 import { getJitsiMeetTransport } from '../transport';
117 119
 
118 120
 import {
@@ -833,6 +835,9 @@ function initCommands() {
833 835
             } else {
834 836
                 logger.error(' End Conference not supported');
835 837
             }
838
+        },
839
+        'toggle-whiteboard': () => {
840
+            APP.store.dispatch(toggleWhiteboard());
836 841
         }
837 842
     };
838 843
     transport.on('event', ({ data, name }) => {
@@ -2014,6 +2019,20 @@ class API {
2014 2019
         });
2015 2020
     }
2016 2021
 
2022
+    /**
2023
+     * Notify external application (if API is enabled) if whiteboard state is
2024
+     * changed.
2025
+     *
2026
+     * @param {WhiteboardStatus} status - The new whiteboard status.
2027
+     * @returns {void}
2028
+     */
2029
+    notifyWhiteboardStatusChanged(status: WhiteboardStatus) {
2030
+        this._sendEvent({
2031
+            name: 'whiteboard-status-changed',
2032
+            status
2033
+        });
2034
+    }
2035
+
2017 2036
     /**
2018 2037
      * Disposes the allocated resources.
2019 2038
      *

+ 4
- 2
modules/API/external/external_api.js Vedi File

@@ -90,7 +90,8 @@ const commands = {
90 90
     toggleSubtitles: 'toggle-subtitles',
91 91
     toggleTileView: 'toggle-tile-view',
92 92
     toggleVirtualBackgroundDialog: 'toggle-virtual-background',
93
-    toggleVideo: 'toggle-video'
93
+    toggleVideo: 'toggle-video',
94
+    toggleWhiteboard: 'toggle-whiteboard'
94 95
 };
95 96
 
96 97
 /**
@@ -154,7 +155,8 @@ const events = {
154 155
     'subject-change': 'subjectChange',
155 156
     'suspend-detected': 'suspendDetected',
156 157
     'tile-view-changed': 'tileViewChanged',
157
-    'toolbar-button-clicked': 'toolbarButtonClicked'
158
+    'toolbar-button-clicked': 'toolbarButtonClicked',
159
+    'whiteboard-status-changed': 'whiteboardStatusChanged'
158 160
 };
159 161
 
160 162
 /**

+ 31
- 0
react/features/whiteboard/actions.any.ts Vedi File

@@ -0,0 +1,31 @@
1
+import { IStore } from '../app/types';
2
+
3
+import { setWhiteboardOpen } from './actions';
4
+import { isWhiteboardAllowed, isWhiteboardOpen, isWhiteboardVisible } from './functions';
5
+import { WhiteboardStatus } from './types';
6
+
7
+
8
+/**
9
+ * API to toggle the whiteboard.
10
+ *
11
+ * @returns {Function}
12
+ */
13
+export function toggleWhiteboard() {
14
+    return async (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
15
+        const state = getState();
16
+        const isAllowed = isWhiteboardAllowed(state);
17
+        const isOpen = isWhiteboardOpen(state);
18
+
19
+        if (isAllowed) {
20
+            if (isOpen && !isWhiteboardVisible(state)) {
21
+                dispatch(setWhiteboardOpen(true));
22
+            } else if (isOpen && isWhiteboardVisible(state)) {
23
+                dispatch(setWhiteboardOpen(false));
24
+            } else if (!isOpen) {
25
+                dispatch(setWhiteboardOpen(true));
26
+            }
27
+        } else if (typeof APP !== 'undefined') {
28
+            APP.API.notifyWhiteboardStatusChanged(WhiteboardStatus.FORBIDDEN);
29
+        }
30
+    };
31
+}

+ 9
- 0
react/features/whiteboard/functions.ts Vedi File

@@ -89,3 +89,12 @@ export const getCollabServerUrl = (state: IReduxState): string | undefined => {
89 89
 export const isWhiteboardVisible = (state: IReduxState): boolean =>
90 90
     getPinnedParticipant(state)?.id === WHITEBOARD_ID
91 91
     || state['features/large-video'].participantId === WHITEBOARD_ID;
92
+
93
+/**
94
+* Indicates whether the whiteboard is accessible to a participant that has a moderator role.
95
+*
96
+* @param {IReduxState} state - The state from the Redux store.
97
+* @returns {boolean}
98
+*/
99
+export const isWhiteboardAllowed = (state: IReduxState): boolean =>
100
+    isWhiteboardEnabled(state) && isLocalParticipantModerator(state);

+ 20
- 1
react/features/whiteboard/middleware.ts Vedi File

@@ -9,12 +9,13 @@ import MiddlewareRegistry from '../base/redux/MiddlewareRegistry';
9 9
 import StateListenerRegistry from '../base/redux/StateListenerRegistry';
10 10
 import { getCurrentRoomId } from '../breakout-rooms/functions';
11 11
 import { addStageParticipant } from '../filmstrip/actions.web';
12
-import { isStageFilmstripAvailable } from '../filmstrip/functions';
12
+import { isStageFilmstripAvailable } from '../filmstrip/functions.web';
13 13
 
14 14
 import { RESET_WHITEBOARD, SET_WHITEBOARD_OPEN } from './actionTypes';
15 15
 import { resetWhiteboard, setWhiteboardOpen, setupWhiteboard } from './actions';
16 16
 import { WHITEBOARD_ID, WHITEBOARD_PARTICIPANT_NAME } from './constants';
17 17
 import { getCollabDetails, getCollabServerUrl, isWhiteboardPresent } from './functions';
18
+import { WhiteboardStatus } from './types';
18 19
 
19 20
 const focusWhiteboard = (store: IStore) => {
20 21
     const { dispatch, getState } = store;
@@ -68,21 +69,27 @@ MiddlewareRegistry.register((store: IStore) => (next: Function) => async (action
68 69
                 collabServerUrl,
69 70
                 collabDetails
70 71
             });
72
+            raiseWhiteboardNotification(WhiteboardStatus.INSTANTIATED);
71 73
 
72 74
             return;
73 75
         }
74 76
 
75 77
         if (action.isOpen) {
76 78
             focusWhiteboard(store);
79
+            raiseWhiteboardNotification(WhiteboardStatus.SHOWN);
77 80
 
78 81
             return;
79 82
         }
80 83
 
81 84
         dispatch(participantLeft(WHITEBOARD_ID, conference, { fakeParticipant: FakeParticipant.Whiteboard }));
85
+        raiseWhiteboardNotification(WhiteboardStatus.HIDDEN);
86
+
82 87
         break;
83 88
     }
84 89
     case RESET_WHITEBOARD: {
85 90
         dispatch(participantLeft(WHITEBOARD_ID, conference, { fakeParticipant: FakeParticipant.Whiteboard }));
91
+        raiseWhiteboardNotification(WhiteboardStatus.RESET);
92
+
86 93
         break;
87 94
     }
88 95
     }
@@ -90,6 +97,18 @@ MiddlewareRegistry.register((store: IStore) => (next: Function) => async (action
90 97
     return next(action);
91 98
 });
92 99
 
100
+/**
101
+ * Raises the whiteboard status notifications changes (if API is enabled).
102
+ *
103
+ * @param {WhiteboardStatus} status - The whiteboard changed status.
104
+ * @returns {Function}
105
+ */
106
+function raiseWhiteboardNotification(status: WhiteboardStatus) {
107
+    if (typeof APP !== 'undefined') {
108
+        APP.API.notifyWhiteboardStatusChanged(status);
109
+    }
110
+}
111
+
93 112
 /**
94 113
  * Set up state change listener to perform maintenance tasks when the conference
95 114
  * is left or failed, e.g. Disable the whiteboard if it's left open.

+ 13
- 0
react/features/whiteboard/types.ts Vedi File

@@ -0,0 +1,13 @@
1
+
2
+/**
3
+ * Whiteboard statuses used to raise the notification when it's changed.
4
+ *
5
+ * @enum
6
+ */
7
+export enum WhiteboardStatus {
8
+    FORBIDDEN = 'FORBIDDEN',
9
+    HIDDEN = 'HIDDEN',
10
+    INSTANTIATED = 'INSTANTIATED',
11
+    RESET = 'RESET',
12
+    SHOWN = 'SHOWN'
13
+}

Loading…
Annulla
Salva