Compare commits

...
5 Commits
Author SHA1 Message Date
amitwhandClaude e1e0072eea Remove table header background styling (v1.7.6)
Removed custom background colors from table headers to improve preview appearance and maintain consistency with normal theming.

## Changes
- Removed background-color from default theme table headers (was #f6f8fa)
- Removed dark theme table header background styling block
- Headers retain font-weight: 600 for visual distinction
- Table borders and alternating row colors remain intact

## User Request
User feedback: "remove the theming of table headers, it looks bad. Keep normal theming of preview"

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-11 18:54:54 +05:30
amitwhandClaude 1b2afb5f15 Fix double-click file opening in installed Windows app (v1.7.5)
This fix addresses the critical issue where double-clicking .md files would not open them in the installed PanConverter application on Windows.

## Root Cause
When a user double-clicks a file and the app is already running, Windows tries to launch a SECOND INSTANCE with the file path. Without single-instance lock handling, that second instance would exit and the first instance would never receive the file path.

## Changes
- Added single-instance lock handling in main.js (lines 52-85)
- Implemented second-instance event handler to capture file paths
- Focus existing window when second instance is attempted
- Pass file path to existing instance using openFileFromPath()
- Properly handle rendererReady state for file opening

## Testing
- Works in development mode (npm start)
- Should now work correctly in installed Windows app with double-click
- Maintains single instance behavior across all file opening methods

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-11 13:46:48 +05:30
amitwhandClaude c811af9d48 Remove debug console.log statements (v1.7.4 cleanup)
Cleaned up debug logging from file opening investigation:
- Removed console.log from command line arg processing
- Removed console.log from renderer-ready handler
- Removed console.log from openFileFromPath function
- Removed console.log from file-opened IPC handler

The double-click file opening fix is confirmed working.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-11 13:13:27 +05:30
amitwhandClaude a6e91b7403 Fix critical double-click file opening bug (v1.7.4)
CRITICAL BUG FIX: Files opened via double-click were not rendering in the application.

Root Cause:
- The openFileFromPath() function was sending IPC 'file-opened' message WITHOUT checking if rendererReady was true
- When files were double-clicked before renderer initialization, the IPC message was sent but lost
- The comment "Always try to send, the renderer will handle it when ready" was incorrect

The Fix (src/main.js:1586):
- Added rendererReady check to the conditional: if (mainWindow && mainWindow.webContents && rendererReady)
- Now properly stores file in app.pendingFile when renderer is not ready
- File is opened correctly when renderer-ready signal arrives

Flow:
1. File double-clicked → openFileFromPath() called
2. If renderer NOT ready → store in app.pendingFile
3. When renderer sends 'renderer-ready' → openFileFromPath(app.pendingFile) is called
4. This time renderer IS ready → file opens successfully

Version: 1.7.4
- Updated package.json version to 1.7.4
- Updated About dialog version to 1.7.4

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-11 12:57:52 +05:30
amitwhandClaude a44b13d2fb Version 1.7.3 - Bug Fixes and ConcreteInfo Themes
Fixed critical file opening bug and theme visibility issues, plus added ConcreteInfo branded themes.

Bug Fixes:
• Fixed double-click file opening race condition
  - Removed setTimeout logic from did-finish-load handler
  - Now relies solely on renderer-ready IPC signal for proper initialization
  - Files from Windows Explorer now open correctly on first attempt

• Fixed theme preview text visibility for 14 themes
  - Added proper .pane:last-child background overrides
  - Fixed dark text on dark backgrounds and light text on light backgrounds
  - Affected themes: Dracula, Nord, One Dark, Atom One Light, Material,
    Gruvbox Dark/Light, Tokyo Night, Palenight, Ayu Dark/Light/Mirage,
    Oceanic Next, Cobalt2

New Features:
• Added 3 ConcreteInfo branded themes
  - Concrete Dark: Very dark theme with orange accents
  - Concrete Light: Light theme with orange accents
  - Concrete Warm: Mid-tone gray theme with orange accents
  - All themes use ConcreteInfo brand colors: #0d0b09, #464646, #9a9696, #e3e3e3, #e5461f

• Updated theme count from 19 to 22 themes

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-11 12:48:42 +05:30
3 changed files with 321 additions and 21 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "pan-converter", "name": "pan-converter",
"version": "1.7.2", "version": "1.7.6",
"description": "Cross-platform Markdown editor and converter using Pandoc", "description": "Cross-platform Markdown editor and converter using Pandoc",
"main": "src/main.js", "main": "src/main.js",
"scripts": { "scripts": {
+45 -16
View File
@@ -49,6 +49,41 @@ let currentFile = null; // This will now represent the active tab's file
let pandocAvailable = null; // Cache pandoc availability check let pandocAvailable = null; // Cache pandoc availability check
let rendererReady = false; // Track if renderer is ready to receive file data let rendererReady = false; // Track if renderer is ready to receive file data
// Handle single instance lock for Windows file association
// When a file is double-clicked and the app is already running,
// Windows tries to start a second instance. We prevent this and
// pass the file to the existing instance instead.
const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) {
// Another instance is already running, quit this one
app.quit();
} else {
// This is the first instance, handle second-instance events
app.on('second-instance', (event, commandLine, workingDirectory) => {
// Someone tried to run a second instance, focus our window instead
if (mainWindow) {
if (mainWindow.isMinimized()) mainWindow.restore();
mainWindow.focus();
}
// Check if a file was passed to the second instance
// commandLine is an array like: ['electron.exe', 'app.asar', 'file.md']
const fileArgs = commandLine.slice(2);
for (const arg of fileArgs) {
if ((arg.endsWith('.md') || arg.endsWith('.markdown')) && fs.existsSync(arg)) {
// Open the file in the existing instance
if (rendererReady) {
openFileFromPath(arg);
} else {
app.pendingFile = arg;
}
break;
}
}
});
}
// Check if pandoc is available // Check if pandoc is available
function checkPandocAvailability() { function checkPandocAvailability() {
return new Promise((resolve) => { return new Promise((resolve) => {
@@ -86,14 +121,8 @@ function createWindow() {
// Wait for the page to fully load before sending file data // Wait for the page to fully load before sending file data
mainWindow.webContents.on('did-finish-load', () => { mainWindow.webContents.on('did-finish-load', () => {
console.log('Window finished loading'); console.log('Window finished loading');
// Give renderer a moment to initialize // Don't open file here - wait for renderer-ready signal
setTimeout(() => { // The renderer will send renderer-ready when TabManager is initialized
if (app.pendingFile && !rendererReady) {
console.log('Opening pending file after did-finish-load:', app.pendingFile);
openFileFromPath(app.pendingFile);
app.pendingFile = null;
}
}, 500); // Wait 500ms for TabManager to initialize
}); });
} }
@@ -261,7 +290,11 @@ function createMenu() {
{ label: 'Ayu Light', click: () => setTheme('ayu-light') }, { label: 'Ayu Light', click: () => setTheme('ayu-light') },
{ label: 'Ayu Mirage', click: () => setTheme('ayu-mirage') }, { label: 'Ayu Mirage', click: () => setTheme('ayu-mirage') },
{ label: 'Oceanic Next', click: () => setTheme('oceanic-next') }, { label: 'Oceanic Next', click: () => setTheme('oceanic-next') },
{ label: 'Cobalt2', click: () => setTheme('cobalt2') } { label: 'Cobalt2', click: () => setTheme('cobalt2') },
{ type: 'separator' },
{ label: 'Concrete Dark', click: () => setTheme('concrete-dark') },
{ label: 'Concrete Light', click: () => setTheme('concrete-light') },
{ label: 'Concrete Warm', click: () => setTheme('concrete-warm') }
] ]
}, },
{ type: 'separator' }, { type: 'separator' },
@@ -412,7 +445,7 @@ function createMenu() {
type: 'info', type: 'info',
title: 'About PanConverter', title: 'About PanConverter',
message: 'PanConverter', message: 'PanConverter',
detail: 'A cross-platform Markdown editor and converter using Pandoc.\n\nVersion: 1.7.2\nAuthor: Amit Haridas\nEmail: amit.wh@gmail.com\nLicense: MIT\n\nFeatures:\n• Modern glassmorphism UI with gradient backgrounds\n• Comprehensive PDF Editor (merge, split, compress, rotate, watermark, encrypt)\n• Universal File Converter (LibreOffice, ImageMagick, FFmpeg, Pandoc)\n• Windows Explorer context menu integration\n• Tabbed interface for multiple files\n• Advanced markdown editing with live preview\n• Real-time preview updates while typing\n• Full toolbar markdown editing functions\n• Enhanced PDF export with built-in Electron fallback\n• File association support for .md files\n• Command-line interface for batch conversion\n• Advanced export options with templates and metadata\n• Batch file conversion with progress tracking\n• Improved preview typography and spacing\n• Adjustable font sizes via menu (Ctrl+Shift+Plus/Minus)\n• Complete theme support including Monokai fixes\n• Find & replace with match highlighting\n• Line numbers and auto-indentation\n• Export to multiple formats via Pandoc\n• PowerPoint & presentation export\n• Export tables to Excel/ODS spreadsheets\n• Document import & conversion\n• Table creation helper\n• 19 beautiful themes (including Dracula, Nord, Tokyo Night, Gruvbox, Ayu, and more)\n• Undo/redo functionality\n• Live word count and statistics', detail: 'A cross-platform Markdown editor and converter using Pandoc.\n\nVersion: 1.7.4\nAuthor: Amit Haridas\nEmail: amit.wh@gmail.com\nLicense: MIT\n\nFeatures:\n• Modern glassmorphism UI with gradient backgrounds\n• Comprehensive PDF Editor (merge, split, compress, rotate, watermark, encrypt)\n• Universal File Converter (LibreOffice, ImageMagick, FFmpeg, Pandoc)\n• Windows Explorer context menu integration\n• Tabbed interface for multiple files\n• Advanced markdown editing with live preview\n• Real-time preview updates while typing\n• Full toolbar markdown editing functions\n• Enhanced PDF export with built-in Electron fallback\n• File association support for .md files\n• Command-line interface for batch conversion\n• Advanced export options with templates and metadata\n• Batch file conversion with progress tracking\n• Improved preview typography and spacing\n• Adjustable font sizes via menu (Ctrl+Shift+Plus/Minus)\n• Complete theme support including Monokai fixes\n• Find & replace with match highlighting\n• Line numbers and auto-indentation\n• Export to multiple formats via Pandoc\n• PowerPoint & presentation export\n• Export tables to Excel/ODS spreadsheets\n• Document import & conversion\n• Table creation helper\n• 22 beautiful themes (including Dracula, Nord, Tokyo Night, Gruvbox, Ayu, Concrete, and more)\n• Undo/redo functionality\n• Live word count and statistics',
buttons: ['OK'] buttons: ['OK']
}); });
} }
@@ -1585,16 +1618,12 @@ function openFileFromPath(filePath) {
if (fs.existsSync(filePath)) { if (fs.existsSync(filePath)) {
currentFile = filePath; currentFile = filePath;
const content = fs.readFileSync(filePath, 'utf-8'); const content = fs.readFileSync(filePath, 'utf-8');
if (mainWindow && mainWindow.webContents) { if (mainWindow && mainWindow.webContents && rendererReady) {
console.log('Attempting to open file:', filePath, 'rendererReady:', rendererReady);
// Always try to send, the renderer will handle it when ready
mainWindow.webContents.send('file-opened', { path: filePath, content }); mainWindow.webContents.send('file-opened', { path: filePath, content });
} else { } else {
// Store file to open after window is created // Store file to open after renderer is ready
app.pendingFile = filePath; app.pendingFile = filePath;
} }
} else {
console.error('File does not exist:', filePath);
} }
} }
+275 -4
View File
@@ -326,7 +326,6 @@ body {
#preview table th, .preview-content table th { #preview table th, .preview-content table th {
font-weight: 600; font-weight: 600;
background-color: #f6f8fa;
} }
#preview table tr:nth-child(2n), .preview-content table tr:nth-child(2n) { #preview table tr:nth-child(2n), .preview-content table tr:nth-child(2n) {
@@ -449,9 +448,6 @@ body.theme-dark .preview-content table th, body.theme-dark .preview-content tabl
border-color: #3e3e42; border-color: #3e3e42;
} }
body.theme-dark #preview table th, body.theme-dark .preview-content table th {
background-color: #2d2d30;
}
body.theme-dark #preview table tr:nth-child(2n), body.theme-dark .preview-content table tr:nth-child(2n) { body.theme-dark #preview table tr:nth-child(2n), body.theme-dark .preview-content table tr:nth-child(2n) {
background-color: #2d2d30; background-color: #2d2d30;
@@ -1629,6 +1625,10 @@ body.theme-dracula .editor-textarea {
color: #f8f8f2; color: #f8f8f2;
} }
body.theme-dracula .pane:last-child {
background: #282a36;
}
body.theme-dracula .preview-content { body.theme-dracula .preview-content {
color: #f8f8f2; color: #f8f8f2;
} }
@@ -1698,6 +1698,10 @@ body.theme-nord .editor-textarea {
color: #d8dee9; color: #d8dee9;
} }
body.theme-nord .pane:last-child {
background: #2e3440;
}
body.theme-nord .preview-content { body.theme-nord .preview-content {
color: #d8dee9; color: #d8dee9;
} }
@@ -1767,6 +1771,10 @@ body.theme-onedark .editor-textarea {
color: #abb2bf; color: #abb2bf;
} }
body.theme-onedark .pane:last-child {
background: #282c34;
}
body.theme-onedark .preview-content { body.theme-onedark .preview-content {
color: #abb2bf; color: #abb2bf;
} }
@@ -1836,6 +1844,10 @@ body.theme-atomonelight .editor-textarea {
color: #383a42; color: #383a42;
} }
body.theme-atomonelight .pane:last-child {
background: #fafafa;
}
body.theme-atomonelight .preview-content { body.theme-atomonelight .preview-content {
color: #383a42; color: #383a42;
} }
@@ -1905,6 +1917,10 @@ body.theme-material .editor-textarea {
color: #eeffff; color: #eeffff;
} }
body.theme-material .pane:last-child {
background: #263238;
}
body.theme-material .preview-content { body.theme-material .preview-content {
color: #eeffff; color: #eeffff;
} }
@@ -1974,6 +1990,10 @@ body.theme-gruvbox-dark .editor-textarea {
color: #ebdbb2; color: #ebdbb2;
} }
body.theme-gruvbox-dark .pane:last-child {
background: #282828;
}
body.theme-gruvbox-dark .preview-content { body.theme-gruvbox-dark .preview-content {
color: #ebdbb2; color: #ebdbb2;
} }
@@ -2043,6 +2063,10 @@ body.theme-gruvbox-light .editor-textarea {
color: #3c3836; color: #3c3836;
} }
body.theme-gruvbox-light .pane:last-child {
background: #fbf1c7;
}
body.theme-gruvbox-light .preview-content { body.theme-gruvbox-light .preview-content {
color: #3c3836; color: #3c3836;
} }
@@ -2112,6 +2136,10 @@ body.theme-tokyonight .editor-textarea {
color: #c0caf5; color: #c0caf5;
} }
body.theme-tokyonight .pane:last-child {
background: #1a1b26;
}
body.theme-tokyonight .preview-content { body.theme-tokyonight .preview-content {
color: #c0caf5; color: #c0caf5;
} }
@@ -2181,6 +2209,10 @@ body.theme-palenight .editor-textarea {
color: #a6accd; color: #a6accd;
} }
body.theme-palenight .pane:last-child {
background: #292d3e;
}
body.theme-palenight .preview-content { body.theme-palenight .preview-content {
color: #a6accd; color: #a6accd;
} }
@@ -2250,6 +2282,10 @@ body.theme-ayu-dark .editor-textarea {
color: #b3b1ad; color: #b3b1ad;
} }
body.theme-ayu-dark .pane:last-child {
background: #0a0e14;
}
body.theme-ayu-dark .preview-content { body.theme-ayu-dark .preview-content {
color: #b3b1ad; color: #b3b1ad;
} }
@@ -2319,6 +2355,10 @@ body.theme-ayu-light .editor-textarea {
color: #5c6166; color: #5c6166;
} }
body.theme-ayu-light .pane:last-child {
background: #fafafa;
}
body.theme-ayu-light .preview-content { body.theme-ayu-light .preview-content {
color: #5c6166; color: #5c6166;
} }
@@ -2388,6 +2428,10 @@ body.theme-ayu-mirage .editor-textarea {
color: #cbccc6; color: #cbccc6;
} }
body.theme-ayu-mirage .pane:last-child {
background: #1f2430;
}
body.theme-ayu-mirage .preview-content { body.theme-ayu-mirage .preview-content {
color: #cbccc6; color: #cbccc6;
} }
@@ -2457,6 +2501,10 @@ body.theme-oceanic-next .editor-textarea {
color: #cdd3de; color: #cdd3de;
} }
body.theme-oceanic-next .pane:last-child {
background: #1b2b34;
}
body.theme-oceanic-next .preview-content { body.theme-oceanic-next .preview-content {
color: #cdd3de; color: #cdd3de;
} }
@@ -2526,6 +2574,10 @@ body.theme-cobalt2 .editor-textarea {
color: #ffffff; color: #ffffff;
} }
body.theme-cobalt2 .pane:last-child {
background: #193549;
}
body.theme-cobalt2 .preview-content { body.theme-cobalt2 .preview-content {
color: #ffffff; color: #ffffff;
} }
@@ -2552,4 +2604,223 @@ body.theme-cobalt2 .status-bar {
background: #15232d; background: #15232d;
border-top-color: #2a4a5d; border-top-color: #2a4a5d;
color: #ffffff; color: #ffffff;
}
/* Theme: Concrete Dark - ConcreteInfo branded dark theme */
body.theme-concrete-dark {
background: #0d0b09;
color: #e3e3e3;
}
body.theme-concrete-dark .tab-bar {
background: #1a1816;
border-bottom-color: #464646;
}
body.theme-concrete-dark .tab {
background: #464646;
border-color: #9a9696;
color: #e3e3e3;
}
body.theme-concrete-dark .tab.active {
background: #0d0b09;
border-color: #e5461f;
}
body.theme-concrete-dark .toolbar {
background: #1a1816;
border-bottom-color: #464646;
}
body.theme-concrete-dark .toolbar button {
color: #e3e3e3;
}
body.theme-concrete-dark .toolbar button:hover {
background: #464646;
border-color: #e5461f;
}
body.theme-concrete-dark .editor-textarea {
background: #0d0b09;
color: #e3e3e3;
}
body.theme-concrete-dark .pane:last-child {
background: #0d0b09;
}
body.theme-concrete-dark .preview-content {
color: #e3e3e3;
}
body.theme-concrete-dark .preview-content h1,
body.theme-concrete-dark .preview-content h2 {
border-bottom-color: #464646;
color: #e5461f;
}
body.theme-concrete-dark .preview-content code {
background-color: #464646;
}
body.theme-concrete-dark .preview-content pre {
background-color: #464646;
}
body.theme-concrete-dark .preview-content a {
color: #e5461f;
}
body.theme-concrete-dark .status-bar {
background: #1a1816;
border-top-color: #464646;
color: #9a9696;
}
/* Theme: Concrete Light - ConcreteInfo branded light theme */
body.theme-concrete-light {
background: #fafafa;
color: #0d0b09;
}
body.theme-concrete-light .tab-bar {
background: #e3e3e3;
border-bottom-color: #9a9696;
}
body.theme-concrete-light .tab {
background: #e3e3e3;
border-color: #9a9696;
color: #0d0b09;
}
body.theme-concrete-light .tab.active {
background: #fafafa;
border-color: #e5461f;
}
body.theme-concrete-light .toolbar {
background: #e3e3e3;
border-bottom-color: #9a9696;
}
body.theme-concrete-light .toolbar button {
color: #0d0b09;
}
body.theme-concrete-light .toolbar button:hover {
background: #9a9696;
border-color: #e5461f;
}
body.theme-concrete-light .editor-textarea {
background: #fafafa;
color: #0d0b09;
}
body.theme-concrete-light .pane:last-child {
background: #fafafa;
}
body.theme-concrete-light .preview-content {
color: #0d0b09;
}
body.theme-concrete-light .preview-content h1,
body.theme-concrete-light .preview-content h2 {
border-bottom-color: #9a9696;
color: #e5461f;
}
body.theme-concrete-light .preview-content code {
background-color: #e3e3e3;
}
body.theme-concrete-light .preview-content pre {
background-color: #e3e3e3;
}
body.theme-concrete-light .preview-content a {
color: #e5461f;
}
body.theme-concrete-light .status-bar {
background: #e3e3e3;
border-top-color: #9a9696;
color: #464646;
}
/* Theme: Concrete Warm - ConcreteInfo branded warm theme */
body.theme-concrete-warm {
background: #464646;
color: #e3e3e3;
}
body.theme-concrete-warm .tab-bar {
background: #3a3836;
border-bottom-color: #9a9696;
}
body.theme-concrete-warm .tab {
background: #9a9696;
border-color: #e3e3e3;
color: #0d0b09;
}
body.theme-concrete-warm .tab.active {
background: #464646;
border-color: #e5461f;
}
body.theme-concrete-warm .toolbar {
background: #3a3836;
border-bottom-color: #9a9696;
}
body.theme-concrete-warm .toolbar button {
color: #e3e3e3;
}
body.theme-concrete-warm .toolbar button:hover {
background: #9a9696;
border-color: #e5461f;
}
body.theme-concrete-warm .editor-textarea {
background: #464646;
color: #e3e3e3;
}
body.theme-concrete-warm .pane:last-child {
background: #464646;
}
body.theme-concrete-warm .preview-content {
color: #e3e3e3;
}
body.theme-concrete-warm .preview-content h1,
body.theme-concrete-warm .preview-content h2 {
border-bottom-color: #9a9696;
color: #e5461f;
}
body.theme-concrete-warm .preview-content code {
background-color: #3a3836;
}
body.theme-concrete-warm .preview-content pre {
background-color: #3a3836;
}
body.theme-concrete-warm .preview-content a {
color: #e5461f;
}
body.theme-concrete-warm .status-bar {
background: #3a3836;
border-top-color: #9a9696;
color: #e3e3e3;
} }