refactor(main): extract window creation to src/main/window/ (main only, ascii/table windows removed)

This commit is contained in:
2026-06-06 14:03:12 +05:30
parent 6c7a86c99b
commit 848102905e
3 changed files with 112 additions and 67 deletions
+5 -67
View File
@@ -8,6 +8,7 @@ const GitOperations = require('./main/GitOperations');
const { getAllowedDirectories, validatePath, resolveWritablePath, isPathAccessible } = require('./main/utils/paths'); const { getAllowedDirectories, validatePath, resolveWritablePath, isPathAccessible } = require('./main/utils/paths');
const fileOps = require('./main/files'); const fileOps = require('./main/files');
const menu = require('./main/menu'); const menu = require('./main/menu');
const { createMainWindow } = require('./main/window');
// Add MiKTeX to PATH for LaTeX support // Add MiKTeX to PATH for LaTeX support
if (process.platform === 'win32') { if (process.platform === 'win32') {
@@ -387,71 +388,6 @@ function checkPandocAvailability() {
}); });
} }
function createWindow() {
mainWindow = new BrowserWindow({
width: 1200,
height: 800,
show: false,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
spellcheck: true
},
icon: path.join(__dirname, '../assets/icon.png')
});
mainWindow.loadFile(path.join(__dirname, 'index.html'));
// Show window only after content is ready — avoids blank flash
mainWindow.once('ready-to-show', () => {
mainWindow.show();
});
menu.register(mainWindow);
mainWindow.on('closed', () => {
mainWindow = null;
});
// Spell check context menu
mainWindow.webContents.on('context-menu', (event, params) => {
const { Menu, MenuItem } = require('electron');
const menu = new Menu();
// Add spell check suggestions
if (params.misspelledWord) {
for (const suggestion of params.dictionarySuggestions) {
menu.append(new MenuItem({
label: suggestion,
click: () => mainWindow.webContents.replaceMisspelling(suggestion)
}));
}
if (params.dictionarySuggestions.length > 0) {
menu.append(new MenuItem({ type: 'separator' }));
}
menu.append(new MenuItem({
label: 'Add to Dictionary',
click: () => mainWindow.webContents.session.addWordToSpellCheckerDictionary(params.misspelledWord)
}));
menu.append(new MenuItem({ type: 'separator' }));
}
// Standard context menu items
menu.append(new MenuItem({ role: 'cut' }));
menu.append(new MenuItem({ role: 'copy' }));
menu.append(new MenuItem({ role: 'paste' }));
menu.append(new MenuItem({ role: 'selectAll' }));
menu.popup();
});
// Wait for the page to fully load before sending file data
mainWindow.webContents.on('did-finish-load', () => {
console.log('Window finished loading');
// Don't open file here - wait for renderer-ready signal
// The renderer will send renderer-ready when TabManager is initialized
});
}
// Show About Dialog with logo // Show About Dialog with logo
@@ -3127,7 +3063,8 @@ app.whenReady().then(() => {
return; // Don't create window for CLI operations return; // Don't create window for CLI operations
} }
createWindow(); mainWindow = createMainWindow();
mainWindow.on('closed', () => { mainWindow = null; });
// Register file ops IPC handlers // Register file ops IPC handlers
fileOps.register({ fileOps.register({
@@ -3178,7 +3115,8 @@ app.on('window-all-closed', () => {
app.on('activate', () => { app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) { if (BrowserWindow.getAllWindows().length === 0) {
createWindow(); mainWindow = createMainWindow();
mainWindow.on('closed', () => { mainWindow = null; });
} }
}); });
+80
View File
@@ -0,0 +1,80 @@
// src/main/window/index.js
// Main window creation
const { BrowserWindow } = require('electron');
const path = require('path');
const state = require('./state');
const menu = require('../menu');
function createMainWindow() {
const bounds = state.load();
const win = new BrowserWindow({
width: bounds.width,
height: bounds.height,
x: bounds.x,
y: bounds.y,
show: false,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
spellcheck: true
},
icon: path.join(__dirname, '../../assets/icon.png')
});
win.loadFile(path.join(__dirname, '../../index.html'));
// Show window only after content is ready — avoids blank flash
win.once('ready-to-show', () => {
win.show();
});
menu.register(win);
win.on('closed', () => {
state.save(win);
});
// Spell check context menu
win.webContents.on('context-menu', (event, params) => {
const { Menu, MenuItem } = require('electron');
const ctxMenu = new Menu();
// Add spell check suggestions
if (params.misspelledWord) {
for (const suggestion of params.dictionarySuggestions) {
ctxMenu.append(new MenuItem({
label: suggestion,
click: () => win.webContents.replaceMisspelling(suggestion)
}));
}
if (params.dictionarySuggestions.length > 0) {
ctxMenu.append(new MenuItem({ type: 'separator' }));
}
ctxMenu.append(new MenuItem({
label: 'Add to Dictionary',
click: () => win.webContents.session.addWordToSpellCheckerDictionary(params.misspelledWord)
}));
ctxMenu.append(new MenuItem({ type: 'separator' }));
}
// Standard context menu items
ctxMenu.append(new MenuItem({ role: 'cut' }));
ctxMenu.append(new MenuItem({ role: 'copy' }));
ctxMenu.append(new MenuItem({ role: 'paste' }));
ctxMenu.append(new MenuItem({ role: 'selectAll' }));
ctxMenu.popup();
});
// Wait for the page to fully load before sending file data
win.webContents.on('did-finish-load', () => {
console.log('Window finished loading');
// Don't open file here - wait for renderer-ready signal
// The renderer will send renderer-ready when TabManager is initialized
});
return win;
}
module.exports = { createMainWindow };
+27
View File
@@ -0,0 +1,27 @@
// src/main/window/state.js
// Window state persistence (size, position)
const { app } = require('electron');
const path = require('path');
const fs = require('fs');
const stateFile = path.join(app.getPath('userData'), 'window-state.json');
function load() {
try {
return JSON.parse(fs.readFileSync(stateFile, 'utf8'));
} catch {
return { width: 1200, height: 800 };
}
}
function save(win) {
const bounds = win.getBounds();
try {
fs.writeFileSync(stateFile, JSON.stringify(bounds));
} catch {
/* ignore */
}
}
module.exports = { load, save };