export function createDesktopNotification(
options: DesktopNotificationOptions,
onClick?: () => void,
): DesktopNotificationHandle {
const notification = new Notification(options);
if (onClick) {
notification.on("click", onClick);
}
return {
show: () => {
const release = retainNotification(notification);
return new Promise((resolve, reject) => {
let settled = false;
let settleTimer: NodeJS.Timeout | null = null;
const settle = (callback: () => void) => {
if (settled) return;
settled = true;
if (settleTimer) {
clearTimeout(settleTimer);
settleTimer = null;
}
callback();
};
notification.once("show", () => {
settle(resolve);
});
if (process.platform === "win32") {
notification.once("failed", (_event, error) => {
release();
settle(() => {
reject(new Error(error || "桌面通知发送失败"));
});
});
}
if (process.platform === "darwin") {
notification.once("show", () => {
setTimeout(() => {
settle(resolve);
}, 100);
});
}
settleTimer = setTimeout(() => {
release();
settle(() => {
if (process.platform === "darwin") {
reject(
new Error(
"桌面通知发送超时,请检查 macOS 系统偏好设置中的通知权限",
),
);
} else {
reject(new Error("桌面通知发送超时"));
}
});
}, 5_000);
settleTimer.unref?.();
try {
notification.show();
} catch (error) {
release();
settle(() => {
reject(error);
});
}
});
},
};
}