From 79261720c6ed474b503f221f3a0c4a65c6d05ee1 Mon Sep 17 00:00:00 2001 From: Renaud Heluin Date: Sun, 26 May 2024 11:28:35 +0200 Subject: [PATCH] feat: electron app --- electron-react/.gitignore | 2 ++ electron-react/README.md | 25 ++++----------- electron-react/forge.config.ts | 12 +++---- electron-react/src/App.tsx | 27 ++++++++++++++++ electron-react/src/interface.d.ts | 4 +++ electron-react/src/main.ts | 52 ++++++++++++++++++------------- electron-react/src/preload.ts | 11 +++++++ electron-react/src/renderer.tsx | 13 ++++---- 8 files changed, 94 insertions(+), 52 deletions(-) diff --git a/electron-react/.gitignore b/electron-react/.gitignore index 8296128d..daf2c4bb 100644 --- a/electron-react/.gitignore +++ b/electron-react/.gitignore @@ -90,3 +90,5 @@ typings/ # Electron-Forge out/ + +reports/ \ No newline at end of file diff --git a/electron-react/README.md b/electron-react/README.md index 40edaed6..c53b6b90 100644 --- a/electron-react/README.md +++ b/electron-react/README.md @@ -1,22 +1,9 @@ -### electron-react-starter +# ELECTON-REACT-APP (ecoindex) -This is a starter template that I made for myself while learning electron. It is a modified version of the [Vite + Typescript](https://www.electronforge.io/templates/vite-+-typescript) template from electron-forge. +> https://github.com/mongj/electron-react-starter -In addition to the template, React has been added to the renderer. TailwindCSS and shadcn-ui have also been set up. +## TODO -To install the depencies and run the app in dev mode: - -``` -yarn -yarn start -``` - -To package and distribute the app: - -``` -yarn package -yarn make -yarn publish -``` - -This corresponds to the 3 build commands available via electron-forge CLI. For more information, see electron-forge's [documentation](https://www.electronforge.io/core-concepts/build-lifecycle). +- [ ] enregistrer le chemin de base, mettre un chemin par défaut ~/ecoindex-exports +- [ ] Faire une version simple, multiple urls +- [ ] Faire une version complexe, avec des options diff --git a/electron-react/forge.config.ts b/electron-react/forge.config.ts index 1961d106..73d0da03 100644 --- a/electron-react/forge.config.ts +++ b/electron-react/forge.config.ts @@ -58,12 +58,12 @@ const config: ForgeConfig = { // at package time, before code signing the application new FusesPlugin({ version: FuseVersion.V1, - [FuseV1Options.RunAsNode]: false, - [FuseV1Options.EnableCookieEncryption]: true, - [FuseV1Options.EnableNodeOptionsEnvironmentVariable]: false, - [FuseV1Options.EnableNodeCliInspectArguments]: false, - [FuseV1Options.EnableEmbeddedAsarIntegrityValidation]: true, - [FuseV1Options.OnlyLoadAppFromAsar]: true, + // [FuseV1Options.RunAsNode]: true, + // [FuseV1Options.EnableCookieEncryption]: true, + // [FuseV1Options.EnableNodeOptionsEnvironmentVariable]: true, + // [FuseV1Options.EnableNodeCliInspectArguments]: true, + // [FuseV1Options.EnableEmbeddedAsarIntegrityValidation]: true, + // [FuseV1Options.OnlyLoadAppFromAsar]: true, }), ], } diff --git a/electron-react/src/App.tsx b/electron-react/src/App.tsx index 68abc8a4..2a9e0ad2 100644 --- a/electron-react/src/App.tsx +++ b/electron-react/src/App.tsx @@ -4,6 +4,19 @@ import { useState } from 'react' function App() { const [counter, setCounter] = useState(0) + function showNotification( + title = 'Hello', + body = 'Hello, world!', + silent = false, + ) { + // new window.Notification(title, { + // body: body, + // silent, + // }) + // new Notification({ title, body, silent }).show() + new window.Notification(title, { body: body, silent }) + } + window.electronAPI.onUpdateCounter((value: number) => { setCounter(counter + value) }) @@ -13,6 +26,12 @@ function App() { window.electronAPI.onMenuSetFolderOuput((value: string) => { window.electronAPI.handleSetFolderOuput() }) + window.electronAPI.doNotification( + (title: string, body: string, silent: boolean) => { + showNotification(title, body, silent) + console.log(title, body, silent) + }, + ) return (
@@ -24,6 +43,13 @@ function App() {
IPC + +

Click it to see the effect in this interface.

Go to the top left menu bar to update counter! (main to renderer)
diff --git a/electron-react/src/interface.d.ts b/electron-react/src/interface.d.ts index 70168b57..169ca1f0 100644 --- a/electron-react/src/interface.d.ts +++ b/electron-react/src/interface.d.ts @@ -12,6 +12,10 @@ export interface IElectronAPI { onMenuInstallPuppeteerBrowser: (callback: (value: string) => void) => void onMenuSetFolderOuput: (callback: (value: string) => void) => void onUpdateCounter: (callback: (value: number) => void) => void + doNotification: ( + callback: (title: string, body: string, silent: boolean) => void, + ) => void + notificationApi: { sendNotification: (message: string) => void } } declare global { diff --git a/electron-react/src/main.ts b/electron-react/src/main.ts index 7c1dbc48..7b3801b6 100644 --- a/electron-react/src/main.ts +++ b/electron-react/src/main.ts @@ -12,7 +12,6 @@ import { executablePath, default as puppeteer } from 'puppeteer' import { spawn } from 'child_process' import settings from 'electron-settings' import { IpcMainEvent } from 'electron/main' -import os from 'os' import path from 'path' import { updateElectronApp } from 'update-electron-app' @@ -20,19 +19,20 @@ console.log('File used for Persisting Data - ' + settings.file()) function welcomeNotification() { if (Notification.isSupported()) { - const initNotif = new Notification() - initNotif.title = 'Ecoindex App is started!' - initNotif.body = 'Hello 👋' - initNotif.silent = true - initNotif.show() + showNotification('Ecoindex App is started!', 'Hello 👋', true) } } -function showNotification(title = 'Hello', body = 'Hello, world!') { - const startNotif = new Notification() - startNotif.title = title - startNotif.body = body - startNotif.show() +function showNotification( + title = 'Hello', + body = 'Hello, world!', + silent = false, +) { + // new window.Notification(title, { + // body: body, + // silent, + // }) + new Notification({ title, body, silent }).show() } // Handle creating/removing shortcuts on Windows when installing/uninstalling. @@ -46,7 +46,7 @@ function handleSetTitle(event: IpcMainEvent, title: string) { win.setTitle(title) } -async function handleFolderOuputSelector() { +async function handleFolderOuputSelector(event: IpcMainEvent) { const { canceled, filePaths } = await dialog.showOpenDialog({ properties: ['openDirectory'], }) @@ -54,15 +54,15 @@ async function handleFolderOuputSelector() { return filePaths[0] } } -async function handleInstallPuppeteerBrowser() { - async function checkPuppeteerBrowserVersion(version: string) { - console.log('targetVersion', version) +async function handleInstallPuppeteerBrowser(event: IpcMainEvent) { + console.log('handleInstallPuppeteerBrowser') - console.log('defaultPath', executablePath()) + async function checkPuppeteerBrowserVersion(version: string) { const path = executablePath().replace( /(\d+\.)(\d+\.)(\d+\.)(\d+)/gm, versionToCheck, ) + console.log('defaultPath', executablePath()) console.log('newPath', path) const browser = await puppeteer.launch({ @@ -72,7 +72,6 @@ async function handleInstallPuppeteerBrowser() { }) const installedVersion = await browser.version() - console.log('installedVersion', installedVersion) await browser.close() @@ -92,13 +91,13 @@ async function handleInstallPuppeteerBrowser() { return } - console.log('installPuppeteerBrowser') showNotification( 'Puppeteer browser installation started...', 'This process may take a few minutes', ) const ls = spawn('npx', [ + ' --yes', 'puppeteer', 'browsers', 'install', @@ -117,13 +116,19 @@ async function handleInstallPuppeteerBrowser() { }) } -async function handleLaunchEcoindexSimpleCollect() { +async function handleLaunchEcoindexSimpleCollect(event: IpcMainEvent) { + console.log('handleLaunchEcoindexSimpleCollect') showNotification( 'Collect Ecoindex is started...', 'This process may take a few minutes', ) - return - const ls = spawn('npx', ['lighthouse-plugin-ecoindex', 'collect', '-d']) + // return + const ls = spawn('npx', [ + '--yes', + 'lighthouse-plugin-ecoindex', + 'collect', + '-d', + ]) ls.stdout.on('data', function (data) { console.log(data.toString()) }) @@ -144,6 +149,7 @@ const createWindow = () => { height: 600, webPreferences: { nodeIntegration: true, + contextIsolation: true, preload: path.join(__dirname, 'preload.js'), }, }) @@ -203,6 +209,10 @@ const createWindow = () => { // initialization and is ready to create browser windows. // Some APIs can only be used after this event occurs. app.whenReady().then(() => { + ipcMain.on('notify', (_event, message) => { + new Notification({ title: 'Notification', body: message }).show() + // showNotification('Notification', message) + }) ipcMain.on('set-title', handleSetTitle) ipcMain.handle('handleInstallPuppeteerBrowser', handleInstallPuppeteerBrowser) ipcMain.handle( diff --git a/electron-react/src/preload.ts b/electron-react/src/preload.ts index 3f1b47c8..7a4ce6e4 100644 --- a/electron-react/src/preload.ts +++ b/electron-react/src/preload.ts @@ -7,6 +7,13 @@ contextBridge.exposeInMainWorld('versions', { }) contextBridge.exposeInMainWorld('electronAPI', { + // to test + notificationApi: { + sendNotification(message: string) { + console.log(message) + ipcRenderer.send('notify', message) + }, + }, setTitle: (title: string) => ipcRenderer.send('set-title', title), handleSetFolderOuput: () => ipcRenderer.invoke('dialog:handleSetFolderOuput'), handleLaunchEcoindexSimpleCollect: () => @@ -17,6 +24,10 @@ contextBridge.exposeInMainWorld('electronAPI', { ipcRenderer.on('menu-install-puppeteer-browser', (_event, value: string) => callback(value), ), + doNotification: (callback: (value: string) => void) => + ipcRenderer.on('menu-install-puppeteer-browser', (_event, value: string) => + callback(value), + ), onMenuSetFolderOuput: (callback: (value: string) => void) => ipcRenderer.on('menu-set-folder-output', (_event, value: string) => callback(value), diff --git a/electron-react/src/renderer.tsx b/electron-react/src/renderer.tsx index 4b906b1f..a5f6c41b 100644 --- a/electron-react/src/renderer.tsx +++ b/electron-react/src/renderer.tsx @@ -1,10 +1,11 @@ -import "./index.css"; -import App from "./App"; -import React from "react"; -import ReactDOM from "react-dom/client"; +import './index.css' -ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( +import React from 'react' +import ReactDOM from 'react-dom/client' +import App from './App' + +ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( , -); +)