docs-combiner 0.1.18 → 0.1.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.js CHANGED
@@ -48,6 +48,66 @@ const fs = __importStar(require("fs"));
48
48
  const http = __importStar(require("http"));
49
49
  const url = __importStar(require("url"));
50
50
  let pendingGoogleAuth = null;
51
+ let mainWindow = null;
52
+ if (process.env.DOCS_COMBINER_DISABLE_GPU === '1') {
53
+ electron_1.app.disableHardwareAcceleration();
54
+ }
55
+ function getInspectableWindow() {
56
+ var _a, _b, _c;
57
+ return (_c = (_b = (_a = electron_1.BrowserWindow.getFocusedWindow()) !== null && _a !== void 0 ? _a : mainWindow) !== null && _b !== void 0 ? _b : electron_1.BrowserWindow.getAllWindows()[0]) !== null && _c !== void 0 ? _c : null;
58
+ }
59
+ function toggleDevToolsForWindow(win) {
60
+ if (!win || win.isDestroyed()) {
61
+ console.warn('[DevTools] No BrowserWindow available');
62
+ return;
63
+ }
64
+ const webContents = win.webContents;
65
+ if (webContents.isDestroyed()) {
66
+ console.warn('[DevTools] WebContents is destroyed');
67
+ return;
68
+ }
69
+ try {
70
+ if (webContents.isDevToolsOpened()) {
71
+ webContents.closeDevTools();
72
+ }
73
+ else {
74
+ webContents.openDevTools({ mode: 'detach', activate: true });
75
+ }
76
+ }
77
+ catch (e) {
78
+ console.error('[DevTools] Failed to toggle DevTools:', e);
79
+ }
80
+ }
81
+ function telegramSendMessageViaBot(botToken, chatId, text) {
82
+ return __awaiter(this, void 0, void 0, function* () {
83
+ const apiUrl = `https://api.telegram.org/bot${encodeURIComponent(botToken)}/sendMessage`;
84
+ const safeText = text.length > 4096 ? `${text.slice(0, 4090)}…` : text;
85
+ try {
86
+ const res = yield fetch(apiUrl, {
87
+ method: 'POST',
88
+ headers: { 'Content-Type': 'application/json' },
89
+ body: JSON.stringify({
90
+ chat_id: chatId,
91
+ text: safeText,
92
+ }),
93
+ });
94
+ const data = (yield res.json());
95
+ if (!data.ok) {
96
+ return {
97
+ ok: false,
98
+ error: data.description || `HTTP ${res.status}`,
99
+ };
100
+ }
101
+ return { ok: true };
102
+ }
103
+ catch (e) {
104
+ return {
105
+ ok: false,
106
+ error: e instanceof Error ? e.message : String(e),
107
+ };
108
+ }
109
+ });
110
+ }
51
111
  function abortPendingGoogleAuth(reason) {
52
112
  const pending = pendingGoogleAuth;
53
113
  if (!pending)
@@ -61,6 +121,52 @@ function abortPendingGoogleAuth(reason) {
61
121
  }
62
122
  pending.reject(new Error(reason));
63
123
  }
124
+ function buildAppMenu() {
125
+ const isMac = process.platform === 'darwin';
126
+ const template = [];
127
+ if (isMac) {
128
+ template.push({ role: 'appMenu' });
129
+ // Cut/Copy/Paste/Select All — без этого Cmd+V в полях иногда не работает (Chromium + системное меню).
130
+ template.push({ role: 'editMenu' });
131
+ }
132
+ else {
133
+ template.push({
134
+ label: 'File',
135
+ submenu: [{ role: 'quit' }],
136
+ });
137
+ template.push({
138
+ label: 'Edit',
139
+ submenu: [
140
+ { role: 'undo' },
141
+ { role: 'redo' },
142
+ { type: 'separator' },
143
+ { role: 'cut' },
144
+ { role: 'copy' },
145
+ { role: 'paste' },
146
+ { role: 'delete' },
147
+ { type: 'separator' },
148
+ { role: 'selectAll' },
149
+ ],
150
+ });
151
+ }
152
+ template.push({
153
+ label: 'View',
154
+ submenu: [
155
+ { role: 'reload' },
156
+ { role: 'forceReload' },
157
+ {
158
+ label: 'Toggle Developer Tools',
159
+ accelerator: isMac ? 'Alt+Command+I' : 'Ctrl+Shift+I',
160
+ click: () => toggleDevToolsForWindow(getInspectableWindow()),
161
+ },
162
+ { type: 'separator' },
163
+ { role: 'resetZoom' },
164
+ { role: 'zoomIn' },
165
+ { role: 'zoomOut' },
166
+ ],
167
+ });
168
+ electron_1.Menu.setApplicationMenu(electron_1.Menu.buildFromTemplate(template));
169
+ }
64
170
  function createWindow() {
65
171
  // Try to read theme preference from localStorage file
66
172
  // In Electron, localStorage is stored in a specific location
@@ -74,7 +180,7 @@ function createWindow() {
74
180
  catch (e) {
75
181
  // Use default
76
182
  }
77
- const mainWindow = new electron_1.BrowserWindow({
183
+ mainWindow = new electron_1.BrowserWindow({
78
184
  width: 1000,
79
185
  height: 800,
80
186
  backgroundColor: '#121212', // Set to dark by default, will be corrected by preload if light
@@ -86,10 +192,47 @@ function createWindow() {
86
192
  sandbox: false
87
193
  },
88
194
  });
195
+ const win = mainWindow;
196
+ // Toggles from main: works when the page/React failed — handled before the renderer consumes the key.
197
+ // F12, Cmd+Shift+D (mac) / Ctrl+Shift+D (win/linux); also View → Toggle Developer Tools / Cmd+Option+I (see menu).
198
+ win.webContents.on('before-input-event', (event, input) => {
199
+ if (input.type !== 'keyDown') {
200
+ return;
201
+ }
202
+ if (input.key === 'F12' && !input.control && !input.meta && !input.alt) {
203
+ toggleDevToolsForWindow(win);
204
+ event.preventDefault();
205
+ return;
206
+ }
207
+ if (input.key.toLowerCase() !== 'd' || !input.shift || input.alt) {
208
+ return;
209
+ }
210
+ const isMac = process.platform === 'darwin';
211
+ const hasPrimaryMod = isMac ? input.meta === true : input.control === true;
212
+ if (hasPrimaryMod) {
213
+ toggleDevToolsForWindow(win);
214
+ event.preventDefault();
215
+ }
216
+ });
217
+ win.webContents.on('render-process-gone', (_event, details) => {
218
+ console.error(`[Renderer] render-process-gone: reason=${details.reason}, exitCode=${details.exitCode}`);
219
+ });
220
+ win.webContents.on('unresponsive', () => {
221
+ console.error('[Renderer] webContents became unresponsive');
222
+ });
223
+ win.webContents.on('responsive', () => {
224
+ console.log('[Renderer] webContents became responsive');
225
+ });
226
+ win.webContents.on('did-fail-load', (_event, errorCode, errorDescription, validatedURL) => {
227
+ console.error(`[Renderer] did-fail-load: ${errorCode} ${errorDescription} ${validatedURL}`);
228
+ });
229
+ win.webContents.on('console-message', (_event, level, message, line, sourceId) => {
230
+ console.log(`[Renderer console:${level}] ${message} (${sourceId}:${line})`);
231
+ });
89
232
  // Show window only after page is ready to prevent white flash
90
- mainWindow.webContents.once('did-finish-load', () => {
233
+ win.webContents.once('did-finish-load', () => {
91
234
  // Ensure theme is applied before showing
92
- mainWindow.webContents.executeJavaScript(`
235
+ win.webContents.executeJavaScript(`
93
236
  (function() {
94
237
  const savedTheme = localStorage.getItem('themeMode');
95
238
  const isDark = savedTheme === 'dark';
@@ -100,17 +243,21 @@ function createWindow() {
100
243
  if (root) root.style.setProperty('background-color', bgColor, 'important');
101
244
  })();
102
245
  `).then(() => {
103
- mainWindow.show();
246
+ win.show();
104
247
  }).catch(() => {
105
- mainWindow.show();
248
+ win.show();
106
249
  });
107
250
  });
108
251
  // We need to point to the webpack output html
109
- mainWindow.loadFile(path.join(__dirname, 'index.html'));
252
+ win.loadFile(path.join(__dirname, 'index.html'));
110
253
  // DevTools disabled by default as requested
111
254
  // mainWindow.webContents.openDevTools();
112
255
  }
113
256
  electron_1.app.whenReady().then(() => {
257
+ buildAppMenu();
258
+ electron_1.app.on('child-process-gone', (_event, details) => {
259
+ console.error(`[Electron] child-process-gone: type=${details.type}, reason=${details.reason}, exitCode=${details.exitCode}`);
260
+ });
114
261
  const userDataPath = electron_1.app.getPath('userData');
115
262
  if (!fs.existsSync(userDataPath)) {
116
263
  fs.mkdirSync(userDataPath, { recursive: true });
@@ -137,6 +284,28 @@ electron_1.app.whenReady().then(() => {
137
284
  return {};
138
285
  }
139
286
  }));
287
+ electron_1.ipcMain.handle('telegram-send-test', (_event, payload) => __awaiter(void 0, void 0, void 0, function* () {
288
+ var _a, _b;
289
+ const botToken = String((_a = payload === null || payload === void 0 ? void 0 : payload.botToken) !== null && _a !== void 0 ? _a : '').trim();
290
+ const chatId = String((_b = payload === null || payload === void 0 ? void 0 : payload.chatId) !== null && _b !== void 0 ? _b : '').trim();
291
+ if (!botToken || !chatId) {
292
+ return { ok: false, error: 'Укажите токен бота и ID чата.' };
293
+ }
294
+ return telegramSendMessageViaBot(botToken, chatId, 'Docs Combiner — тест оповещений.');
295
+ }));
296
+ electron_1.ipcMain.handle('telegram-send-message', (_event, payload) => __awaiter(void 0, void 0, void 0, function* () {
297
+ var _a, _b, _c;
298
+ const botToken = String((_a = payload === null || payload === void 0 ? void 0 : payload.botToken) !== null && _a !== void 0 ? _a : '').trim();
299
+ const chatId = String((_b = payload === null || payload === void 0 ? void 0 : payload.chatId) !== null && _b !== void 0 ? _b : '').trim();
300
+ const text = String((_c = payload === null || payload === void 0 ? void 0 : payload.text) !== null && _c !== void 0 ? _c : '');
301
+ if (!botToken || !chatId) {
302
+ return { ok: false, error: 'Укажите токен бота и ID чата.' };
303
+ }
304
+ if (!text.trim()) {
305
+ return { ok: false, error: 'Пустой текст сообщения.' };
306
+ }
307
+ return telegramSendMessageViaBot(botToken, chatId, text);
308
+ }));
140
309
  electron_1.ipcMain.handle('save-file', (event, content, filename) => __awaiter(void 0, void 0, void 0, function* () {
141
310
  const { canceled, filePath } = yield electron_1.dialog.showSaveDialog({
142
311
  defaultPath: filename,
@@ -275,3 +444,9 @@ electron_1.app.whenReady().then(() => {
275
444
  electron_1.app.on('window-all-closed', function () {
276
445
  electron_1.app.quit();
277
446
  });
447
+ process.on('uncaughtException', (err) => {
448
+ console.error('[Main] uncaughtException:', err);
449
+ });
450
+ process.on('unhandledRejection', (reason) => {
451
+ console.error('[Main] unhandledRejection:', reason);
452
+ });
package/dist/preload.js CHANGED
@@ -59,4 +59,6 @@ electron_1.contextBridge.exposeInMainWorld('electronAPI', {
59
59
  cancelPendingAuth: () => electron_1.ipcRenderer.invoke('cancel-pending-auth'),
60
60
  openExternal: (url) => electron_1.ipcRenderer.invoke('open-external', url),
61
61
  log: (level, ...args) => electron_1.ipcRenderer.invoke('log', level, ...args),
62
+ telegramSendTest: (botToken, chatId) => electron_1.ipcRenderer.invoke('telegram-send-test', { botToken, chatId }),
63
+ telegramSendMessage: (botToken, chatId, text) => electron_1.ipcRenderer.invoke('telegram-send-message', { botToken, chatId, text }),
62
64
  });