From 7dc1cc048eb7d78c66569199e257e9e9e0bc4856 Mon Sep 17 00:00:00 2001 From: Amit Haridas Date: Sun, 26 Oct 2025 14:36:05 +0530 Subject: [PATCH] =?UTF-8?q?FINAL=20FIX:=20Proper=20print=20preview=20and?= =?UTF-8?q?=20file=20loading=20with=20correct=20DOM=20timing=20Print=20Pre?= =?UTF-8?q?view=20-=20FIXED:=20-=20Eliminated=20race=20condition:=20render?= =?UTF-8?q?er=20now=20waits=20for=20DOM=20to=20render=20before=20telling?= =?UTF-8?q?=20main=20to=20print=20-=20Uses=20double=20requestAnimationFram?= =?UTF-8?q?e=20to=20ensure=20browser=20has=20repainted=20-=20Main=20proces?= =?UTF-8?q?s=20only=20waits=2050ms=20(DOM=20already=20rendered=20by=20rend?= =?UTF-8?q?erer)=20-=20Renderer=20hides=20UI=20elements,=20applies=20print?= =?UTF-8?q?-mode=20class,=20THEN=20signals=20main=20to=20print=20-=20This?= =?UTF-8?q?=20ensures=20print=20dialog=20captures=20the=20properly=20rende?= =?UTF-8?q?red=20preview,=20not=20toolbar=20File=20Loading=20-=20FIXED:=20?= =?UTF-8?q?-=20Fixed=20critical=20bug=20in=20openFile():=20updatePreview?= =?UTF-8?q?=20was=20called=20BEFORE=20editor=20value=20was=20set=20-=20Whe?= =?UTF-8?q?n=20reusing=20current=20tab,=20preview=20now=20updates=20AFTER?= =?UTF-8?q?=20editor=20content=20is=20loaded=20-=20Ensures=20preview=20alw?= =?UTF-8?q?ays=20has=20content=20to=20render=20-=20Both=20tab=20reuse=20an?= =?UTF-8?q?d=20new=20tab=20creation=20now=20properly=20update=20preview=20?= =?UTF-8?q?Technical=20Details:=20Print=20flow:=201.=20User=20clicks=20Pri?= =?UTF-8?q?nt=20Preview=202.=20Menu=20sends=20'print-preview'=20to=20rende?= =?UTF-8?q?rer=203.=20Renderer:=20hide=20UI,=20set=20print-mode=20class=20?= =?UTF-8?q?4.=20Renderer:=20requestAnimationFrame=20x2=20(waits=20for=20re?= =?UTF-8?q?paints)=205.=20Renderer:=20sends=20'do-print'=20to=20main=20(DO?= =?UTF-8?q?M=20fully=20rendered)=206.=20Main:=20small=2050ms=20delay,=20th?= =?UTF-8?q?en=20prints=207.=20Result:=20prints=20preview=20content,=20not?= =?UTF-8?q?=20toolbar!=20File=20loading=20flow:=201.=20User=20double-click?= =?UTF-8?q?s=20.md=20file=20(or=20file=20association)=202.=20Main=20proces?= =?UTF-8?q?s=20stores=20file=20path=203.=20Renderer=20signals=20ready=20af?= =?UTF-8?q?ter=20theme=20loads=204.=20Main=20sends=20file-opened=20message?= =?UTF-8?q?=205.=20Renderer=20openFile()=20called=206.=20Editor=20value=20?= =?UTF-8?q?set=207.=20THEN=20updatePreview()=20called=20(content=20exists)?= =?UTF-8?q?=208.=20Preview=20renders=20correctly!=20=F0=9F=A4=96=20Generat?= =?UTF-8?q?ed=20with=20[Claude=20Code](https://claude.com/claude-code)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.js | 32 ++++++++---------- src/renderer.js | 88 ++++++++++++++++++++++++------------------------- 2 files changed, 58 insertions(+), 62 deletions(-) diff --git a/src/main.js b/src/main.js index 9ad7349..038543a 100644 --- a/src/main.js +++ b/src/main.js @@ -1166,37 +1166,33 @@ ipcMain.on('set-current-file', (event, filePath) => { currentFile = filePath; }); -// Handle print preview +// Handle print preview - send signal to renderer to prepare ipcMain.on('print-preview', (event) => { if (mainWindow) { - // Prepare for printing preview only (black text, no colors) - mainWindow.webContents.send('prepare-print-preview', false); - // Give renderer time to prepare, then print - setTimeout(() => { - mainWindow.webContents.print({ - silent: false, - printBackground: false, - color: true, - margin: { marginType: 'default' } - }); - }, 100); + mainWindow.webContents.send('print-preview'); } }); -// Handle print preview with styles +// Handle print preview with styles - send signal to renderer to prepare ipcMain.on('print-preview-styled', (event) => { if (mainWindow) { - // Prepare for printing preview with colors - mainWindow.webContents.send('prepare-print-preview', true); - // Give renderer time to prepare, then print + mainWindow.webContents.send('print-preview-styled'); + } +}); + +// Handle actual printing when renderer is ready +ipcMain.on('do-print', (event, { withStyles }) => { + if (mainWindow) { + // Renderer has already hidden UI and prepared the page + // Small delay to ensure everything is rendered setTimeout(() => { mainWindow.webContents.print({ silent: false, - printBackground: true, + printBackground: withStyles, color: true, margin: { marginType: 'default' } }); - }, 100); + }, 50); } }); diff --git a/src/renderer.js b/src/renderer.js index b29e20c..3f54908 100644 --- a/src/renderer.js +++ b/src/renderer.js @@ -964,10 +964,13 @@ class TabManager { tab.originalContent = content; tab.isDirty = false; - // Update the editor immediately + // Update the editor and preview const editor = document.getElementById(`editor-${this.activeTabId}`); if (editor) { editor.value = content; + // Update preview after editor is updated + this.updatePreview(this.activeTabId); + this.updateWordCount(); } } else { // Create new tab for the file @@ -990,9 +993,6 @@ class TabManager { } }, 50); } - - this.updatePreview(this.activeTabId); - this.updateWordCount(); this.startAutoSave(); this.addToRecentFiles(filePath); this.updateTabBar(); @@ -1152,18 +1152,16 @@ ipcRenderer.on('adjust-font-size', (event, action) => { updateFontSizes(currentFontSize); }); -// Print preview request handlers - relay to main process +// Print preview request handlers - handle printing directly ipcRenderer.on('print-preview', () => { - ipcRenderer.send('print-preview'); + handlePrintPreview(false); }); ipcRenderer.on('print-preview-styled', () => { - ipcRenderer.send('print-preview-styled'); + handlePrintPreview(true); }); -// Print preview handler - prepare for printing -ipcRenderer.on('prepare-print-preview', (event, withStyles) => { - // Get the active tab's preview element +function handlePrintPreview(withStyles) { const activeTabId = tabManager ? tabManager.activeTabId : 1; const previewContent = document.getElementById(`preview-${activeTabId}`); @@ -1172,30 +1170,27 @@ ipcRenderer.on('prepare-print-preview', (event, withStyles) => { return; } - // Hide UI elements except the preview + // Hide UI elements document.getElementById('toolbar').style.display = 'none'; document.getElementById('tab-bar').style.display = 'none'; document.getElementById('status-bar').style.display = 'none'; - // Hide editor panes (not the whole editor-container) const editorPane = document.getElementById(`editor-pane-${activeTabId}`); if (editorPane) { editorPane.style.display = 'none'; } - // Hide all export dialogs and other overlays - const exportDialog = document.getElementById('export-dialog'); - const batchDialog = document.getElementById('batch-dialog'); - const pdfDialog = document.getElementById('pdf-editor-dialog'); - const converterDialog = document.getElementById('converter-dialog'); - const findDialog = document.getElementById('find-dialog'); - if (exportDialog) exportDialog.style.display = 'none'; - if (batchDialog) batchDialog.style.display = 'none'; - if (pdfDialog) pdfDialog.style.display = 'none'; - if (converterDialog) converterDialog.style.display = 'none'; - if (findDialog) findDialog.style.display = 'none'; + // Hide all dialogs + const dialogs = [ + 'export-dialog', 'batch-dialog', 'pdf-editor-dialog', + 'converter-dialog', 'find-dialog' + ]; + dialogs.forEach(id => { + const dialog = document.getElementById(id); + if (dialog) dialog.style.display = 'none'; + }); - // Make preview full screen for printing + // Apply print-mode to preview pane const previewPane = document.getElementById(`preview-pane-${activeTabId}`); if (previewPane) { previewPane.classList.add('print-mode'); @@ -1204,29 +1199,34 @@ ipcRenderer.on('prepare-print-preview', (event, withStyles) => { } } - // Re-show everything after print - setTimeout(() => { - document.getElementById('toolbar').style.display = ''; - document.getElementById('tab-bar').style.display = ''; - document.getElementById('status-bar').style.display = ''; + // Use requestAnimationFrame twice to ensure browser has rendered the DOM changes + requestAnimationFrame(() => { + requestAnimationFrame(() => { + // Now tell main process to print - the DOM is fully rendered + ipcRenderer.send('do-print', { withStyles }); - // Restore editor pane - if (editorPane) { - editorPane.style.display = ''; - } + // Restore UI after print + setTimeout(() => { + document.getElementById('toolbar').style.display = ''; + document.getElementById('tab-bar').style.display = ''; + document.getElementById('status-bar').style.display = ''; - // Restore dialog visibility if they were open - if (exportDialog) exportDialog.style.display = ''; - if (batchDialog) batchDialog.style.display = ''; - if (pdfDialog) pdfDialog.style.display = ''; - if (converterDialog) converterDialog.style.display = ''; - if (findDialog) findDialog.style.display = ''; + if (editorPane) { + editorPane.style.display = ''; + } - if (previewPane) { - previewPane.classList.remove('print-mode', 'print-no-styles'); - } - }, 500); -}); + dialogs.forEach(id => { + const dialog = document.getElementById(id); + if (dialog) dialog.style.display = ''; + }); + + if (previewPane) { + previewPane.classList.remove('print-mode', 'print-no-styles'); + } + }, 100); + }); + }); +} // Export Dialog functionality let currentExportFormat = null;