Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
f572175
feat(plugin-sdk): add setInput and clearInput methods to BoxSDK
TalexDreamSoul Dec 1, 2025
c41559c
chore(utils): bump version to 1.0.35
TalexDreamSoul Dec 1, 2025
c11db4a
refactor(sdk): improve channel communication logic
TalexDreamSoul Dec 1, 2025
9d77125
feat(core-app): add URL processor for handling custom protocols
TalexDreamSoul Dec 1, 2025
9e0df8e
fix(sdk): correct `this` context in async channel operations
TalexDreamSoul Dec 1, 2025
03895f6
fix(channel): correct plugin channel types and improve async handler …
TalexDreamSoul Dec 1, 2025
741f547
feat(clipboard): add advanced search and filtering to clipboard history
TalexDreamSoul Dec 1, 2025
5258599
fix(core-box): correct input event handling and keyboard propagation
TalexDreamSoul Dec 2, 2025
735bfeb
feat(core-box): improve search relevance and keyboard navigation
TalexDreamSoul Dec 2, 2025
26f41ec
feat(search): improve feature search relevance with token-based matching
TalexDreamSoul Dec 2, 2025
958ba0e
feat(core-box): only autofill from clipboard when opened via shortcut
TalexDreamSoul Dec 2, 2025
2ba3cf4
chore: release v2.4.7-beta.7
TalexDreamSoul Dec 2, 2025
586703b
feat(core-box): make clipboard autopaste conditional on shortcut trigger
TalexDreamSoul Dec 2, 2025
cb00eb3
fix(ui): improve plugin icon display and dark mode visibility
TalexDreamSoul Dec 2, 2025
317e203
chore(core-box): remove unnecessary comments
TalexDreamSoul Dec 2, 2025
c236932
feat(plugin): introduce processor-based widget compiler and sandboxed…
TalexDreamSoul Dec 3, 2025
9c78f50
feat(storage): implement persistent storage for prompts and sessions
TalexDreamSoul Dec 5, 2025
f162b43
feat(core-box): add keyboard event forwarding for plugin ui view
TalexDreamSoul Dec 6, 2025
acf22f1
Update apps/core-app/src/renderer/src/modules/hooks/useUrlProcessor.ts
TalexDreamSoul Dec 6, 2025
31609e9
Update apps/core-app/src/renderer/src/modules/hooks/useUrlProcessor.ts
TalexDreamSoul Dec 6, 2025
4d03022
Update apps/core-app/src/renderer/src/modules/box/adapter/transport/c…
TalexDreamSoul Dec 6, 2025
293d924
fix(core-box,plugin,renderer): add window availability checks and imp…
TalexDreamSoul Dec 6, 2025
574ce35
Merge branch 'fix/2.4.7-251201' of https://github.com/talex-touch/tuf…
TalexDreamSoul Dec 6, 2025
9868e2e
Update apps/core-app/src/main/modules/plugin/widget/widget-processor.ts
TalexDreamSoul Dec 6, 2025
33d1482
Update apps/core-app/src/main/modules/box-tool/search-engine/sort/tuf…
TalexDreamSoul Dec 6, 2025
783f142
Update plugins/touch-translation/widgets/TestWidget.vue
TalexDreamSoul Dec 6, 2025
eb94d5f
fix(widget): enhance module import detection and sandbox validation
TalexDreamSoul Dec 6, 2025
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 apps/core-app/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@talex-touch/core-app",
"version": "2.4.7-beta.6",
"version": "2.4.7-beta.7",
"description": "A strong adaptation more platform all-tool program.",
"author": "TalexDreamSoul <TalexDreamSoul@Gmail.com>",
"license": "MPL-2.0 license",
Expand Down
13 changes: 13 additions & 0 deletions apps/core-app/plan-prd/01-project/TODO_PLAN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# TODO 精简清单

聚焦代码内显式 TODO 以及 PRD 补档需求,按优先级列出。

## P0-P1 立即处理
- [x] 存储:`src/renderer/src/modules/hooks/usePromptManager.ts` 自定义提示词落地 TouchStorage,移除 console 占坑
- [x] 存储:`src/renderer/src/modules/division-box/store/division-box.ts` 固定列表改用 TouchStorage,告别 localStorage
- [ ] 下载中心:`useDownloadCenter.ts` 删除任务 API,`DownloadCenterView.vue` 优先级调整 API 接入,避免假动作

## 其他待办(按模块)
- 主进程/核心:`analytics/startup-analytics.ts` 上报实现;`extension-loader.ts` 卸载流程;`plugin-installer.ts` 安装校验升级;`plugin-log.service.ts` 日志格式化;`tray-menu-builder.ts` 接 CoreBox/Terminal;`search-core.ts` 性能与索引刷新;`file-provider.ts` 向量嵌入接入
- 渲染层:智能统计视图数据源落地(`IntelligenceCapabilities.vue`、`IntelligenceChannels.vue`、`IntelligencePrompts.vue`);`modules/channel/plugin-core/index.ts` 补插件核心 API;Prompt 管理与分屏存储见上;下载中心见上
- 文档:PRD 中的搜索优化/AI Agent 相关条目只列标题,缺实现链接和进度标记,需要补全或下线
3 changes: 2 additions & 1 deletion apps/core-app/plan-prd/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

### 项目架构
- [PROJECT_ANALYSIS.md](01-project/PROJECT_ANALYSIS.md) - 项目架构分析
- [TODO_PLAN.md](01-project/TODO_PLAN.md) - TODO 精简与优先级清单

### 搜索功能
- [TUFF_USAGE_TRACKING_PRD.md](03-features/search/TUFF_USAGE_TRACKING_PRD.md) - 使用跟踪需求文档
Expand All @@ -56,4 +57,4 @@
### 性能优化
- [PERFORMANCE_OPTIMIZATIONS.md](04-implementation/performance/PERFORMANCE_OPTIMIZATIONS.md) - 性能优化详解
- [PERFORMANCE_QUICK_REFERENCE.md](04-implementation/performance/PERFORMANCE_QUICK_REFERENCE.md) - 性能快速参考
- [PROGRESS_TRACKER_USAGE.md](04-implementation/performance/PROGRESS_TRACKER_USAGE.md) - 进度跟踪使用指南
- [PROGRESS_TRACKER_USAGE.md](04-implementation/performance/PROGRESS_TRACKER_USAGE.md) - 进度跟踪使用指南
116 changes: 51 additions & 65 deletions apps/core-app/src/main/core/channel-core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type {
ITouchChannel,
RawChannelSyncData,
RawStandardChannelData,
StandardChannelData,
StandardChannelData
} from '@talex-touch/utils/channel'
import type { WebContentsView } from 'electron'
import type { TalexTouch } from '../types'
Expand Down Expand Up @@ -74,13 +74,13 @@ class TouchChannel implements ITouchChannel {
type: pluginName ? ChannelType.PLUGIN : ChannelType.MAIN,
_originData: arg,
event: e,
uniqueKey: uniqueKey as string,
uniqueKey: uniqueKey as string
},
sync: sync as RawChannelSyncData | undefined,
code: code as DataCode,
data: data as IChannelData,
plugin: pluginName,
name: name as string,
name: name as string
}
}
}
Expand All @@ -100,8 +100,7 @@ class TouchChannel implements ITouchChannel {

const map = this.channelMap.get(rawData.header.type)

if (!map)
throw new Error('Invalid channel type!')
if (!map) throw new Error('Invalid channel type!')

map.get(rawData.name)?.forEach((func) => {
let _replied = false
Expand All @@ -127,49 +126,44 @@ class TouchChannel implements ITouchChannel {
// Check if sender is still valid before sending
if (e.sender.isDestroyed()) {
console.warn(
`[Channel] Cannot send reply for ${rawData.name} to destroyed webContents.`,
`[Channel] Cannot send reply for ${rawData.name} to destroyed webContents.`
)
return
}
e.sender.send(
`@${rawData.header.type === ChannelType.MAIN ? 'main' : 'plugin'}-process-message`,
finalData,
finalData
)
}
catch (error) {
} catch (error) {
// Handle EPIPE and other write errors
const errorMessage = error instanceof Error ? error.message : String(error)
if (errorMessage.includes('EPIPE') || errorMessage.includes('write')) {
console.warn(
`[Channel] EPIPE error when sending reply for ${rawData.name}: ${errorMessage}. WebContents may have crashed.`,
`[Channel] EPIPE error when sending reply for ${rawData.name}: ${errorMessage}. WebContents may have crashed.`
)
}
else {
} else {
console.error(`[Channel] Error sending reply for ${rawData.name}:`, error)
}
}
}
else {
} else {
try {
e.returnValue = finalData
}
catch (error) {
} catch (error) {
// Handle sync IPC errors
const errorMessage = error instanceof Error ? error.message : String(error)
console.warn(
`[Channel] Error setting returnValue for ${rawData.name}: ${errorMessage}`,
`[Channel] Error setting returnValue for ${rawData.name}: ${errorMessage}`
)
}
}
_replied = true
},
...rawData,
...rawData
}

const res = func(handInData)

if (res && res instanceof Promise)
return
if (res && res instanceof Promise) return

// Only auto-reply if the handler hasn't already replied
if (!_replied) {
Expand All @@ -182,10 +176,9 @@ class TouchChannel implements ITouchChannel {
code: DataCode,
rawData: RawStandardChannelData,
data: unknown,
sync?: RawChannelSyncData,
sync?: RawChannelSyncData
): RawStandardChannelData {
if (!rawData || !rawData.header)
throw new Error(`Invalid data!${JSON.stringify(rawData)}`)
if (!rawData || !rawData.header) throw new Error(`Invalid data!${JSON.stringify(rawData)}`)
return {
code,
data,
Expand All @@ -195,16 +188,16 @@ class TouchChannel implements ITouchChannel {
timeStamp: new Date().getTime(),
// reply sync timeout should follow the request timeout, unless user set it.
timeout: sync.timeout,
id: sync.id,
id: sync.id
},
name: rawData.name,
plugin: rawData.header.plugin || void 0,
header: {
event: rawData.header.event,
status: 'reply',
type: rawData.header.type,
_originData: rawData.header._originData,
},
_originData: rawData.header._originData
}
}
}

Expand Down Expand Up @@ -264,13 +257,13 @@ class TouchChannel implements ITouchChannel {
type: ChannelType,
eventName: string,
arg: any,
header: any = {},
header: any = {}
): Promise<any> {
const webContents = (win as any)?.webContents as Electron.WebContents | undefined

if (!webContents) {
console.warn(
`[Channel] Skip sending "${eventName}" because the target webContents is unavailable.`,
`[Channel] Skip sending "${eventName}" because the target webContents is unavailable.`
)

return Promise.resolve()
Expand All @@ -284,35 +277,35 @@ class TouchChannel implements ITouchChannel {
sync: {
timeStamp: new Date().getTime(),
timeout: CHANNEL_DEFAULT_TIMEOUT,
id: uniqueId,
id: uniqueId
},
name: eventName,
header: {
status: 'request',
type,
...header,
},
...header
}
} as RawStandardChannelData

let _channelCategory = '@main-process-message'

let finalData: RawStandardChannelData
try {
finalData = JSON.parse(structuredStrictStringify(data))
}
catch (error) {
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error)
console.error(
`[Channel] Failed to serialize payload for "${eventName}": ${errorMessage}`,
{ eventName, type, argSummary: this.__safePreview(arg) },
)
console.error(`[Channel] Failed to serialize payload for "${eventName}": ${errorMessage}`, {
eventName,
type,
argSummary: this.__safePreview(arg)
})
return Promise.resolve({
code: DataCode.ERROR,
data: {
message: errorMessage,
reason: 'serialize_failed',
eventName,
},
eventName
}
})
}

Expand All @@ -327,7 +320,7 @@ class TouchChannel implements ITouchChannel {
_channelCategory = '@plugin-process-message'
if (webContents.isDestroyed()) {
console.error(
`[Channel] Plugin process message for ${JSON.stringify(arg)} | ${JSON.stringify(header)} has been destroyed(webContentsView).`,
`[Channel] Plugin process message for ${JSON.stringify(arg)} | ${JSON.stringify(header)} has been destroyed(webContentsView).`
)
return Promise.resolve()
}
Expand All @@ -350,16 +343,14 @@ class TouchChannel implements ITouchChannel {
return
}
this.pendingMap.delete(uniqueId)
console.warn(
`[Channel] Request "${eventName}" timed out after ${timeoutMs}ms.`,
)
console.warn(`[Channel] Request "${eventName}" timed out after ${timeoutMs}ms.`)
resolve({
code: DataCode.ERROR,
data: {
message: `Channel request "${eventName}" timed out after ${timeoutMs}ms`,
reason: 'timeout',
eventName,
},
eventName
}
})
}, timeoutMs)

Expand All @@ -369,16 +360,14 @@ class TouchChannel implements ITouchChannel {

resolve(res)
})
}
catch (error) {
} catch (error) {
// Handle EPIPE and other write errors
const errorMessage = error instanceof Error ? error.message : String(error)
if (errorMessage.includes('EPIPE') || errorMessage.includes('write')) {
console.warn(
`[Channel] EPIPE error when sending "${eventName}": ${errorMessage}. WebContents may have crashed.`,
`[Channel] EPIPE error when sending "${eventName}": ${errorMessage}. WebContents may have crashed.`
)
}
else {
} else {
console.error(`[Channel] Error sending "${eventName}":`, error)
}

Expand All @@ -389,8 +378,8 @@ class TouchChannel implements ITouchChannel {
data: {
message: errorMessage,
reason: 'send_failed',
eventName,
},
eventName
}
})
}
})
Expand All @@ -400,7 +389,7 @@ class TouchChannel implements ITouchChannel {
win: Electron.BrowserWindow,
type: ChannelType,
eventName: string,
arg: any,
arg: any
): Promise<any> {
return this._sendTo(win, type, eventName, arg)
}
Expand All @@ -410,11 +399,11 @@ class TouchChannel implements ITouchChannel {
type: ChannelType,
eventName: string,
pluginName: string,
arg: any,
arg: any
): Promise<any> {
if (!win) {
console.warn(
`[Channel] Skip sending "${eventName}" to plugin "${pluginName}" because UI view is not ready.`,
`[Channel] Skip sending "${eventName}" to plugin "${pluginName}" because UI view is not ready.`
)

return Promise.resolve()
Expand All @@ -428,8 +417,8 @@ class TouchChannel implements ITouchChannel {
eventName,
{ ...arg, plugin: pluginName },
{
uniqueKey: key,
},
uniqueKey: key
}
)
}

Expand All @@ -455,7 +444,7 @@ class TouchChannel implements ITouchChannel {
ChannelType.PLUGIN,
eventName,
pluginName,
arg,
arg
)
}

Expand All @@ -465,7 +454,7 @@ class TouchChannel implements ITouchChannel {
ChannelType.PLUGIN,
eventName,
pluginName,
arg,
arg
)
}

Expand All @@ -477,14 +466,12 @@ class TouchChannel implements ITouchChannel {
* @returns A safely serializable preview of the payload
*/
private __safePreview(payload: unknown): unknown {
if (payload === null || payload === undefined)
return payload
if (payload === null || payload === undefined) return payload
if (typeof payload === 'string')
return payload.length > 200 ? `${payload.slice(0, 200)}…` : payload
try {
return JSON.parse(structuredStrictStringify(payload))
}
catch {
} catch {
return '[unserializable-payload]'
}
}
Expand All @@ -493,8 +480,7 @@ class TouchChannel implements ITouchChannel {
let touchChannel: ITouchChannel | null = null

export function genTouchChannel(app?: TalexTouch.TouchApp): ITouchChannel {
if (app && !touchChannel)
touchChannel = new TouchChannel(app)
if (app && !touchChannel) touchChannel = new TouchChannel(app)

return touchChannel!
}
6 changes: 4 additions & 2 deletions apps/core-app/src/main/modules/box-tool/core-box/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ export class CoreBoxModule extends BaseModule {
}
}
} else {
coreBoxManager.trigger(true)
// Pass triggeredByShortcut flag when opening CoreBox via shortcut
coreBoxManager.trigger(true, { triggeredByShortcut: true })
lastScreenId = curScreen.id
}
})
Expand All @@ -79,7 +80,8 @@ export class CoreBoxModule extends BaseModule {
windowManager.updatePosition(currentWindow, curScreen)
}

coreBoxManager.trigger(true)
// Also pass triggeredByShortcut for AI quick call
coreBoxManager.trigger(true, { triggeredByShortcut: true })
lastScreenId = curScreen.id

const targetWindow = windowManager.current?.window
Expand Down
Loading
Loading