1
1
const path = require ( "path" ) ;
2
2
const hardware = require ( "./hardware" ) ;
3
3
const integration = require ( "./integration" ) ;
4
- const { app, screen, nativeTheme, BaseWindow, WebContentsView } = require ( "electron" ) ;
4
+ const { app, screen, nativeTheme, ipcMain , BaseWindow, WebContentsView } = require ( "electron" ) ;
5
5
6
6
global . WEBVIEW = global . WEBVIEW || {
7
7
initialized : false ,
@@ -24,28 +24,58 @@ const init = async (args) => {
24
24
console . error ( "Please provide the '--web-url' parameter" ) ;
25
25
return app . quit ( ) ;
26
26
}
27
+ if ( ! / ^ h t t p s ? : \/ \/ / . test ( args . web_url ) ) {
28
+ console . error ( "Please provide the '--web-url' parameter with http(s)" ) ;
29
+ return app . quit ( ) ;
30
+ }
27
31
const url = new URL ( args . web_url ) ;
28
- const theme = args . web_theme ? args . web_theme : "dark" ;
29
- const zoom = args . web_zoom ? parseFloat ( args . web_zoom ) : 1.25 ;
32
+ const theme = [ "light" , "dark" ] . includes ( args . web_theme ) ? args . web_theme : "dark" ;
33
+ const zoom = ! isNaN ( parseFloat ( args . web_zoom ) ) ? parseFloat ( args . web_zoom ) : 1.25 ;
34
+ const widget = args . web_widget ? args . web_widget === "true" : true ;
35
+
36
+ // Init global layout
37
+ WEBVIEW . viewZoom = zoom ;
38
+ WEBVIEW . viewTheme = theme ;
39
+ WEBVIEW . widgetTheme = theme ;
40
+ WEBVIEW . widgetEnabled = widget ;
41
+ nativeTheme . themeSource = WEBVIEW . viewTheme ;
30
42
31
43
// Init global root window
32
- nativeTheme . themeSource = theme ;
33
44
WEBVIEW . window = new BaseWindow ( {
34
45
title : `TouchKio - ${ url . host } ` ,
35
46
icon : path . join ( __dirname , ".." , "img" , "icon.png" ) ,
36
47
} ) ;
37
48
WEBVIEW . window . setMenuBarVisibility ( false ) ;
38
49
WEBVIEW . window . setFullScreen ( true ) ;
39
50
40
- // Init global main webview
41
- WEBVIEW . view = new WebContentsView ( ) ;
51
+ // Init global webview
52
+ WEBVIEW . view = new WebContentsView ( {
53
+ webPreferences : {
54
+ nodeIntegration : false ,
55
+ contextIsolation : true ,
56
+ } ,
57
+ } ) ;
42
58
WEBVIEW . window . contentView . addChildView ( WEBVIEW . view ) ;
43
59
WEBVIEW . view . webContents . loadURL ( url . toString ( ) ) ;
60
+ WEBVIEW . view . setBackgroundColor ( "#FFFFFFFF" ) ;
61
+
62
+ // Init global widget
63
+ WEBVIEW . widget = new WebContentsView ( {
64
+ transparent : true ,
65
+ webPreferences : {
66
+ nodeIntegration : true ,
67
+ contextIsolation : false ,
68
+ } ,
69
+ } ) ;
70
+ WEBVIEW . window . contentView . addChildView ( WEBVIEW . widget ) ;
71
+ WEBVIEW . widget . webContents . loadFile ( path . join ( __dirname , "widget.html" ) ) ;
72
+ WEBVIEW . widget . setBackgroundColor ( "#00000000" ) ;
44
73
45
74
// Register events
46
- windowEvents ( WEBVIEW . window , zoom ) ;
47
- touchEvents ( WEBVIEW . window ) ;
48
- viewEvents ( WEBVIEW . view ) ;
75
+ windowEvents ( ) ;
76
+ widgetEvents ( ) ;
77
+ domEvents ( ) ;
78
+ appEvents ( ) ;
49
79
50
80
return true ;
51
81
} ;
@@ -69,74 +99,74 @@ const update = () => {
69
99
WEBVIEW . status = "Framed" ;
70
100
}
71
101
102
+ // Update widget status
103
+ if ( ! HARDWARE . support . keyboardVisibility ) {
104
+ WEBVIEW . widget . webContents . send ( "button-hide" , { id : "keyboard" } ) ;
105
+ }
106
+
72
107
// Update integration sensor
73
108
console . log ( "Update Kiosk Status:" , WEBVIEW . status ) ;
74
109
integration . update ( ) ;
75
110
} ;
76
111
77
112
/**
78
113
* Register window events and handler.
79
- *
80
- * @param {Object } window - The root window object.
81
- * @param {number } zoom - Zoom level used for the webview.
82
114
*/
83
- const windowEvents = ( window , zoom ) => {
84
- // Handle window resize for webview bounds
115
+ const windowEvents = ( ) => {
116
+ // Handle window resize events
85
117
const resize = ( ) => {
86
- const { width, height } = window . getBounds ( ) ;
87
- WEBVIEW . view . setBounds ( { x : 0 , y : 0 , width : width , height : height } ) ;
88
- WEBVIEW . view . webContents . setZoomFactor ( zoom ) ;
89
- } ;
90
- window . on ( "ready-to-show" , resize ) ;
91
- window . on ( "resize" , resize ) ;
92
- resize ( ) ;
118
+ const window = WEBVIEW . window . getBounds ( ) ;
119
+ const widget = { width : 60 , height : 200 } ;
93
120
94
- // Handle window status updates
95
- window . on ( "minimize" , update ) ;
96
- window . on ( "restore" , update ) ;
97
- window . on ( "maximize" , update ) ;
98
- window . on ( "unmaximize" , update ) ;
99
- window . on ( "enter-full-screen" , update ) ;
100
- window . on ( "leave-full-screen" , update ) ;
121
+ // Update view size
122
+ WEBVIEW . view . setBounds ( {
123
+ x : 0 ,
124
+ y : 0 ,
125
+ width : window . width ,
126
+ height : window . height ,
127
+ } ) ;
128
+ WEBVIEW . view . webContents . setZoomFactor ( WEBVIEW . viewZoom ) ;
129
+ WEBVIEW . view . webContents . focus ( ) ;
101
130
102
- // Handle signal and exit events
103
- process . on ( "SIGINT" , app . quit ) ;
104
- app . on ( "before-quit" , ( ) => {
105
- WEBVIEW . status = "Terminated" ;
106
- integration . update ( ) ;
107
- } ) ;
108
-
109
- // Handle multiple instances
110
- app . on ( "second-instance" , ( ) => {
111
- if ( window . isMinimized ( ) ) {
112
- window . restore ( ) ;
131
+ // Update widget size
132
+ if ( WEBVIEW . widgetEnabled ) {
133
+ WEBVIEW . widget . setBounds ( {
134
+ x : window . width - 15 ,
135
+ y : parseInt ( window . height / 2 - widget . height / 2 ) ,
136
+ width : widget . width ,
137
+ height : widget . height ,
138
+ } ) ;
139
+ WEBVIEW . widget . webContents . send ( "data-theme" , { theme : "hidden" } ) ;
113
140
}
114
- window . focus ( ) ;
115
- } ) ;
116
- } ;
141
+ } ;
142
+ WEBVIEW . window . on ( "ready-to-show" , resize ) ;
143
+ WEBVIEW . window . on ( "resize" , resize ) ;
144
+ resize ( ) ;
117
145
118
- /**
119
- * Register touch events and handler.
120
- *
121
- * @param {Object } window - The root window object.
122
- */
123
- const touchEvents = ( window ) => {
124
- // Handle focus change for webview lock
125
- window . on ( "focus" , ( ) => {
146
+ // Handle window focus events
147
+ WEBVIEW . window . on ( "focus" , ( ) => {
126
148
if ( WEBVIEW . locked ) {
127
149
hardware . setDisplayStatus ( "ON" ) ;
128
- window . blur ( ) ;
150
+ WEBVIEW . window . blur ( ) ;
129
151
}
130
152
WEBVIEW . locked = false ;
131
153
} ) ;
132
154
HARDWARE . display . notifiers . push ( ( ) => {
133
155
WEBVIEW . locked = hardware . getDisplayStatus ( ) === "OFF" ;
134
156
if ( WEBVIEW . locked ) {
135
- window . blur ( ) ;
157
+ WEBVIEW . window . blur ( ) ;
136
158
}
137
159
} ) ;
138
160
139
- // Handle touch events for activity tracking
161
+ // Handle window status updates
162
+ WEBVIEW . window . on ( "minimize" , update ) ;
163
+ WEBVIEW . window . on ( "restore" , update ) ;
164
+ WEBVIEW . window . on ( "maximize" , update ) ;
165
+ WEBVIEW . window . on ( "unmaximize" , update ) ;
166
+ WEBVIEW . window . on ( "enter-full-screen" , update ) ;
167
+ WEBVIEW . window . on ( "leave-full-screen" , update ) ;
168
+
169
+ // Handle window touch events for activity tracking
140
170
setInterval ( ( ) => {
141
171
const posOld = WEBVIEW . pointer . position ;
142
172
const posNew = screen . getCursorScreenPoint ( ) ;
@@ -156,35 +186,134 @@ const touchEvents = (window) => {
156
186
} ;
157
187
158
188
/**
159
- * Register webview events and handler.
160
- *
161
- * @param {Object } view - The main webview object.
189
+ * Register widget events and handler.
162
190
*/
163
- const viewEvents = ( view ) => {
191
+ const widgetEvents = ( ) => {
192
+ if ( ! WEBVIEW . widgetEnabled ) {
193
+ return ;
194
+ }
195
+
196
+ // Handle widget focus events
197
+ WEBVIEW . widget . webContents . on ( "focus" , ( ) => {
198
+ const window = WEBVIEW . window . getBounds ( ) ;
199
+ const widget = WEBVIEW . widget . getBounds ( ) ;
200
+
201
+ // Show widget
202
+ WEBVIEW . widget . setBounds ( {
203
+ x : window . width - 60 ,
204
+ y : widget . y ,
205
+ width : widget . width ,
206
+ height : widget . height ,
207
+ } ) ;
208
+ WEBVIEW . widget . webContents . send ( "data-theme" , { theme : WEBVIEW . widgetTheme } ) ;
209
+ } ) ;
210
+
211
+ // Handle widget blur events
212
+ WEBVIEW . widget . webContents . on ( "blur" , ( ) => {
213
+ const window = WEBVIEW . window . getBounds ( ) ;
214
+ const widget = WEBVIEW . widget . getBounds ( ) ;
215
+
216
+ // Hide widget
217
+ WEBVIEW . widget . setBounds ( {
218
+ x : window . width - 15 ,
219
+ y : widget . y ,
220
+ width : widget . width ,
221
+ height : widget . height ,
222
+ } ) ;
223
+ WEBVIEW . widget . webContents . send ( "data-theme" , { theme : "hidden" } ) ;
224
+ } ) ;
225
+
226
+ // Handle widget button click events
227
+ ipcMain . on ( "button-click" , ( e , button ) => {
228
+ switch ( button . id ) {
229
+ case "refresh" :
230
+ WEBVIEW . view . webContents . reloadIgnoringCache ( ) ;
231
+ break ;
232
+ case "fullscreen" :
233
+ if ( WEBVIEW . window . isFullScreen ( ) ) {
234
+ WEBVIEW . window . restore ( ) ;
235
+ WEBVIEW . window . unmaximize ( ) ;
236
+ WEBVIEW . window . setFullScreen ( false ) ;
237
+ } else {
238
+ WEBVIEW . window . restore ( ) ;
239
+ WEBVIEW . window . unmaximize ( ) ;
240
+ WEBVIEW . window . setFullScreen ( true ) ;
241
+ }
242
+ break ;
243
+ case "minimize" :
244
+ WEBVIEW . window . restore ( ) ;
245
+ WEBVIEW . window . setFullScreen ( false ) ;
246
+ WEBVIEW . window . minimize ( ) ;
247
+ break ;
248
+ case "keyboard" :
249
+ const toggle = hardware . getKeyboardVisibility ( ) === "ON" ? "OFF" : "ON" ;
250
+ hardware . setKeyboardVisibility ( toggle ) ;
251
+ switch ( toggle ) {
252
+ case "OFF" :
253
+ WEBVIEW . window . restore ( ) ;
254
+ WEBVIEW . window . unmaximize ( ) ;
255
+ WEBVIEW . window . setFullScreen ( true ) ;
256
+ break ;
257
+ case "ON" :
258
+ WEBVIEW . window . restore ( ) ;
259
+ WEBVIEW . window . setFullScreen ( false ) ;
260
+ WEBVIEW . window . maximize ( ) ;
261
+ break ;
262
+ }
263
+ break ;
264
+ }
265
+ } ) ;
266
+ } ;
267
+
268
+ /**
269
+ * Register dom events and handler.
270
+ */
271
+ const domEvents = ( ) => {
164
272
// Enable webview touch emulation
165
- view . webContents . debugger . attach ( "1.1" ) ;
166
- view . webContents . debugger . sendCommand ( "Emulation.setEmitTouchEventsForMouse" , {
273
+ WEBVIEW . view . webContents . debugger . attach ( "1.1" ) ;
274
+ WEBVIEW . view . webContents . debugger . sendCommand ( "Emulation.setEmitTouchEventsForMouse" , {
167
275
configuration : "mobile" ,
168
276
enabled : true ,
169
277
} ) ;
170
278
171
279
// Disable webview hyperlinks
172
- view . webContents . setWindowOpenHandler ( ( ) => {
280
+ WEBVIEW . view . webContents . setWindowOpenHandler ( ( ) => {
173
281
return { action : "deny" } ;
174
282
} ) ;
175
283
176
284
// Remove webview scrollbar
177
- view . webContents . on ( "dom-ready" , ( ) => {
178
- view . webContents . insertCSS ( "::-webkit-scrollbar { display: none; }" ) ;
285
+ WEBVIEW . view . webContents . on ( "dom-ready" , ( ) => {
286
+ WEBVIEW . view . webContents . insertCSS ( "::-webkit-scrollbar { display: none; }" ) ;
179
287
} ) ;
180
288
181
289
// Webview fully loaded
182
- view . webContents . on ( "did-finish-load" , ( ) => {
290
+ WEBVIEW . view . webContents . on ( "did-finish-load" , ( ) => {
291
+ // view.webContents.openDevTools();
183
292
WEBVIEW . initialized = true ;
184
293
update ( ) ;
185
294
} ) ;
186
295
} ;
187
296
297
+ /**
298
+ * Register app events and handler.
299
+ */
300
+ const appEvents = ( ) => {
301
+ // Handle signal and exit events
302
+ process . on ( "SIGINT" , app . quit ) ;
303
+ app . on ( "before-quit" , ( ) => {
304
+ WEBVIEW . status = "Terminated" ;
305
+ integration . update ( ) ;
306
+ } ) ;
307
+
308
+ // Handle multiple instances
309
+ app . on ( "second-instance" , ( ) => {
310
+ if ( WEBVIEW . window . isMinimized ( ) ) {
311
+ WEBVIEW . window . restore ( ) ;
312
+ }
313
+ WEBVIEW . window . focus ( ) ;
314
+ } ) ;
315
+ } ;
316
+
188
317
module . exports = {
189
318
init,
190
319
update,
0 commit comments