diff --git a/app/page.tsx b/app/page.tsx index 9a44f55..fd52e7b 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -291,7 +291,7 @@ function ScribeContent() { className="bg-background text-text-primary h-screen flex flex-col items-center justify-center font-['Lora']">
- ERitors Logo + ERitors Logo
diff --git a/electron/main.ts b/electron/main.ts index bca4761..ba0461b 100644 --- a/electron/main.ts +++ b/electron/main.ts @@ -1,14 +1,30 @@ -import { app, BrowserWindow, ipcMain } from 'electron'; +import { app, BrowserWindow, ipcMain, nativeImage, protocol } from 'electron'; import * as path from 'path'; import * as url from 'url'; import { fileURLToPath } from 'url'; import Store from 'electron-store'; +import * as fs from 'fs'; // Fix pour __dirname en ES modules const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); -const isDev = process.env.NODE_ENV === 'development'; +const isDev = !app.isPackaged; + +// Enregistrer le protocole app:// comme standard (avant app.whenReady) +if (!isDev) { + protocol.registerSchemesAsPrivileged([ + { + scheme: 'app', + privileges: { + standard: true, + secure: true, + supportFetchAPI: true, + corsEnabled: true + } + } + ]); +} // Définir le nom de l'application app.setName('ERitors Scribe'); @@ -21,7 +37,9 @@ const preloadPath = isDev // Icône de l'application const iconPath = isDev ? path.join(__dirname, '../build/icon.png') - : path.join(__dirname, '../build/icon.png'); + : process.platform === 'darwin' + ? path.join(process.resourcesPath, 'icon.icns') // macOS utilise .icns + : path.join(process.resourcesPath, 'app.asar/build/icon.png'); // Windows/Linux utilisent .png // Store sécurisé pour le token const store = new Store({ @@ -36,7 +54,8 @@ function createLoginWindow(): void { width: 500, height: 900, resizable: false, - icon: iconPath, + // Ne pas définir icon sur macOS - utilise l'icône de l'app bundle + ...(process.platform !== 'darwin' && { icon: iconPath }), webPreferences: { preload: preloadPath, contextIsolation: true, @@ -52,13 +71,7 @@ function createLoginWindow(): void { loginWindow.loadURL(`http://localhost:${devPort}/login/login`); loginWindow.webContents.openDevTools(); } else { - loginWindow.loadURL( - url.format({ - pathname: path.join(__dirname, '../out/login/login/index.html'), - protocol: 'file:', - slashes: true, - }) - ); + loginWindow.loadURL('app://./login/login/index.html'); } loginWindow.once('ready-to-show', () => { @@ -74,7 +87,8 @@ function createMainWindow(): void { mainWindow = new BrowserWindow({ width: 1200, height: 800, - icon: iconPath, + // Ne pas définir icon sur macOS - utilise l'icône de l'app bundle + ...(process.platform !== 'darwin' && { icon: iconPath }), webPreferences: { preload: preloadPath, contextIsolation: true, @@ -89,13 +103,7 @@ function createMainWindow(): void { mainWindow.loadURL(`http://localhost:${devPort}`); mainWindow.webContents.openDevTools(); } else { - mainWindow.loadURL( - url.format({ - pathname: path.join(__dirname, '../out/index.html'), - protocol: 'file:', - slashes: true, - }) - ); + mainWindow.loadURL('app://./index.html'); } mainWindow.once('ready-to-show', () => { @@ -143,13 +151,61 @@ ipcMain.on('logout', () => { }); app.whenReady().then(() => { + console.log('App ready, isDev:', isDev); + console.log('resourcesPath:', process.resourcesPath); + console.log('isPackaged:', app.isPackaged); + + // Enregistrer le protocole custom app:// pour servir les fichiers depuis out/ + if (!isDev) { + const outPath = path.join(process.resourcesPath, 'app.asar.unpacked/out'); + + protocol.handle('app', async (request) => { + // Enlever app:// et ./ + let filePath = request.url.replace('app://', '').replace(/^\.\//, ''); + const fullPath = path.normalize(path.join(outPath, filePath)); + + // Vérifier que le chemin est bien dans out/ (sécurité) + if (!fullPath.startsWith(outPath)) { + console.error('Security: Attempted to access file outside out/:', fullPath); + return new Response('Forbidden', { status: 403 }); + } + + try { + const data = await fs.promises.readFile(fullPath); + const ext = path.extname(fullPath).toLowerCase(); + const mimeTypes: Record = { + '.html': 'text/html', + '.css': 'text/css', + '.js': 'application/javascript', + '.json': 'application/json', + '.png': 'image/png', + '.jpg': 'image/jpeg', + '.svg': 'image/svg+xml', + '.ico': 'image/x-icon', + '.woff': 'font/woff', + '.woff2': 'font/woff2', + '.ttf': 'font/ttf', + }; + + return new Response(data, { + headers: { 'Content-Type': mimeTypes[ext] || 'application/octet-stream' } + }); + } catch (error) { + console.error('Failed to load:', fullPath, error); + return new Response('Not found', { status: 404 }); + } + }); + } + // Définir l'icône du Dock sur macOS if (process.platform === 'darwin' && app.dock) { - app.dock.setIcon(iconPath); + const icon = nativeImage.createFromPath(iconPath); + app.dock.setIcon(icon); } // Vérifier si un token existe const token = store.get('authToken'); + console.log('Token exists:', !!token); if (token) { // Token existe, ouvrir la fenêtre principale @@ -172,7 +228,6 @@ app.whenReady().then(() => { }); app.on('window-all-closed', () => { - if (process.platform !== 'darwin') { - app.quit(); - } + // Quitter l'application quand toutes les fenêtres sont fermées + app.quit(); }); diff --git a/package.json b/package.json index 20c8d23..e606f3d 100644 --- a/package.json +++ b/package.json @@ -5,17 +5,11 @@ "type": "module", "main": "dist/electron/main.js", "scripts": { - "dev:next": "next dev -p 4000", - "dev:electron": "NODE_ENV=development PORT=4000 electron -r tsx/cjs electron/main.ts", - "dev": "concurrently \"npm run dev:next\" \"wait-on http://localhost:4000 && npm run dev:electron\"", - "build:next": "next build", - "build:electron": "tsc --project tsconfig.electron.json && tsc --project tsconfig.preload.json", - "build": "npm run build:next && npm run build:electron", - "start": "electron .", - "package": "npm run build && electron-builder build --mac --win --linux", - "package:mac": "npm run build && electron-builder build --mac", - "package:win": "npm run build && electron-builder build --win", - "package:linux": "npm run build && electron-builder build --linux" + "dev": "concurrently \"next dev -p 4000\" \"wait-on http://localhost:4000 && electron -r tsx/cjs electron/main.ts\"", + "build:mac": "next build && tsc --project tsconfig.electron.json && tsc --project tsconfig.preload.json && electron-builder build --mac", + "build:win": "next build && tsc --project tsconfig.electron.json && tsc --project tsconfig.preload.json && electron-builder build --win", + "build:linux": "next build && tsc --project tsconfig.electron.json && tsc --project tsconfig.preload.json && electron-builder build --linux", + "build:all": "next build && tsc --project tsconfig.electron.json && tsc --project tsconfig.preload.json && electron-builder build --mac --win --linux" }, "keywords": [], "author": "", @@ -71,17 +65,22 @@ "tailwindcss": "^4.1.17" }, "build": { - "appId": "com.eritorsscribe.app", - "productName": "EritorsScribe", + "appId": "com.eritors.scribe.desktop", + "productName": "ERitors Scribe", "files": [ "dist/**/*", "out/**/*", + "build/**/*", "package.json" ], + "asarUnpack": [ + "out/**/*" + ], "directories": { "output": "release" }, "mac": { + "icon": "build/icons/mac/icon.icns", "target": [ "dmg", "zip" @@ -93,6 +92,7 @@ "entitlementsInherit": "build/entitlements.mac.plist" }, "win": { + "icon": "build/icons/win/icon.ico", "target": [ { "target": "nsis", @@ -104,6 +104,7 @@ ] }, "linux": { + "icon": "build/icons/png", "target": [ "AppImage", "deb"