Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ app.whenReady().then(async () => {
app.on('window-all-closed', () => {
// 检查是否还有非悬浮按钮的窗口
const mainWindows = presenter.windowPresenter.getAllWindows()

if (mainWindows.length === 0) {
// 只有悬浮按钮窗口时,在非 macOS 平台退出应用
if (process.platform !== 'darwin') {
Expand Down
26 changes: 26 additions & 0 deletions src/main/presenter/configPresenter/providerModelSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -982,7 +982,33 @@ export const providerModelSettings: Record<string, { models: ProviderModelSettin
}
]
},
aihubmix: {
models: [
{
id: 'deepseek-ai/DeepSeek-R1-0528',
name: 'DeepSeek R1-0528',
temperature: 0.6,
maxTokens: 65536,
contextLength: 131072,
match: ['deepseek-ai/DeepSeek-R1-0528'],
vision: false,
functionCall: true,
reasoning: true
},

{
id: 'deepseek-ai/DeepSeek-V3-0324',
name: 'DeepSeek v3-0324',
temperature: 0.6,
maxTokens: 65536,
contextLength: 131072,
match: ['deepseek-ai/DeepSeek-V3-0324'],
vision: false,
functionCall: true,
reasoning: false
}
]
},
// OpenRouter提供商特定模型配置
openrouter: {
models: [
Expand Down
150 changes: 75 additions & 75 deletions src/main/presenter/floatingButtonPresenter/FloatingButtonWindow.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { BrowserWindow, screen } from 'electron';
import path from 'path';
import { FloatingButtonConfig, FloatingButtonState } from './types';
import logger from '../../../shared/logger';
import { BrowserWindow, screen } from 'electron'
import path from 'path'
import { FloatingButtonConfig, FloatingButtonState } from './types'
import logger from '../../../shared/logger'

export class FloatingButtonWindow {
private window: BrowserWindow | null = null;
private config: FloatingButtonConfig;
private state: FloatingButtonState;
private window: BrowserWindow | null = null
private config: FloatingButtonConfig
private state: FloatingButtonState

constructor(config: FloatingButtonConfig) {
this.config = config;
this.config = config
this.state = {
isVisible: false,
bounds: {
Expand All @@ -18,26 +18,26 @@ export class FloatingButtonWindow {
width: config.size.width,
height: config.size.height
}
};
}
}

/**
* 创建悬浮窗口
*/
public async create(): Promise<void> {
if (this.window) {
return;
return
}

try {
const position = this.calculatePosition();
const position = this.calculatePosition()

// 根据环境选择正确的预加载脚本路径
const isDev = process.env.NODE_ENV === 'development';
const preloadPath = isDev
const isDev = process.env.NODE_ENV === 'development'
const preloadPath = isDev
? path.join(process.cwd(), 'out/preload/floating.mjs')
: path.join(__dirname, '../../preload/floating.mjs');
: path.join(__dirname, '../../preload/floating.mjs')

this.window = new BrowserWindow({
width: this.config.size.width,
height: this.config.size.height,
Expand All @@ -61,27 +61,27 @@ export class FloatingButtonWindow {
devTools: true, // 开发模式下启用开发者工具
sandbox: false // 禁用沙盒模式,确保预加载脚本能正常工作
}
});
})

// 设置窗口透明度
this.window.setOpacity(this.config.opacity);
this.window.setOpacity(this.config.opacity)

// 加载悬浮按钮页面
if (isDev) {
await this.window.loadURL('http://localhost:5173/floating/');
await this.window.loadURL('http://localhost:5173/floating/')
// 开发模式下可选择性打开开发者工具(暂时禁用,避免影响拖拽)
this.window.webContents.openDevTools({ mode: 'detach' });
this.window.webContents.openDevTools({ mode: 'detach' })
} else {
await this.window.loadFile(path.join(__dirname, '../../../renderer/floating/index.html'));
await this.window.loadFile(path.join(__dirname, '../../../renderer/floating/index.html'))
}

// 监听窗口事件
this.setupWindowEvents();
this.setupWindowEvents()

logger.info('FloatingButtonWindow created successfully');
logger.info('FloatingButtonWindow created successfully')
} catch (error) {
logger.error('Failed to create FloatingButtonWindow:', error);
throw error;
logger.error('Failed to create FloatingButtonWindow:', error)
throw error
}
}

Expand All @@ -90,66 +90,66 @@ export class FloatingButtonWindow {
*/
public show(): void {
if (!this.window) {
return;
return
}

this.window.show();
this.state.isVisible = true;
logger.debug('FloatingButtonWindow shown');
this.window.show()
this.state.isVisible = true
logger.debug('FloatingButtonWindow shown')
}

/**
* 隐藏悬浮窗口
*/
public hide(): void {
if (!this.window) {
return;
return
}

this.window.hide();
this.state.isVisible = false;
logger.debug('FloatingButtonWindow hidden');
this.window.hide()
this.state.isVisible = false
logger.debug('FloatingButtonWindow hidden')
}

/**
* 销毁悬浮窗口
*/
public destroy(): void {
if (this.window) {
this.window.destroy();
this.window = null;
this.state.isVisible = false;
logger.debug('FloatingButtonWindow destroyed');
this.window.destroy()
this.window = null
this.state.isVisible = false
logger.debug('FloatingButtonWindow destroyed')
}
}

/**
* 更新配置
*/
public updateConfig(config: Partial<FloatingButtonConfig>): void {
this.config = { ...this.config, ...config };
this.config = { ...this.config, ...config }

if (this.window) {
// 更新窗口属性
if (config.size) {
this.window.setSize(this.config.size.width, this.config.size.height);
this.state.bounds.width = this.config.size.width;
this.state.bounds.height = this.config.size.height;
this.window.setSize(this.config.size.width, this.config.size.height)
this.state.bounds.width = this.config.size.width
this.state.bounds.height = this.config.size.height
}

if (config.position || config.offset) {
const position = this.calculatePosition();
this.window.setPosition(position.x, position.y);
this.state.bounds.x = position.x;
this.state.bounds.y = position.y;
const position = this.calculatePosition()
this.window.setPosition(position.x, position.y)
this.state.bounds.x = position.x
this.state.bounds.y = position.y
}

if (config.opacity !== undefined) {
this.window.setOpacity(this.config.opacity);
this.window.setOpacity(this.config.opacity)
}

if (config.alwaysOnTop !== undefined) {
this.window.setAlwaysOnTop(this.config.alwaysOnTop);
this.window.setAlwaysOnTop(this.config.alwaysOnTop)
}
}
}
Expand All @@ -158,70 +158,70 @@ export class FloatingButtonWindow {
* 获取当前状态
*/
public getState(): FloatingButtonState {
return { ...this.state };
return { ...this.state }
}

/**
* 检查窗口是否存在
*/
public exists(): boolean {
return this.window !== null && !this.window.isDestroyed();
return this.window !== null && !this.window.isDestroyed()
}

/**
* 计算悬浮按钮位置
*/
private calculatePosition(): { x: number; y: number } {
const primaryDisplay = screen.getPrimaryDisplay();
const { workAreaSize } = primaryDisplay;
let x: number, y: number;
const primaryDisplay = screen.getPrimaryDisplay()
const { workAreaSize } = primaryDisplay

let x: number, y: number

switch (this.config.position) {
case 'top-left':
x = this.config.offset.x;
y = this.config.offset.y;
break;
x = this.config.offset.x
y = this.config.offset.y
break
case 'top-right':
x = workAreaSize.width - this.config.size.width - this.config.offset.x;
y = this.config.offset.y;
break;
x = workAreaSize.width - this.config.size.width - this.config.offset.x
y = this.config.offset.y
break
case 'bottom-left':
x = this.config.offset.x;
y = workAreaSize.height - this.config.size.height - this.config.offset.y;
break;
x = this.config.offset.x
y = workAreaSize.height - this.config.size.height - this.config.offset.y
break
case 'bottom-right':
default:
x = workAreaSize.width - this.config.size.width - this.config.offset.x;
y = workAreaSize.height - this.config.size.height - this.config.offset.y;
break;
x = workAreaSize.width - this.config.size.width - this.config.offset.x
y = workAreaSize.height - this.config.size.height - this.config.offset.y
break
}

return { x, y };
return { x, y }
}

/**
* 设置窗口事件监听
*/
private setupWindowEvents(): void {
if (!this.window) {
return;
return
}

// 窗口关闭事件
this.window.on('closed', () => {
this.window = null;
this.state.isVisible = false;
});
this.window = null
this.state.isVisible = false
})

// 窗口移动事件
this.window.on('moved', () => {
if (this.window) {
const bounds = this.window.getBounds();
this.state.bounds.x = bounds.x;
this.state.bounds.y = bounds.y;
const bounds = this.window.getBounds()
this.state.bounds.x = bounds.x
this.state.bounds.y = bounds.y
}
});
})

// 注意:悬浮按钮点击事件的 IPC 处理器在主进程的 index.ts 中设置
}
Expand Down
Loading