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);