@lobehub/chat
Version:
Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.
155 lines (129 loc) • 4.65 kB
text/typescript
import {
DesktopNotificationResult,
ShowDesktopNotificationParams,
} from '@lobechat/electron-client-ipc';
import { Notification, app } from 'electron';
import { macOS, windows } from 'electron-is';
import { createLogger } from '@/utils/logger';
import { ControllerModule, ipcClientEvent } from './index';
const logger = createLogger('controllers:NotificationCtr');
export default class NotificationCtr extends ControllerModule {
/**
* 在应用准备就绪后设置桌面通知
*/
afterAppReady() {
this.setupNotifications();
}
/**
* 设置桌面通知权限和配置
*/
private setupNotifications() {
logger.debug('Setting up desktop notifications');
try {
// 检查通知支持
if (!Notification.isSupported()) {
logger.warn('Desktop notifications are not supported on this platform');
return;
}
// 在 macOS 上,我们可能需要显式请求通知权限
if (macOS()) {
logger.debug('macOS detected, notification permissions should be handled by system');
}
// 在 Windows 上设置应用用户模型 ID
if (windows()) {
app.setAppUserModelId('com.lobehub.chat');
logger.debug('Set Windows App User Model ID for notifications');
}
logger.info('Desktop notifications setup completed');
} catch (error) {
logger.error('Failed to setup desktop notifications:', error);
}
}
/**
* 显示系统桌面通知(仅当窗口隐藏时)
*/
('showDesktopNotification')
async showDesktopNotification(
params: ShowDesktopNotificationParams,
): Promise<DesktopNotificationResult> {
logger.debug('收到桌面通知请求:', params);
try {
// 检查通知支持
if (!Notification.isSupported()) {
logger.warn('系统不支持桌面通知');
return { error: 'Desktop notifications not supported', success: false };
}
// 检查窗口是否隐藏
const isWindowHidden = this.isMainWindowHidden();
if (!isWindowHidden) {
logger.debug('主窗口可见,跳过桌面通知');
return { reason: 'Window is visible', skipped: true, success: true };
}
logger.info('窗口已隐藏,显示桌面通知:', params.title);
const notification = new Notification({
body: params.body,
// 添加更多配置以确保通知能正常显示
hasReply: false,
silent: params.silent || false,
timeoutType: 'default',
title: params.title,
urgency: 'normal',
});
// 添加更多事件监听来调试
notification.on('show', () => {
logger.info('通知已显示');
});
notification.on('click', () => {
logger.debug('用户点击通知,显示主窗口');
const mainWindow = this.app.browserManager.getMainWindow();
mainWindow.show();
mainWindow.browserWindow.focus();
});
notification.on('close', () => {
logger.debug('通知已关闭');
});
notification.on('failed', (error) => {
logger.error('通知显示失败:', error);
});
// 使用 Promise 来确保通知显示
return new Promise((resolve) => {
notification.show();
// 给通知一些时间来显示,然后检查结果
setTimeout(() => {
logger.info('通知显示调用完成');
resolve({ success: true });
}, 100);
});
} catch (error) {
logger.error('显示桌面通知失败:', error);
return {
error: error instanceof Error ? error.message : 'Unknown error',
success: false,
};
}
}
/**
* 检查主窗口是否隐藏
*/
('isMainWindowHidden')
isMainWindowHidden(): boolean {
try {
const mainWindow = this.app.browserManager.getMainWindow();
const browserWindow = mainWindow.browserWindow;
// 如果窗口被销毁,认为是隐藏的
if (browserWindow.isDestroyed()) {
return true;
}
// 检查窗口是否可见和聚焦
const isVisible = browserWindow.isVisible();
const isFocused = browserWindow.isFocused();
const isMinimized = browserWindow.isMinimized();
logger.debug('窗口状态检查:', { isFocused, isMinimized, isVisible });
// 窗口隐藏的条件:不可见或最小化或失去焦点
return !isVisible || isMinimized || !isFocused;
} catch (error) {
logger.error('检查窗口状态失败:', error);
return true; // 发生错误时认为窗口隐藏,确保通知能显示
}
}
}