性能优化

This commit is contained in:
zhongluofeng
2026-08-06 10:33:16 +08:00
parent c7578a2e6b
commit e66c53e66d
105 changed files with 7273 additions and 5002 deletions
+113
View File
@@ -0,0 +1,113 @@
/**
* app Provider:扫描开始菜单应用。
* 1 分钟缓存减少重复 IPC;图标按需加载(前端 Map 缓存,避免重复请求)。
*/
import { invoke } from '@tauri-apps/api/core'
import { bestScore } from '../engine'
import type { QPItem, QPProvider } from './types'
import { buildItemForms, makeAppLaunch, makeAppSubActions } from './utils'
interface AppRecord {
name: string
path: string
}
let appCache: AppRecord[] | null = null
let appCacheTime = 0
const APP_CACHE_TTL = 60_000 // 1 分钟缓存
async function loadApps(): Promise<AppRecord[]> {
if (appCache && Date.now() - appCacheTime < APP_CACHE_TTL) {
return appCache
}
try {
const apps = await invoke<AppRecord[]>('quickpanel_scan_apps')
appCache = apps
appCacheTime = Date.now()
return apps
} catch (e) {
console.error('[quickpanel] 扫描应用失败:', e)
return []
}
}
export class AppProvider implements QPProvider {
id = 'app'
label = '应用'
priority = 95
async search(query: string): Promise<QPItem[]> {
const apps = await loadApps()
if (!query.trim()) {
// 空查询:不显示应用(避免列表过长),由命令入口承担
return []
}
const results: Array<{ item: QPItem; score: number }> = []
let idx = 0
for (const app of apps) {
const forms = buildItemForms(app.name)
const score = bestScore(query, forms)
if (score >= 0) {
results.push({
item: {
id: `app-${idx}`,
title: app.name,
subtitle: app.path,
group: '应用',
iconPath: app.path,
action: makeAppLaunch(app.path),
subActions: makeAppSubActions(app.path),
appRank: 0, // 开始菜单:最可靠来源
},
score,
})
}
idx++
}
results.sort((a, b) => b.score - a.score)
return results.slice(0, 15).map(r => ({ ...r.item, score: r.score }))
}
}
// ===== 应用图标按需加载 =====
// 前端缓存(path -> dataUrl)。Rust 侧另有内存 + 磁盘缓存,此处仅避免重复 IPC。
const appIconCache = new Map<string, string>() // path -> dataUrl('' = 无图标)
/** 为搜索结果中带 iconPath 的项(应用、历史中的应用)按需加载图标(data URL),
* 并写入 item.iconUrl 触发响应式更新。
* 命中前端缓存时同步返回;否则异步调用 Rust 命令(命中 Rust 缓存则零开销)。 */
export async function loadAppIconsForResults(items: QPItem[]): Promise<void> {
const toLoad: QPItem[] = []
for (const item of items) {
if (!item.iconPath) continue
if (item.iconUrl !== undefined) continue // 已设置(含加载中)
const cached = appIconCache.get(item.iconPath)
if (cached !== undefined) {
item.iconUrl = cached
} else {
item.iconUrl = '' // 标记加载中,避免重复请求
toLoad.push(item)
}
}
if (!toLoad.length) return
await Promise.all(
toLoad.map(async item => {
const path = item.iconPath!
try {
const url = await invoke<string | null>('quickpanel_get_app_icon', { path })
const u = url ?? ''
appIconCache.set(path, u)
item.iconUrl = u
} catch {
appIconCache.set(path, '')
item.iconUrl = ''
}
}),
)
}
/** 清空前端图标缓存(Rust 端清理命令 quickpanel_clear_app_icon_cache 调用后可一并清空) */
export function invalidateAppIconCache() {
appIconCache.clear()
}