diff --git a/src/index.html b/src/index.html index 361c66b..bfc2744 100644 --- a/src/index.html +++ b/src/index.html @@ -964,7 +964,7 @@
- +
@@ -992,7 +992,7 @@
- +
diff --git a/src/main.js b/src/main.js index 7b10665..7f41737 100644 --- a/src/main.js +++ b/src/main.js @@ -5,6 +5,15 @@ const { exec } = require('child_process'); const { PDFDocument, rgb, degrees, StandardFonts } = require('pdf-lib'); const WordTemplateExporter = require('./wordTemplateExporter'); +// Add MiKTeX to PATH for LaTeX support +if (process.platform === 'win32') { + const miktexPath = 'C:\\Program Files\\MiKTeX\\miktex\\bin\\x64'; + if (fs.existsSync(miktexPath)) { + process.env.PATH = `${miktexPath};${process.env.PATH}`; + console.log('[MAIN] Added MiKTeX to PATH:', miktexPath); + } +} + // Get the system Pandoc path function getPandocPath() { // Pandoc is expected to be in the system's PATH. @@ -664,6 +673,52 @@ ipcMain.on('save-header-footer-settings', (event, settings) => { }); // Save header/footer logo image +// Browse for header/footer logo +ipcMain.on('browse-header-footer-logo', async (event, position) => { + try { + const result = await dialog.showOpenDialog(mainWindow, { + title: `Select ${position.charAt(0).toUpperCase() + position.slice(1)} Logo/Image`, + filters: [ + { name: 'Images', extensions: ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'svg', 'webp'] } + ], + properties: ['openFile'] + }); + + if (!result.canceled && result.filePaths.length > 0) { + const filePath = result.filePaths[0]; + + // Copy image to userData directory for persistent storage + const userDataPath = app.getPath('userData'); + const logoDir = path.join(userDataPath, 'logos'); + + // Create logos directory if it doesn't exist + if (!fs.existsSync(logoDir)) { + fs.mkdirSync(logoDir, { recursive: true }); + } + + // Generate unique filename + const ext = path.extname(filePath); + const filename = `${position}_${Date.now()}${ext}`; + const destPath = path.join(logoDir, filename); + + // Copy file + fs.copyFileSync(filePath, destPath); + + // Update settings + if (position === 'header') { + headerFooterSettings.header.logo = destPath; + } else if (position === 'footer') { + headerFooterSettings.footer.logo = destPath; + } + + event.reply('header-footer-logo-saved', { position, path: destPath }); + } + } catch (error) { + console.error('Logo browse error:', error); + dialog.showErrorBox('Logo Error', `Failed to select logo: ${error.message}`); + } +}); + ipcMain.on('save-header-footer-logo', async (event, { position, filePath }) => { try { if (!filePath) { diff --git a/src/renderer.js b/src/renderer.js index 90abce8..f096dce 100644 --- a/src/renderer.js +++ b/src/renderer.js @@ -2658,23 +2658,9 @@ function saveHeaderFooterSettings() { closeHeaderFooterDialog(); } -// Handle logo file selection -function handleLogoSelection(position) { - const input = document.getElementById(`${position}-logo`); - - if (input.files && input.files[0]) { - const file = input.files[0]; - // Use webUtils to get the real file path in Electron - const filePath = file.path || (window.electron && window.electron.webUtils ? window.electron.webUtils.getPathForFile(file) : null); - - if (!filePath) { - alert('Error: Could not get file path. Please try again.'); - return; - } - - // Send to main process to save - ipcRenderer.send('save-header-footer-logo', { position, filePath }); - } +// Handle logo browsing - ask main process to show open dialog +function browseForLogo(position) { + ipcRenderer.send('browse-header-footer-logo', position); } // Handle logo saved confirmation @@ -2685,7 +2671,6 @@ ipcRenderer.on('header-footer-logo-saved', (event, { position, path }) => { // Clear logo function clearLogo(position) { ipcRenderer.send('clear-header-footer-logo', position); - document.getElementById(`${position}-logo`).value = ''; document.getElementById(`${position}-logo-preview`).textContent = ''; } @@ -2728,9 +2713,9 @@ document.querySelectorAll('.field-insert-btn').forEach(btn => { }); }); -// Logo file inputs -document.getElementById('header-logo').addEventListener('change', () => handleLogoSelection('header')); -document.getElementById('footer-logo').addEventListener('change', () => handleLogoSelection('footer')); +// Logo browse buttons +document.getElementById('header-logo-browse').addEventListener('click', () => browseForLogo('header')); +document.getElementById('footer-logo-browse').addEventListener('click', () => browseForLogo('footer')); // Logo clear buttons document.getElementById('header-logo-clear').addEventListener('click', () => clearLogo('header')); diff --git a/src/styles.css b/src/styles.css index b12ef61..a6b7945 100644 --- a/src/styles.css +++ b/src/styles.css @@ -3312,6 +3312,22 @@ body.printing-no-styles .preview-content pre, background: var(--button-hover, #5a6268); } +.browse-btn { + padding: 6px 12px; + background: var(--accent-color, #007bff); + color: white; + border: none; + border-radius: 4px; + cursor: pointer; + font-size: 13px; + transition: background 0.2s ease; + margin-right: 8px; +} + +.browse-btn:hover { + background: var(--accent-hover, #0056b3); +} + .clear-btn { padding: 6px 12px; background: var(--danger-color, #dc3545);