FINAL FIX: Proper print preview and file loading with correct DOM timing

Print Preview - FIXED:
- Eliminated race condition: renderer now waits for DOM to render before telling main to print
- Uses double requestAnimationFrame to ensure browser has repainted
- Main process only waits 50ms (DOM already rendered by renderer)
- Renderer hides UI elements, applies print-mode class, THEN signals main to print
- This ensures print dialog captures the properly rendered preview, not toolbar

File Loading - FIXED:
- Fixed critical bug in openFile(): updatePreview was called BEFORE editor value was set
- When reusing current tab, preview now updates AFTER editor content is loaded
- Ensures preview always has content to render
- Both tab reuse and new tab creation now properly update preview

Technical Details:
Print flow:
1. User clicks Print Preview
2. Menu sends 'print-preview' to renderer
3. Renderer: hide UI, set print-mode class
4. Renderer: requestAnimationFrame x2 (waits for repaints)
5. Renderer: sends 'do-print' to main (DOM fully rendered)
6. Main: small 50ms delay, then prints
7. Result: prints preview content, not toolbar!

File loading flow:
1. User double-clicks .md file (or file association)
2. Main process stores file path
3. Renderer signals ready after theme loads
4. Main sends file-opened message
5. Renderer openFile() called
6. Editor value set
7. THEN updatePreview() called (content exists)
8. Preview renders correctly!

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-26 14:36:05 +05:30
co-authored by Claude
parent fefb299e6d
commit c305789428
2 changed files with 58 additions and 62 deletions
+14 -18
View File
@@ -1166,37 +1166,33 @@ ipcMain.on('set-current-file', (event, filePath) => {
currentFile = filePath; currentFile = filePath;
}); });
// Handle print preview // Handle print preview - send signal to renderer to prepare
ipcMain.on('print-preview', (event) => { ipcMain.on('print-preview', (event) => {
if (mainWindow) { if (mainWindow) {
// Prepare for printing preview only (black text, no colors) mainWindow.webContents.send('print-preview');
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);
} }
}); });
// Handle print preview with styles // Handle print preview with styles - send signal to renderer to prepare
ipcMain.on('print-preview-styled', (event) => { ipcMain.on('print-preview-styled', (event) => {
if (mainWindow) { if (mainWindow) {
// Prepare for printing preview with colors mainWindow.webContents.send('print-preview-styled');
mainWindow.webContents.send('prepare-print-preview', true); }
// Give renderer time to prepare, then print });
// 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(() => { setTimeout(() => {
mainWindow.webContents.print({ mainWindow.webContents.print({
silent: false, silent: false,
printBackground: true, printBackground: withStyles,
color: true, color: true,
margin: { marginType: 'default' } margin: { marginType: 'default' }
}); });
}, 100); }, 50);
} }
}); });
+34 -34
View File
@@ -964,10 +964,13 @@ class TabManager {
tab.originalContent = content; tab.originalContent = content;
tab.isDirty = false; tab.isDirty = false;
// Update the editor immediately // Update the editor and preview
const editor = document.getElementById(`editor-${this.activeTabId}`); const editor = document.getElementById(`editor-${this.activeTabId}`);
if (editor) { if (editor) {
editor.value = content; editor.value = content;
// Update preview after editor is updated
this.updatePreview(this.activeTabId);
this.updateWordCount();
} }
} else { } else {
// Create new tab for the file // Create new tab for the file
@@ -990,9 +993,6 @@ class TabManager {
} }
}, 50); }, 50);
} }
this.updatePreview(this.activeTabId);
this.updateWordCount();
this.startAutoSave(); this.startAutoSave();
this.addToRecentFiles(filePath); this.addToRecentFiles(filePath);
this.updateTabBar(); this.updateTabBar();
@@ -1152,18 +1152,16 @@ ipcRenderer.on('adjust-font-size', (event, action) => {
updateFontSizes(currentFontSize); updateFontSizes(currentFontSize);
}); });
// Print preview request handlers - relay to main process // Print preview request handlers - handle printing directly
ipcRenderer.on('print-preview', () => { ipcRenderer.on('print-preview', () => {
ipcRenderer.send('print-preview'); handlePrintPreview(false);
}); });
ipcRenderer.on('print-preview-styled', () => { ipcRenderer.on('print-preview-styled', () => {
ipcRenderer.send('print-preview-styled'); handlePrintPreview(true);
}); });
// Print preview handler - prepare for printing function handlePrintPreview(withStyles) {
ipcRenderer.on('prepare-print-preview', (event, withStyles) => {
// Get the active tab's preview element
const activeTabId = tabManager ? tabManager.activeTabId : 1; const activeTabId = tabManager ? tabManager.activeTabId : 1;
const previewContent = document.getElementById(`preview-${activeTabId}`); const previewContent = document.getElementById(`preview-${activeTabId}`);
@@ -1172,30 +1170,27 @@ ipcRenderer.on('prepare-print-preview', (event, withStyles) => {
return; return;
} }
// Hide UI elements except the preview // Hide UI elements
document.getElementById('toolbar').style.display = 'none'; document.getElementById('toolbar').style.display = 'none';
document.getElementById('tab-bar').style.display = 'none'; document.getElementById('tab-bar').style.display = 'none';
document.getElementById('status-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}`); const editorPane = document.getElementById(`editor-pane-${activeTabId}`);
if (editorPane) { if (editorPane) {
editorPane.style.display = 'none'; editorPane.style.display = 'none';
} }
// Hide all export dialogs and other overlays // Hide all dialogs
const exportDialog = document.getElementById('export-dialog'); const dialogs = [
const batchDialog = document.getElementById('batch-dialog'); 'export-dialog', 'batch-dialog', 'pdf-editor-dialog',
const pdfDialog = document.getElementById('pdf-editor-dialog'); 'converter-dialog', 'find-dialog'
const converterDialog = document.getElementById('converter-dialog'); ];
const findDialog = document.getElementById('find-dialog'); dialogs.forEach(id => {
if (exportDialog) exportDialog.style.display = 'none'; const dialog = document.getElementById(id);
if (batchDialog) batchDialog.style.display = 'none'; if (dialog) dialog.style.display = 'none';
if (pdfDialog) pdfDialog.style.display = 'none'; });
if (converterDialog) converterDialog.style.display = 'none';
if (findDialog) findDialog.style.display = 'none';
// Make preview full screen for printing // Apply print-mode to preview pane
const previewPane = document.getElementById(`preview-pane-${activeTabId}`); const previewPane = document.getElementById(`preview-pane-${activeTabId}`);
if (previewPane) { if (previewPane) {
previewPane.classList.add('print-mode'); previewPane.classList.add('print-mode');
@@ -1204,29 +1199,34 @@ ipcRenderer.on('prepare-print-preview', (event, withStyles) => {
} }
} }
// Re-show everything after print // 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 UI after print
setTimeout(() => { setTimeout(() => {
document.getElementById('toolbar').style.display = ''; document.getElementById('toolbar').style.display = '';
document.getElementById('tab-bar').style.display = ''; document.getElementById('tab-bar').style.display = '';
document.getElementById('status-bar').style.display = ''; document.getElementById('status-bar').style.display = '';
// Restore editor pane
if (editorPane) { if (editorPane) {
editorPane.style.display = ''; editorPane.style.display = '';
} }
// Restore dialog visibility if they were open dialogs.forEach(id => {
if (exportDialog) exportDialog.style.display = ''; const dialog = document.getElementById(id);
if (batchDialog) batchDialog.style.display = ''; if (dialog) dialog.style.display = '';
if (pdfDialog) pdfDialog.style.display = ''; });
if (converterDialog) converterDialog.style.display = '';
if (findDialog) findDialog.style.display = '';
if (previewPane) { if (previewPane) {
previewPane.classList.remove('print-mode', 'print-no-styles'); previewPane.classList.remove('print-mode', 'print-no-styles');
} }
}, 500); }, 100);
}); });
});
}
// Export Dialog functionality // Export Dialog functionality
let currentExportFormat = null; let currentExportFormat = null;