fix(v1.0.3): fix startup window display, single instance lock, relative assets and obj packaging

This commit is contained in:
Michael committed 2026-05-21 19:17:07 +02:00
1 parent 47fb80602f
commit af479df65a
7 files changed
+58 -4

No files matched your search

View File
File renamed without changes.
+28
View File
@@ -3,8 +3,26 @@ const path = require('path');
const fs = require('fs'); const fs = require('fs');
const os = require('os'); const os = require('os');
// Autoriser le chargement de fichiers locaux via fetch sous le protocole file://
app.commandLine.appendSwitch('disable-web-security');
app.commandLine.appendSwitch('allow-file-access-from-files');
let mainWindow; let mainWindow;
// ── Single Instance Lock ───────────────────────────────────────────────────
const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) {
app.quit();
process.exit(0);
}
app.on('second-instance', () => {
if (mainWindow) {
if (mainWindow.isMinimized()) mainWindow.restore();
mainWindow.focus();
}
});
// ── Logging Setup ─────────────────────────────────────────────────────────── // ── Logging Setup ───────────────────────────────────────────────────────────
function getLogPath() { function getLogPath() {
const userDataDir = app.getPath('userData'); const userDataDir = app.getPath('userData');
@@ -207,6 +225,7 @@ function createWindow() {
transparent: true, // Permet la transparence (fond de fenêtre transparent) transparent: true, // Permet la transparence (fond de fenêtre transparent)
backgroundColor: '#00000000', // Fond transparent backgroundColor: '#00000000', // Fond transparent
hasShadow: true, hasShadow: true,
show: false, // Cache la fenêtre au démarrage pour éviter les problèmes visuels de DWM
webPreferences: { webPreferences: {
preload: path.join(__dirname, 'preload.js'), preload: path.join(__dirname, 'preload.js'),
contextIsolation: true, // Sécurité Zero Trust active contextIsolation: true, // Sécurité Zero Trust active
@@ -216,6 +235,15 @@ function createWindow() {
}, },
}); });
mainWindow.once('ready-to-show', () => {
// Petit délai de sécurité (80ms) pour garantir la synchronisation DWM sous Windows
setTimeout(() => {
if (mainWindow && !mainWindow.isDestroyed()) {
mainWindow.show();
}
}, 80);
});
loadApp().catch((error) => { loadApp().catch((error) => {
console.error("Echec du chargement de l'application.", error); console.error("Echec du chargement de l'application.", error);
loadFallbackPage("Une erreur inattendue a interrompu le chargement de l'interface."); loadFallbackPage("Une erreur inattendue a interrompu le chargement de l'interface.");
+1
View File
@@ -15,6 +15,7 @@
"appId": "com.romik3.eveflow", "appId": "com.romik3.eveflow",
"productName": "EveFlow", "productName": "EveFlow",
"copyright": "Copyright © 2026 R0m1k3", "copyright": "Copyright © 2026 R0m1k3",
"asar": false,
"directories": { "directories": {
"output": "out" "output": "out"
}, },
File renamed without changes.
+17
View File
@@ -0,0 +1,17 @@
const fs = require('fs');
const path = require('path');
const paths = [
path.join(__dirname, 'public', 'Eve', 'EVE.obj'),
path.join(__dirname, 'Eve', 'EVE.obj')
];
paths.forEach(p => {
const newPath = p + '.bin';
if (fs.existsSync(p)) {
fs.renameSync(p, newPath);
console.log(`Renamed: ${p} -> ${newPath}`);
} else {
console.log(`Not found: ${p}`);
}
});
+11 -3
View File
@@ -13,7 +13,7 @@ interface AvatarModelLoaderProps {
type AvatarManifest = Partial<Record<Exclude<EveAvatar, 'eve'>, string | null>>; type AvatarManifest = Partial<Record<Exclude<EveAvatar, 'eve'>, string | null>>;
const AVATAR_MANIFEST_PATH = '/avatars/avatar-manifest.json'; const AVATAR_MANIFEST_PATH = './avatars/avatar-manifest.json';
const LoadedGlbAvatar: React.FC<{ const LoadedGlbAvatar: React.FC<{
path: string; path: string;
@@ -81,8 +81,16 @@ export const AvatarModelLoader: React.FC<AvatarModelLoaderProps> = ({ avatarId,
}) })
.then((manifest) => { .then((manifest) => {
if (cancelled || !manifest) return; if (cancelled || !manifest) return;
const nextAssetPath = manifest[avatarId]; let nextAssetPath = manifest[avatarId];
setAssetPath(typeof nextAssetPath === 'string' && nextAssetPath.trim() ? nextAssetPath : null); if (typeof nextAssetPath === 'string' && nextAssetPath.trim()) {
// Si le chemin commence par un slash, on le rend relatif pour fonctionner sous le protocole file:// en production
if (nextAssetPath.startsWith('/')) {
nextAssetPath = '.' + nextAssetPath;
}
setAssetPath(nextAssetPath);
} else {
setAssetPath(null);
}
}) })
.catch(() => { .catch(() => {
if (!cancelled) setAssetPath(null); if (!cancelled) setAssetPath(null);
+1 -1
View File
@@ -269,7 +269,7 @@ export const EveModel: React.FC<EveModelProps> = ({ emotion, isSpeaking, avatarI
// Charger les matériaux et le modèle OBJ depuis le répertoire public // Charger les matériaux et le modèle OBJ depuis le répertoire public
const materials = useLoader(MTLLoader, './Eve/EVE.mtl'); const materials = useLoader(MTLLoader, './Eve/EVE.mtl');
const obj = useLoader(OBJLoader, './Eve/EVE.obj', (loader) => { const obj = useLoader(OBJLoader, './Eve/EVE.obj.bin', (loader) => {
materials.preload(); materials.preload();
loader.setMaterials(materials); loader.setMaterials(materials);
}); });