@fto-consult/expo-ui 7.5.34 → 7.5.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/index.js CHANGED
@@ -53,13 +53,13 @@ program.command('electron')
53
53
  .option('-b, --build [boolean]', 'si ce flag est spécfifié alors l\'application sera compilée; combinée avec la commande start|package pour indiquer que l\'application sera à nouveau exportée ou pas.')
54
54
  .option('-a, --arch [architecture]', 'l\'architecture de la plateforme; Commande package')
55
55
  .option('-p, --platform [platform]', 'la plateforme à utiliser pour la compilation; commande package')
56
- .option('-l, --logo [logoPath]', 'le chemin vers le logo de l\'application : (.ico pour window, .incs pour mac et .png pour linux)')
56
+ .option('-l, --icon [iconPath]', 'le chemin vers l\'icon de l\'application : (.ico pour window, .incs pour mac et .png pour linux)')
57
57
  .option('-i, --import [boolean]', 'la commande d\'initialisation du package electron forge, utile pour le packaging de l\'application. Elle permet d\'exécuter le cli electron package, pour l\'import d\'un projet existant. Commande package. exemple : expo-ui electron package --import')
58
58
 
59
59
  .action((script, options) => {
60
60
  const electronProjectRoot = path.resolve(projectRoot,"electron");
61
61
  const opts = Object.assign({},typeof options.opts =='function'? options.opts() : options);
62
- let {out,arch,url,build,platform,import:packageImport,logo} = opts;
62
+ let {out,arch,url,build,platform,import:packageImport,icon} = opts;
63
63
  //let {projectRoot} = opts;
64
64
  if(projectRoot == dir){
65
65
  throwError(`Invalid project root ${projectRoot}; project root must be different to ${dir}`);
@@ -78,8 +78,8 @@ program.command('electron')
78
78
  const packageObj = require(`${packagePath}`);
79
79
  const homepage = packageObj.homepage;
80
80
  let cmd = undefined;
81
- logo = logo && typeof logo =="string" && fs.existsSync(path.resolve(logo)) && logo || undefined;
82
- require("../electron/create-index-file")({electronProjectRoot,appName:packageObj.name,logo});
81
+ icon = icon && typeof icon =="string" && fs.existsSync(path.resolve(icon)) && icon || undefined;
82
+ require("../electron/create-index-file")({electronProjectRoot,appName:packageObj.name,icon});
83
83
  if(!isElectionInitialized || script =='init'){
84
84
  if(script !=='init'){
85
85
  console.log("initializing electron application before ....");
@@ -96,7 +96,7 @@ program.command('electron')
96
96
  }
97
97
  const start = x=>{
98
98
  return new Promise((resolve,reject)=>{
99
- cmd = `electron "${electronProjectRoot}" --root ${electronProjectRoot} ${isValidUrl(url)? ` --url ${url}`:''}`;
99
+ cmd = `electron "${electronProjectRoot}" --root ${electronProjectRoot} ${isValidUrl(url)? ` --url ${url}`:''} ${icon ? `--icon ${path.resolve(icon)}`:""}`;
100
100
  exec({
101
101
  cmd,
102
102
  projectRoot : electronProjectRoot,
package/bin/init.js CHANGED
@@ -22,7 +22,7 @@ module.exports = ({projectRoot,electronProjectRoot})=>{
22
22
  const projectRootPackage = {...mPackageJSON,...electronPackageJSON};
23
23
  const dependencies = require("../electron/dependencies");
24
24
  const electronProjectRootPackage = path.resolve(electronProjectRoot,"package.json");
25
- projectRootPackage.main = `node_modules/${mainPackageName}/electron/index.js`;
25
+ projectRootPackage.main = `index.js`;
26
26
  projectRootPackage.dependencies = {...dependencies.main,...Object.assign(electronPackageJSON.dependencies)};
27
27
  projectRootPackage.dependencies[mainPackage.name] = mainPackage.version;
28
28
  projectRootPackage.devDependencies = {...dependencies.dev,...Object.assign({},electronPackageJSON.devDependencies)};
@@ -10,12 +10,11 @@ module.exports = ({electronProjectRoot,force,logo,appName})=>{
10
10
  const indexPath = path.resolve(electronProjectRoot,"index.js");
11
11
  if(!fs.existsSync(indexPath) || force === true){
12
12
  writeFile(indexPath,`
13
- require("${packageJSON.name}/electron/index.js")({
13
+ require("${packageJSON.name}/electron")({
14
14
  projectRoot : __dirname,
15
15
  appName : "${appName}",
16
16
  logo : ${logo ? `"${logo}"` : undefined},
17
- })
18
- `);
19
- }
17
+ });`);
18
+ }
20
19
  return indexPath;
21
20
  }
package/electron/index.js CHANGED
@@ -1,57 +1,546 @@
1
1
  const { program } = require('commander');
2
- const mainApp = require("./main-app");
2
+ const path = require("path");
3
+ const fs = require("fs");
4
+ const isValidUrl = require("./utils/isValidUrl");
5
+
6
+ const debounce = require("./utils/debounce");
7
+ const {app, BrowserWindow,Tray,Menu,MenuItem,globalShortcut,systemPreferences,powerMonitor,ipcMain,dialog, nativeTheme} = require('electron')
8
+ const session = require("./utils/session");
9
+ const {isJSON} = require("./utils/json");
10
+
11
+ const isObj = x => x && typeof x =='object';
3
12
 
4
13
  program
5
14
  .option('-u, --url <url>', 'L\'adresse url à ouvrir au lancement de l\'application')
6
15
  .option('-r, --root <projectRoot>', 'le chemin du project root de l\'application')
16
+ .option('-l, --icon [iconPath]', 'le chemin vers le icon de l\'application : (.ico pour window, .incs pour mac et .png pour linux)')
7
17
  .parse();
8
18
 
9
19
  const programOptions = program.opts();
10
- const {url,root:mainProjectRoot} = programOptions;
20
+ const {url:pUrl,root:mainProjectRoot,icon} = programOptions;
21
+ const iconPath = icon && typeof icon =="string" && fs.existsSync(path.resolve(icon)) && path.resolve(icon) || undefined;
11
22
 
12
23
  const isAsar = (typeof require.main =="string" && require.main ||"").indexOf('app.asar') !== -1;
13
- const path = require("path");
14
- const fs = require("fs");
15
- const isValidUrl = require("./utils/isValidUrl");
16
24
  const distPath = path.join("dist",'index.html');
17
25
 
18
26
  const processCWD = process.cwd();
19
27
  const electronProjectRoot = mainProjectRoot && typeof mainProjectRoot =='string' && fs.existsSync(path.resolve(mainProjectRoot)) && fs.existsSync(path.resolve(mainProjectRoot,distPath)) && path.resolve(mainProjectRoot) || null;
20
- const projectRoot = electronProjectRoot || fs.existsSync(path.resolve(processCWD,"electron")) && fs.existsSync(path.resolve(processCWD,"electron",distPath)) && path.resolve(processCWD,"electron") || undefined;
28
+ const projectRoot = electronProjectRoot || fs.existsSync(path.resolve(processCWD,"electron")) && fs.existsSync(path.resolve(processCWD,"electron",distPath)) && path.resolve(processCWD,"electron")
29
+ || fs.existsSync(path.resolve(processCWD,distPath)) && path.resolve(processCWD) || undefined;
21
30
  const packageJSONPath = fs.existsSync(processCWD,"package.json")? path.resolve(processCWD,"package.json") : path.resolve(projectRoot,"package.json");
22
- const packageJSON = fs.existsSync(packageJSONPath) ? require(`${packageJSONPath}`) : {};
31
+ const packageJSON = fs.existsSync(packageJSONPath) ? Object.assign({},require(`${packageJSONPath}`)) : {};
32
+ const appName = typeof packageJSON.realAppName =='string' && packageJSON.realAppName || typeof packageJSON.name =="string" && packageJSON.name || "";
33
+
34
+ // fermee automatiquement quand l'objet JavaScript sera garbage collected.
35
+ let mainWindow = undefined;
36
+
37
+ Menu.setApplicationMenu(null);
38
+
39
+ const indexFilePath = path.resolve(path.join(projectRoot,distPath));
40
+ const mainProcessPath = path.resolve('processes',"main","index.js");
41
+ const mainProcessIndex = projectRoot && fs.existsSync(path.resolve(projectRoot,mainProcessPath)) && path.resolve(projectRoot,mainProcessPath);
42
+ const mainProcessRequired = mainProcessIndex && require(`${mainProcessIndex}`);
43
+ //pour étendre les fonctionnalités au niveau du main proceess, bien vouloir écrire dans le fichier projectRoot/electron/main/index.js
44
+ const mainProcess = mainProcessRequired && typeof mainProcessRequired =='object'? mainProcessRequired : {};
23
45
 
24
- const ObjectSize = (object)=>{
25
- if(!object || typeof object !=='object' || Array.isArray(object)) return false;
26
- for(let i in object){
27
- if(object?.hasOwnProperty(i)) return true;
46
+
47
+ const quit = ()=>{
48
+ try {
49
+ app.quit();
50
+ } catch(e){
51
+ console.log(e," triing kit app")
28
52
  }
29
- return false;
30
53
  }
31
54
 
32
- function mainExportedApp (options){
55
+ // Gardez une reference globale de l'objet window, si vous ne le faites pas, la fenetre sera
56
+ if(!isValidUrl(pUrl) && !fs.existsSync(indexFilePath)){
57
+ throw {message:`Unable to start the application: index file located at [${indexFilePath}] does not exists : projectRoot = [${projectRoot}], isAsar:[${require.main}]`}
58
+ }
59
+
60
+ //app.disableHardwareAcceleration();
61
+
62
+ function createBrowserWindow (options){
63
+ const {isMainWindow} = options;
33
64
  options = Object.assign({},options);
34
- options.isAsar = isAsar;
35
- options.url = isValidUrl(options.url)? options.url : isValidUrl(url)? url : undefined;
36
- if(!options.projectRoot || typeof options.projectRoot !=='string' || !fs.existsSync(options.projectRoot) || !fs.existsSync(path.resolve(options.projectRoot,distPath))){
37
- options.projectRoot = projectRoot;
38
- }
39
- options.packageJSON = ObjectSize(options.packageJSON) && options.packageJSON || packageJSON;
40
- if(!ObjectSize(options.packageJSON)){
41
- if(options.projectRoot && typeof options.projectRoot =='string' && fs.existsSync(path.resolve(options.projectRoot,"package.json"))){
42
- options.packageJSON = require(path.resolve(options.projectRoot,"package.json"));
43
- }
65
+ const menu = options.menu;
66
+ options.webPreferences = isObj(options.webPreferences)? options.webPreferences : {};
67
+ options.webPreferences = {
68
+ sandbox: false,
69
+ webSecurity : true,
70
+ plugin:false,
71
+ autoHideMenuBar: true,
72
+ contextIsolation: true,
73
+ contentSecurityPolicy: `
74
+ default-src 'none';
75
+ script-src 'self';
76
+ img-src 'self' data:;
77
+ style-src 'self';
78
+ font-src 'self';
79
+ `,
80
+ ...options.webPreferences,
81
+ devTools: typeof options.webPreferences.devTools === 'boolean'? options.webPreferences.devTools : false,
82
+ allowRunningInsecureContent: false,
83
+ nodeIntegration: false,
84
+ preload: options.preload ? options.preload : null,
85
+ }
86
+ if(options.modal && !options.parent && mainWindow){
87
+ options.parent = mainWindow;
88
+ }
89
+ if(typeof options.show ==='undefined'){
90
+ options.show = false;
91
+ }
92
+ let showOnLoad = options.showOnLoad ===true ? true : undefined;
93
+ if(showOnLoad){
94
+ options.show = false;
95
+ }
96
+ if(typeof mainProcess?.beforeCreateWindow =='function'){
97
+ const opts = Object.assign({},mainProcess.beforeCreateWindow(options));
98
+ options = {...options,...opts};
44
99
  }
45
- options.appName = typeof options.appName =="string" && options.appName ||
46
- typeof options.packageJSON?.realAppName =='string' && options?.packageJSON?.realAppName || typeof packageJSON?.realAppName =="string" && packageJSON?.realAppName ||
47
- typeof option?.packageJSON?.name =="string" && options?.packageJSON?.name || typeof packageJSON.name =="string" && packageJSON.name || undefined;
48
- return mainApp(options);
100
+ options.icon = options.icon || iconPath;
101
+ const window = new BrowserWindow(options);
102
+ if(!menu){
103
+ window.setMenu(null);
104
+ window.removeMenu();
105
+ window.setMenuBarVisibility(false)
106
+ window.setAutoHideMenuBar(true)
107
+ }
108
+ if(showOnLoad){
109
+ window.once('ready-to-show', () => {
110
+ window.show();
111
+ window.webContents.send("window-ready-to-show",JSON.stringify(options.readyToShowOptions));
112
+ });
113
+ }
114
+ window.on('closed', function() {
115
+ if(isMainWindow && typeof mainProcess?.onMainWindowClosed == "function"){
116
+ mainProcess.onMainWindowClosed(window);
117
+ }
118
+ window = null;
119
+ });
120
+ window.webContents.on('context-menu',clipboadContextMenu);
121
+ const url = isValidUrl(options.loadURL) || typeof options.loadURL ==='string' && options.loadURL.trim().startsWith("file://") ? options.loadURL : undefined;
122
+ if(url){
123
+ window.loadURL(url);
124
+ } else if(options.file && fs.existsSync(path.resolve(options.file))){
125
+ window.loadFile(path.resolve(options.file));
126
+ }
127
+ return window;
49
128
  }
129
+
130
+ app.whenReady().then(() => {
131
+ createWindow();
132
+ const readOpts = {toggleDevTools,browserWindow:mainWindow,mainWindow:mainWindow};
133
+ if(typeof mainProcess.whenAppReady =='function'){
134
+ mainProcess.whenAppReady(readOpts);
135
+ }
136
+ globalShortcut.register('CommandOrControl+F12', () => {
137
+ return toggleDevTools();
138
+ });
139
+ app.on('activate', function () {
140
+ if (mainWindow == null || (BrowserWindow.getAllWindows().length === 0)) createWindow()
141
+ });
142
+ });
50
143
 
51
- module.exports = mainExportedApp;
52
-
53
- if(isValidUrl(url) || electronProjectRoot){
54
- mainExportedApp({url:url,projectRoot,packageJSON});
144
+ function createWindow () {
145
+ // Créer le browser window
146
+ mainWindow = createBrowserWindow({
147
+ showOnLoad : false,
148
+ loadURL : undefined,
149
+ isMainWindow : true,
150
+ registerDevToolsCommand : false,
151
+ file : indexFilePath,
152
+ url : pUrl,
153
+ preload : path.resolve(__dirname,'preload.js'),
154
+ webPreferences : {
155
+ devTools : true,
156
+ }
157
+ });
158
+ const sOptions = {width: 500, height: 400, transparent: true, frame: false, alwaysOnTop: true};
159
+ const splash = typeof mainProcess.splashScreen ==='function'&& mainProcess.splashScreen(sOptions)
160
+ || typeof mainProcess.splash ==='function' && mainProcess.splash(sOptions)
161
+ || (mainProcess.splash instanceof BrowserWindow) && mainProcess.splash
162
+ || (mainProcess.splashScreen instanceof BrowserWindow) && mainProcess.splashScreen;
163
+ null;
164
+ let hasInitWindows = false;
165
+ mainWindow.on('show', () => {
166
+ //mainWindow.blur();
167
+ setTimeout(() => {
168
+ mainWindow.focus();
169
+ mainWindow.moveTop();
170
+ mainWindow.webContents.focus();
171
+ if(!hasInitWindows){
172
+ hasInitWindows = true;
173
+ mainWindow.webContents.send('appReady');
174
+ }
175
+ }, 200);
176
+ });
177
+
178
+ mainWindow.on("focus",()=>{
179
+ if(mainWindow && hasInitWindows){
180
+ mainWindow.webContents.send("main-window-focus");
181
+ }
182
+ });
183
+ mainWindow.on("blur",()=>{
184
+ if(mainWindow && hasInitWindows){
185
+ mainWindow.webContents.send("main-window-blur");
186
+ }
187
+ });
188
+ mainWindow.once("ready-to-show",function(){
189
+ if(typeof mainProcess.onMainWindowReadyToShow ==='function'){
190
+ mainProcess.onMainWindowReadyToShow(mainWindow);
191
+ }
192
+ mainWindow.minimize()
193
+ try {
194
+ if(splash && splash instanceof BrowserWindow){
195
+ splash.destroy();
196
+ }
197
+ } catch{ }
198
+ mainWindow.restore();
199
+ mainWindow.show();
200
+ })
201
+
202
+ mainWindow.on('close', (e) => {
203
+ if (mainWindow) {
204
+ if(typeof mainProcess.onMainWindowClose == "function"){
205
+ mainProcess.onMainWindowClose(mainWindow);
206
+ }
207
+ e.preventDefault();
208
+ mainWindow.webContents.send('before-app-exit');
209
+ }
210
+ });
211
+
212
+ mainWindow.on('unresponsive', async () => {
213
+ const { response } = await dialog.showMessageBox({
214
+ title: "L'application a cessé de répondre",
215
+ message : 'Voulez vous relancer l\'application?',
216
+ buttons: ['Relancer', 'Arrêter'],
217
+ cancelId: 1
218
+ });
219
+ if (response === 0) {
220
+ mainWindow.forcefullyCrashRenderer()
221
+ mainWindow.reload()
222
+ } else {
223
+ mainWindow.forcefullyCrashRenderer()
224
+ app.exit();
225
+ }
226
+ });
227
+
228
+ // Émit lorsque la fenêtre est fermée.
229
+ mainWindow.on('closed', () => {
230
+ mainWindow = null
231
+ })
232
+ mainWindow.setMenu(null);
233
+
234
+ /*** les dimenssions de la fenêtre principale */
235
+ let mWindowSessinName = "mainWindowSizes";
236
+ let mWindowPositionSName = mWindowSessinName+"-positions";
237
+ let sizeW = session.get(mWindowSessinName);
238
+ if(!sizeW || typeof sizeW !== 'object'){
239
+ sizeW = {};
240
+ }
241
+ let sPositions = session.get(mWindowPositionSName);
242
+ if(!sPositions || typeof sPositions !=='object'){
243
+ sPositions = {};
244
+ }
245
+ let isNumber = x => typeof x =="number";
246
+ if(isNumber(sizeW.width) && isNumber(sizeW.height)){
247
+ mainWindow.setSize(sizeW.width,sizeW.height);
248
+ if(isNumber(sPositions.x) && isNumber(sPositions.y)){
249
+ mainWindow.setPosition(sPositions.x,sPositions.y);
250
+ }
251
+ }
252
+ const onWinResizeEv = debounce(function () {
253
+ if(mainWindow){
254
+ let wSize = mainWindow.getSize();
255
+ if(Array.isArray(wSize) && wSize.length == 2){
256
+ let [width,height] = wSize;
257
+ if(width && height){
258
+ session.set(mWindowSessinName,{width,height});
259
+ }
260
+ let [x,y] = mainWindow.getPosition();
261
+ session.set(mWindowPositionSName,{x,y});
262
+ }
263
+ }
264
+ }, 100);
265
+ mainWindow.off('resize',onWinResizeEv);
266
+ mainWindow.on('resize',onWinResizeEv);
267
+ mainWindow.off('move',onWinResizeEv);
268
+ mainWindow.on('move',onWinResizeEv);
269
+ if(typeof mainProcess.onCreateMainWindow =='function'){
270
+ mainProcess.onCreateMainWindow(mainWindow);
271
+ }
272
+ return mainWindow;
55
273
  }
274
+
275
+ const toggleDevTools = (value)=>{
276
+ if(mainWindow !==null && mainWindow.webContents){
277
+ const isOpen= mainWindow.webContents.isDevToolsOpened();
278
+ value = value === undefined ? !isOpen : value;
279
+ if(value && !isOpen){
280
+ mainWindow.webContents.openDevTools();
281
+ return mainWindow.webContents.isDevToolsOpened();
282
+ } else {
283
+ if(isOpen) mainWindow.webContents.closeDevTools();
284
+ }
285
+ return mainWindow.webContents.isDevToolsOpened();
286
+ }
287
+ return false;
288
+ }
289
+ ipcMain.on("toggle-dev-tools",function(event,value) {
290
+ return toggleDevTools(value);
291
+ });
292
+
293
+ ipcMain.handle("create-browser-windows",function(event,options){
294
+ if(typeof options =='string'){
295
+ try {
296
+ const t = JSON.parse(options);
297
+ options = t;
298
+ } catch{}
299
+ }
300
+ options = Object.assign({},options);
301
+ createBrowserWindow(options);
302
+ });
303
+
304
+ ipcMain.on("restart-app",x =>{
305
+ app.relaunch();
306
+ });
307
+ let tray = null;
308
+ ipcMain.on("update-system-tray",(event,opts)=>{
309
+ opts = opts && typeof opts == 'object'? opts : {};
310
+ let {contextMenu,tooltip} = opts;
311
+ if(tray){
312
+ } else {
313
+ tray = new Tray();
314
+ }
315
+ if(!tooltip || typeof tooltip !=="string"){
316
+ tooltip = ""
317
+ }
318
+ tray.setToolTip(tooltip);
319
+ if(isJSON(contextMenu)){
320
+ contextMenu = JSON.parse(contextMenu);
321
+ }
322
+ if(Array.isArray(contextMenu) && contextMenu.length) {
323
+ let tpl = []
324
+ contextMenu.map((m,index)=>{
325
+ if(!m || typeof m !=='object') return;
326
+ m.click = (e)=>{
327
+ if(mainWindow && mainWindow.webContents) mainWindow.webContents.send("click-on-system-tray-menu-item",{
328
+ action : m.action && typeof m.action =='string'? m.action : undefined,
329
+ index,
330
+ menuItem : JSON.stringify(m),
331
+ })
332
+ }
333
+ tpl.push(m);
334
+ })
335
+ contextMenu = Menu.buildFromTemplate(tpl);
336
+ } else contextMenu = null;
337
+ tray.setContextMenu(contextMenu)
338
+ });
339
+
340
+ ipcMain.on("get-path",(event,pathName)=>{
341
+ const p = app.getPath(pathName);
342
+ event.returnValue = p;
343
+ return p;
344
+ });
345
+ ipcMain.on("get-project-root",(event)=>{
346
+ event.returnValue = projectRoot;
347
+ return event.returnValue;
348
+ });
349
+ ipcMain.on("get-electron-project-root",(event)=>{
350
+ event.returnValue = projectRoot;
351
+ return event.returnValue ;
352
+ });
353
+
354
+ ipcMain.on("get-package.json",(event)=>{
355
+ event.returnValue = JSON.stringify(packageJSON);
356
+ return event.returnValue ;
357
+ });
358
+
359
+ ipcMain.on("get-app-name",(event)=>{
360
+ event.returnValue = appName;
361
+ return event.returnValue ;
362
+ });
363
+
364
+ ipcMain.on("get-media-access-status",(event,mediaType)=>{
365
+ let p = systemPreferences.getMediaAccessStatus(mediaType);
366
+ event.returnValue = p;
367
+ return p;
368
+ });
369
+
370
+ ipcMain.on("ask-for-media-access",(event,mediaType)=>{
371
+ systemPreferences.askForMediaAccess(mediaType);
372
+ });
373
+
374
+ ipcMain.on("get-app-icon",(event)=>{
375
+ event.returnValue = mainWindow != mainWindow && mainWindow.getIcon && mainWindow.getIcon();
376
+ });
377
+ ipcMain.on("set-app-icon",(event,iconPath)=>{
378
+ if(iconPath && mainWindow != null){
379
+ mainWindow.setIcon(iconPath);
380
+ event.returnValue = iconPath;
381
+ } else {
382
+ event.returnValue = null;
383
+ }
384
+ });
385
+
386
+ ipcMain.on('minimize-main-window', () => {
387
+ if(mainWindow !== null && mainWindow){
388
+ mainWindow.blur();
389
+ mainWindow.minimize();
390
+ }
391
+ })
392
+ ipcMain.on('restore-main-window', () => {
393
+ if(mainWindow && mainWindow !== null){
394
+ mainWindow.restore()
395
+ mainWindow.blur();
396
+ setTimeout(() => {
397
+ mainWindow.focus();
398
+ mainWindow.moveTop();
399
+ mainWindow.webContents.focus();
400
+ }, 200);
401
+ }
402
+ })
403
+ ipcMain.on('close-main-render-process', _ => {
404
+ if(mainWindow){
405
+ mainWindow.destroy();
406
+ }
407
+ mainWindow = null;
408
+ if(typeof gc =="function"){
409
+ gc();
410
+ }
411
+ quit();
412
+ });
413
+
414
+ const powerMonitorCallbackEvent = (action)=>{
415
+ if(!mainWindow || !mainWindow.webContents) return;
416
+ if(action =="suspend" || action =="lock-screen"){
417
+ mainWindow.webContents.send("main-app-suspended",action);
418
+ return;
419
+ }
420
+ mainWindow.webContents.send("main-app-restaured",action);
421
+ mainWindow.webContents.focus();
422
+ return null;
423
+ }
424
+ if(powerMonitor){
425
+ ["suspend","resume","lock-screen","unlock-screen"].map((action)=>{
426
+ powerMonitor.on(action,(event)=>{
427
+ powerMonitorCallbackEvent(action,event);
428
+ })
429
+ })
430
+ }
431
+ ipcMain.on("set-main-window-title",(event,title)=>{
432
+ if(mainWindow !== null){
433
+ mainWindow.setTitle(title);
434
+ }
435
+ });
436
+
437
+ ipcMain.handle("show-open-dialog",function(event,options){
438
+ if(typeof options =="string"){
439
+ try {
440
+ const t = JSON.parse(options);
441
+ options = t;
442
+ } catch{}
443
+ }
444
+ if(!isObj(options)){
445
+ options = {};
446
+ }
447
+ return dialog.showOpenDialog(mainWindow,options)
448
+ })
449
+
450
+ ipcMain.handle("show-save-dialog",function(event,options){
451
+ if(!isObj(options)){
452
+ options = {};
453
+ }
454
+ return dialog.showSaveDialog(mainWindow,options)
455
+ });
456
+
457
+ ipcMain.on("is-dev-tools-open",function(event,value) {
458
+ if(mainWindow !==null && mainWindow.webContents){
459
+ return mainWindow.webContents.isDevToolsOpened();
460
+ }
461
+ return false;
462
+ });
463
+
464
+ ipcMain.on("window-set-progressbar",(event,interval)=>{
465
+ if(typeof interval !="number" || interval <0) interval = 0;
466
+ interval = Math.floor(interval);
467
+ if(mainWindow){
468
+ mainWindow.setProgressBar(interval);
469
+ }
470
+ });
471
+
472
+ /**** customisation des thèmes de l'application */
473
+ ipcMain.handle('set-system-theme:toggle', (event,theme) => {
474
+ theme = theme && typeof theme == "string"? theme : "light";
475
+ theme = theme.toLowerCase().trim();
476
+ if(theme !== 'system' && theme !=='dark'){
477
+ theme = "light";
478
+ }
479
+ nativeTheme.themeSource = theme;
480
+ session.set("os-theme",theme);
481
+ return nativeTheme.shouldUseDarkColors
482
+ });
483
+
484
+ ipcMain.handle('set-system-theme:dark-mode', (event) => {
485
+ nativeTheme.themeSource = 'dark';
486
+ return nativeTheme.shouldUseDarkColors;
487
+ });
488
+ ipcMain.handle('set-system-theme:light-mode', (event) => {
489
+ nativeTheme.themeSource = 'light';
490
+ return nativeTheme.shouldUseDarkColors;
491
+ });
492
+
493
+
494
+ ipcMain.handle('dark-mode:toggle', () => {
495
+ if (nativeTheme.shouldUseDarkColors) {
496
+ nativeTheme.themeSource = 'light'
497
+ } else {
498
+ nativeTheme.themeSource = 'dark'
499
+ }
500
+ return nativeTheme.shouldUseDarkColors
501
+ })
502
+
503
+ ipcMain.handle('dark-mode:system', () => {
504
+ nativeTheme.themeSource = 'system'
505
+ });
506
+
507
+ const clipboadContextMenu = (_, props) => {
508
+ if (props.isEditable || props.selectionText) {
509
+ const menu = new Menu();
510
+ if(props.selectionText){
511
+ menu.append(new MenuItem({ label: 'Copier', role: 'copy' }));
512
+ if(props.isEditable){
513
+ menu.append(new MenuItem({ label: 'Couper', role: 'cut' }));
514
+ }
515
+ }
516
+ if(props.isEditable){
517
+ menu.append(new MenuItem({ label: 'Coller', role: 'paste' }));
518
+ }
519
+ menu.popup();
520
+ }
521
+ };
522
+
523
+ // Quitte l'application quand toutes les fenêtres sont fermées.
524
+ app.on('window-all-closed', () => {
525
+ // Sur macOS, il est commun pour une application et leur barre de menu
526
+ // de rester active tant que l'utilisateur ne quitte pas explicitement avec Cmd + Q
527
+ if (process.platform !== 'darwin') {
528
+ quit();
529
+ }
530
+ });
56
531
 
57
- module.exports.createBrowserWindow = mainApp.createBrowserWindow;
532
+ if(mainProcess.enableSingleInstance !== false){
533
+ const gotTheLock = app.requestSingleInstanceLock()
534
+ if (!gotTheLock) {
535
+ quit()
536
+ } else {
537
+ app.on('second-instance', (event, commandLine, workingDirectory) => {
538
+ // Someone tried to run a second instance, we should focus our window.
539
+ //pour plus tard il sera possible d'afficher la gestion multi fenêtre en environnement electron
540
+ if (mainWindow) {
541
+ if (mainWindow.isMinimized()) mainWindow.restore()
542
+ mainWindow.focus()
543
+ }
544
+ })
545
+ }
546
+ }
@@ -8,6 +8,7 @@
8
8
  */
9
9
 
10
10
  module.exports = {
11
+ enableSingleInstance: true, // si l'application n'autorise qu'une seule instance active. ça sous entend qu'à l'instant t, une seule instance de l'application ne peut être exécutée sur le profil de l'utilisateur lambda
11
12
  /**** cette fonction est appelée à chaque fois que l'on désire créer une instance du BrowserWindow
12
13
  @param {object} BrowserWindowOptions
13
14
  Lors de la création de la fenêtre principal, BrowserWindowOptions continent la propriété isMainWindow à true