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"