const { app, BrowserWindow, ipcMain, dialog, Menu } = require('electron'); const path = require('path'); let mainWindow; function createWindow() { mainWindow = new BrowserWindow({ width: 1200, height: 800, minWidth: 900, minHeight: 600, webPreferences: { nodeIntegration: false, contextIsolation: true, preload: path.join(__dirname, 'preload.js') }, titleBarStyle: 'hiddenInset', show: false }); mainWindow.loadFile('index.html'); mainWindow.once('ready-to-show', () => { mainWindow.show(); }); mainWindow.on('closed', () => { mainWindow = null; }); // Menu contestuale (tasto destro) mainWindow.webContents.on('context-menu', (event, params) => { const contextMenu = Menu.buildFromTemplate([ { label: 'Taglia', accelerator: 'CmdOrCtrl+X', role: 'cut', enabled: params.editFlags.canCut }, { label: 'Copia', accelerator: 'CmdOrCtrl+C', role: 'copy', enabled: params.editFlags.canCopy }, { label: 'Incolla', accelerator: 'CmdOrCtrl+V', role: 'paste', enabled: params.editFlags.canPaste }, { label: 'Seleziona tutto', accelerator: 'CmdOrCtrl+A', role: 'selectAll', enabled: params.editFlags.canSelectAll }, { type: 'separator' }, { label: 'Elimina', role: 'delete', enabled: params.editFlags.canDelete } ]); contextMenu.popup(mainWindow); }); createMenu(); } function createMenu() { const template = [ { label: 'File', submenu: [ { label: 'Esci', accelerator: 'CmdOrCtrl+Q', click: () => { app.quit(); } } ] }, { label: 'Impostazioni', submenu: [ { label: 'Configura Modello e URL', accelerator: 'CmdOrCtrl+,', click: () => { mainWindow.webContents.send('open-settings'); } } ] }, { label: 'Aiuto', submenu: [ { label: 'Informazioni', click: () => { dialog.showMessageBox(mainWindow, { type: 'info', title: 'Informazioni', message: 'Traduttore AI', detail: 'Applicazione desktop per traduzioni con modelli AI locali tramite Ollama.' }); } } ] } ]; const menu = Menu.buildFromTemplate(template); Menu.setApplicationMenu(menu); } app.whenReady().then(createWindow); app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit(); } }); app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) { createWindow(); } }); ipcMain.handle('translate-text', async (event, { text, direction, model, baseUrl }) => { try { const sourceLang = direction === 'en-it' ? 'inglese' : 'italiano'; const targetLang = direction === 'en-it' ? 'italiano' : 'inglese'; // Usa 127.0.0.1 invece di localhost per evitare problemi IPv6 const cleanBaseUrl = baseUrl.replace('localhost', '127.0.0.1'); const response = await fetch(`${cleanBaseUrl}/api/generate`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ model: model, prompt: `Traduci il seguente testo da ${sourceLang} a ${targetLang}. Rispondi SOLO con la traduzione, senza spiegazioni o commenti aggiuntivi:\n\n${text}`, stream: false }) }); if (!response.ok) { throw new Error(`Errore HTTP: ${response.status}`); } const data = await response.json(); return { success: true, translation: data.response }; } catch (error) { return { success: false, error: error.message }; } }); ipcMain.handle('get-models', async (event, baseUrl) => { try { // Assicurati che l'URL sia pulito e sostituisci localhost con 127.0.0.1 per evitare problemi IPv6 let cleanUrl = baseUrl.trim().replace(/\/$/, ''); cleanUrl = cleanUrl.replace('localhost', '127.0.0.1'); const fullUrl = `${cleanUrl}/api/tags`; console.log('Richiesta modelli da:', fullUrl); const response = await fetch(fullUrl, { method: 'GET', headers: { 'Accept': 'application/json', } }); console.log('Risposta status:', response.status); if (!response.ok) { throw new Error(`Errore HTTP: ${response.status} - ${response.statusText}`); } const data = await response.json(); console.log('Modelli trovati:', data.models?.length || 0); return { success: true, models: data.models || [] }; } catch (error) { console.error('Errore in get-models:', error); return { success: false, error: error.message }; } });