@@ -4,108 +4,31 @@ import {gql} from '@apollo/client/core';
44import { BBBGraphQl } from './BBBGraphQl' ;
55import type { DisplayManager } from './displayManager' ;
66import type { Layout } from '../../common/config' ;
7- /*
8- export async function createBBBMeeting(control: string, screens: Array<string>, displayManager: DisplayManager, leftCallback: () => void) {
7+ import { v7 as uuid } from 'uuid' ;
98
10- const bbbGraphQl = new BBBGraphql(control);
11- const connected = await bbbGraphQl.connect();
12- if(!connected)
13- return false;
14-
15- console.log('connected to graphql');
16-
17- const joinUrl1 = await bbbGraphQl.getJoinURL({
18- 'sessionName': 'left',
19- 'enforceLayout': 'CAMERAS_ONLY',
20- 'userdata-bbb_hide_actions_bar': false,
21- 'userdata-bbb_display_notifications': false,
22- 'userdata-bbb_auto_share_webcam': true,
23- 'userdata-bbb_listen_only_mode': false,
24- 'userdata-bbb_skip_check_audio': true,
25- 'userdata-bbb_skip_video_preview': true,
26- 'userdata-bbb_preferred_camera_profile': 'high',
27- 'userdata-bbb_hide_nav_bar': true,
28- 'userdata-bbb_auto_join_audio': true,
29- 'userdata-bbb_show_session_details_on_join': false,
30- });
31-
32- console.log('joinUrl1', joinUrl1.status);
33- console.log('joinUrl1', joinUrl1.statusText);
34- console.log('joinUrl1', JSON.stringify(joinUrl1.data));
35- console.log('joinUrl1', JSON.stringify(joinUrl1.headers));
36- console.log('joinUrl1', JSON.stringify(joinUrl1.config));
37-
38- const joinUrl2 = await bbbGraphQl.getJoinURL({
39- 'sessionName': 'right',
40- 'enforceLayout': 'PRESENTATION_ONLY',
41- 'userdata-bbb_hide_actions_bar': false,
42- 'userdata-bbb_display_notifications': false,
43- 'userdata-bbb_auto_share_webcam': true,
44- 'userdata-bbb_listen_only_mode': false,
45- 'userdata-bbb_skip_check_audio': true,
46- 'userdata-bbb_skip_video_preview': true,
47- 'userdata-bbb_preferred_camera_profile': 'high',
48- 'userdata-bbb_hide_nav_bar': true,
49- 'userdata-bbb_auto_join_audio': true,
50- 'userdata-bbb_show_session_details_on_join': false,
51- });
52-
53- console.log('joinUrl2', joinUrl2.status);
54- console.log('joinUrl2', joinUrl2.statusText);
55- console.log('joinUrl2', JSON.stringify(joinUrl2.data));
56- console.log('joinUrl2', JSON.stringify(joinUrl2.headers));
57- console.log('joinUrl2', JSON.stringify(joinUrl2.config));
58-
59- return new BBBMeeting(screens, displayManager, leftCallback, bbbGraphQl);
60- }
61- */
62- export async function createBBBMeeting ( control : string , layout : Layout , displayManager : DisplayManager , leftCallback : ( ) => void ) {
9+ export async function createBBBMeeting ( control : string , displayManager : DisplayManager , leftCallback : ( ) => void ) {
6310
6411 const bbbGraphQl = new BBBGraphQl ( control ) ;
6512 const connected = await bbbGraphQl . connect ( leftCallback ) ;
66- if ( ! connected )
67- return false ;
13+ if ( ! connected ) return false ;
6814
6915 console . log ( 'connected to graphql' ) ;
7016
71- console . log ( 'layout' , layout . label ) ;
72-
73- const screens : { [ key : string ] : string } = { } ;
74- for ( const [ key , value ] of Object . entries ( layout . screens ) ) {
75- console . log ( key , value ) ;
76-
77- const joinUrl = await bbbGraphQl . getJoinURL ( {
78- sessionName : key ,
79- duplicateSession : false ,
80- ...value . bbb_join_parameters ,
81- } ) ;
82-
83- console . log ( 'status' , joinUrl . status ) ;
84- console . log ( 'statusText' , joinUrl . statusText ) ;
85- console . log ( 'data' , JSON . stringify ( joinUrl . data ) ) ;
86- console . log ( 'headers' , JSON . stringify ( joinUrl . headers ) ) ;
87- console . log ( 'config' , JSON . stringify ( joinUrl . config ) ) ;
88-
89- screens [ key ] = joinUrl . data . response . url ;
90- }
91-
92- return new BBBMeeting ( screens , displayManager , leftCallback , bbbGraphQl ) ;
17+ return new BBBMeeting ( displayManager , leftCallback , bbbGraphQl ) ;
9318}
9419
95-
9620class BBBMeeting {
97- private readonly screens : { [ key : string ] : string } ;
21+ private screens ! : { [ key : string ] : string } ;
9822 private displayManager : DisplayManager ;
9923
100- private windows : BrowserWindow [ ] ;
101- private apolloClient : ApolloClient < NormalizedCacheObject > ;
24+ private windows : { [ key : string ] : BrowserWindow } ;
25+ private apolloClient : ApolloClient < NormalizedCacheObject > | undefined ;
10226 private bbbGraphQl : BBBGraphQl ;
103- private mediaScreen : { url : string , window : BrowserWindow } ;
27+ private mediaScreen : { url : string ; window : BrowserWindow } | undefined ;
10428
105- constructor ( screens : { [ key : string ] : string } , displayManager : DisplayManager , leftCallback : ( ) => void , bbbGraphQl : BBBGraphQl ) {
106- this . screens = screens ;
29+ constructor ( displayManager : DisplayManager , leftCallback : ( ) => void , bbbGraphQl : BBBGraphQl ) {
10730 this . displayManager = displayManager ;
108- this . windows = [ ] ;
31+ this . windows = { } ;
10932 this . bbbGraphQl = bbbGraphQl ;
11033
11134 this . apolloClient = this . bbbGraphQl . getApolloClient ( ) ;
@@ -118,7 +41,6 @@ class BBBMeeting {
11841 }
11942
12043 private onUsersLeft ( callback : ( ) => void ) {
121-
12244 const getMeetingEndData = gql `
12345 subscription getUserCurrent {
12446 user_current {
@@ -133,7 +55,12 @@ class BBBMeeting {
13355 }
13456 }
13557 }
136- ` ;
58+ ` ;
59+
60+ if ( this . apolloClient == undefined ) {
61+ console . error ( 'Error: apolloClient is undefined' ) ;
62+ return ;
63+ }
13764
13865 this . apolloClient
13966 . subscribe ( {
@@ -142,7 +69,7 @@ class BBBMeeting {
14269 . subscribe ( {
14370 next ( data ) {
14471 console . log ( 'getMeetingEndData' , JSON . stringify ( data ) ) ;
145- if ( data . data . user_current [ 0 ] . meeting . ended === true ) {
72+ if ( data . data . user_current [ 0 ] . meeting . ended === true ) {
14673 console . log ( 'Meeting ended' ) ;
14774 callback ( ) ;
14875 }
@@ -152,7 +79,6 @@ class BBBMeeting {
15279 } ,
15380 } ) ;
15481
155-
15682 const USER_SESSIONS = gql `
15783 subscription {
15884 user_session(where: {connectionsAlive: {_gt: "0"}}) {
@@ -187,7 +113,35 @@ class BBBMeeting {
187113 } ) ;
188114 }
189115
190- public openScreens ( ) {
116+ public async openScreens ( layout : Layout ) {
117+
118+ console . log ( 'Switching Layout to: ' , layout . label ) ;
119+
120+ // if (this.windows.length > 0) {
121+ // console.log('Windows already exist. Amount of Current windows: ' + this.windows.length);
122+ // for (var window of this.windows) {
123+ // console.log('Closing window: ' + window.id);
124+ // window.close();
125+ // window.destroy();
126+ // }
127+ // }
128+
129+ this . mediaScreen = undefined ;
130+ this . screens = { } ;
131+
132+ for ( const [ key , value ] of Object . entries ( layout . screens ) ) {
133+ console . log ( "\nProcessing screen: " + key ) ;
134+ console . log ( "With value: " + value + "\n" ) ;
135+ const joinUrl = await this . bbbGraphQl . getJoinURL ( {
136+ sessionName : key ,
137+ duplicateSession : false ,
138+ ...value . bbb_join_parameters ,
139+ } ) ;
140+ this . screens [ key ] = joinUrl . data . response . url ;
141+ }
142+
143+ let newWindows : { [ key : string ] : BrowserWindow } = { } ;
144+
191145 for ( const [ screen , url ] of Object . entries ( this . screens ) ) {
192146 const screenDisplay = this . displayManager . getDisplay ( screen ) ;
193147
@@ -196,40 +150,74 @@ class BBBMeeting {
196150 continue ;
197151 }
198152
199- console . log ( 'screenDisplay' , screenDisplay ) ;
200-
201- const partition = 'persist:windows-' + this . windows . length ;
153+ console . log ( 'Processing screen ' + screen ) ;
154+
155+ const partition = 'persist:windows-' + uuid ( ) ;
156+
157+ // Get old window if exists
158+ let screenWindow = this . windows [ screenDisplay . label ] ;
159+ delete this . windows [ screenDisplay . label ] ;
160+
161+ if ( screenWindow == undefined ) {
162+ console . log ( 'Creating new window' ) ;
163+ screenWindow = new BrowserWindow ( {
164+ show : true ,
165+ width : screenDisplay . size . width ,
166+ height : screenDisplay . size . height ,
167+ x : screenDisplay . bounds . x ,
168+ y : screenDisplay . bounds . y ,
169+ fullscreen : true ,
170+ webPreferences : {
171+ partition : partition ,
172+ contextIsolation : true ,
173+ } ,
174+ autoHideMenuBar : true ,
175+ } ) ;
176+ } else {
177+ console . log ( 'Using existing window' ) ;
178+ }
202179
203- const screenWindow = new BrowserWindow ( {
204- show : true ,
205- width : screenDisplay . size . width ,
206- height : screenDisplay . size . height ,
207- x : screenDisplay . bounds . x ,
208- y : screenDisplay . bounds . y ,
209- fullscreen : true ,
210- webPreferences : {
211- partition : partition ,
212- contextIsolation : true ,
213- } ,
180+ // When leaving the BBB meeting (by visiting another website), BBB will show a confirmation dialog (are you sure blabla)
181+ // This dialog will prevent the loading of a new URL, so we handle this problem here in this event listener
182+ screenWindow . webContents . on ( 'will-prevent-unload' , ( event ) => {
183+ console . log ( "Prevented unload detected, forcing unload..." ) ;
184+ event . preventDefault ( ) ; // This stops the confirmation dialog
185+ if ( screenWindow ) {
186+ console . log ( screenDisplay . label + ": Loading URL again: " + url ) ;
187+ screenWindow . loadURL ( url ) ;
188+ }
214189 } ) ;
215- //screenWindow.webContents.openDevTools();
190+ console . log ( '\n' + screenDisplay . label + ': Loading URL: ' + url ) ;
191+ await screenWindow . loadURL ( url ) ;
192+ console . log ( screenDisplay . label + ': Loading of URL finished.\n' ) ;
216193
217- this . windows . push ( screenWindow ) ;
194+ newWindows [ screenDisplay . label ] = screenWindow ;
218195
219- screenWindow . loadURL ( url ) ;
220-
221- if ( url . includes ( 'userdata-bbb_auto_join_audio=true' ) ) {
196+ if ( url . includes ( 'userdata-bbb_auto_join_audio=true' ) ) {
222197 this . mediaScreen = { url : url , window : screenWindow } ;
223198 }
224199 }
200+
201+ // Close all unused windows
202+ Object . values ( this . windows ) . forEach ( window => {
203+ console . log ( 'closing window ' + window . id ) ;
204+ window . close ( ) ;
205+ window . destroy ( ) ;
206+ } ) ;
207+
208+ this . windows = newWindows ;
225209 }
226210
227211 public mute ( ) {
228- this . executeJavaScriptInMediaScreen ( 'document.querySelectorAll(\'button[data-test="muteMicButton"]\')[0].click()' ) . then ( r => console . log ( r ) ) ;
212+ this . executeJavaScriptInMediaScreen (
213+ 'document.querySelectorAll(\'button[data-test="muteMicButton"]\')[0].click()' ,
214+ ) . then ( r => console . log ( r ) ) ;
229215 }
230216
231217 public unmute ( ) {
232- this . executeJavaScriptInMediaScreen ( 'document.querySelectorAll(\'button[data-test="unmuteMicButton"]\')[0].click()' ) . then ( r => console . log ( r ) ) ;
218+ this . executeJavaScriptInMediaScreen (
219+ 'document.querySelectorAll(\'button[data-test="unmuteMicButton"]\')[0].click()' ,
220+ ) . then ( r => console . log ( r ) ) ;
233221 }
234222
235223 public async getMediaDevices ( ) {
@@ -253,13 +241,13 @@ class BBBMeeting {
253241 }
254242
255243 private async executeJavaScriptInMediaScreen ( command : string ) {
256- if ( this . mediaScreen . window ) {
244+ if ( this . mediaScreen ) {
257245 return await this . mediaScreen . window . webContents . executeJavaScript ( command ) ;
258246 }
259247 }
260248
261249 private closeScreens ( ) {
262- this . windows . forEach ( window => {
250+ Object . values ( this . windows ) . forEach ( window => {
263251 window . close ( ) ;
264252 window . destroy ( ) ;
265253 } ) ;
0 commit comments