mirror of
https://github.com/amitwh/markdown-converter.git
synced 2026-08-02 18:10:18 +05:30
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:
+14
-18
@@ -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
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user