fix(desktop): use Electron's native Notification (reliable click-to-open)
node-notifier/SnoreToast click callback never fired without the crashing wait mode. Switch the chat toast to Electron's built-in Notification: shows avatar + message and its 'click' event reliably raises the app + opens the chat. No SnoreToast, no external tools. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+19
-17
@@ -8,7 +8,7 @@
|
||||
// - external links open in the user's browser, not inside the app
|
||||
//
|
||||
// Server origin is configurable so the same build works against prod or a dev server.
|
||||
const { app, BrowserWindow, session, desktopCapturer, shell, Menu, ipcMain, nativeImage } = require('electron');
|
||||
const { app, BrowserWindow, session, desktopCapturer, shell, Menu, ipcMain, nativeImage, Notification } = require('electron');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
@@ -35,15 +35,11 @@ ipcMain.on('get-install-info', (e) => {
|
||||
// on the next restart. No-op in dev (unpackaged).
|
||||
let autoUpdater = null;
|
||||
try { ({ autoUpdater } = require('electron-updater')); } catch (_) { /* not installed in dev */ }
|
||||
// Chat toast: shows the sender/group avatar + message; clicking it opens the chat. Uses
|
||||
// node-notifier's WindowsToaster for reliable DISPLAY. Inline text reply is intentionally not
|
||||
// used — the bundled SnoreToast crashes (0xC0000409) handling a text reply — so this is a clean
|
||||
// click-to-open toast. Installed-app only (needs the AppUserModelID shortcut the installer sets).
|
||||
let notifier = null;
|
||||
try { notifier = require('node-notifier'); } catch (_) { /* optional */ }
|
||||
// Chat toast: sender/group avatar + message; clicking it raises the app and opens that chat.
|
||||
// Uses Electron's OWN Notification (native, no SnoreToast) whose 'click' event fires reliably.
|
||||
const APP_ID = 'com.bizgaze.connect.desktop';
|
||||
|
||||
// Write the avatar the renderer drew (a data: URL) to a temp PNG for the toast image.
|
||||
// Write the avatar the renderer drew (a data: URL) to a temp PNG for the toast icon.
|
||||
function writeTempPng(dataUrl) {
|
||||
try {
|
||||
if (!dataUrl || !/^data:image\/png;base64,/.test(dataUrl)) return null;
|
||||
@@ -53,20 +49,26 @@ function writeTempPng(dataUrl) {
|
||||
} catch (_) { return null; }
|
||||
}
|
||||
|
||||
// Resolves {open} when the toast is clicked (the renderer then opens that chat), else null.
|
||||
// Resolves {open} when the toast is clicked (renderer then opens that chat), else null.
|
||||
ipcMain.handle('reply-notification', (_e, payload = {}) => new Promise((resolve) => {
|
||||
if (!notifier) return resolve(null);
|
||||
if (!Notification.isSupported()) return resolve(null);
|
||||
const img = writeTempPng(payload.avatar);
|
||||
let done = false;
|
||||
const finish = (v) => { if (!done) { done = true; if (img) { try { fs.unlinkSync(img); } catch (_) {} } resolve(v); } };
|
||||
try {
|
||||
notifier.notify(
|
||||
Object.assign({ appID: APP_ID, title: payload.title || 'Biz Connect', message: payload.body || ' ' }, img ? { icon: img } : {}),
|
||||
(err, response, metadata) => {
|
||||
const act = String(response || (metadata && metadata.action) || '').toLowerCase();
|
||||
finish(act.includes('activat') || act === 'click' ? { kind: payload.kind, id: payload.id, open: true } : null);
|
||||
}
|
||||
);
|
||||
const n = new Notification({
|
||||
title: payload.title || 'Biz Connect',
|
||||
body: payload.body || '',
|
||||
icon: img ? nativeImage.createFromPath(img) : undefined,
|
||||
silent: false,
|
||||
});
|
||||
n.on('click', () => {
|
||||
if (win) { if (win.isMinimized()) win.restore(); win.show(); win.focus(); } // raise the app
|
||||
finish({ kind: payload.kind, id: payload.id, open: true });
|
||||
});
|
||||
n.on('close', () => finish(null));
|
||||
n.show();
|
||||
setTimeout(() => finish(null), 30000); // don't leave the promise pending forever
|
||||
} catch (_) { finish(null); }
|
||||
}));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user