@talex-touch/utils 1.0.32 → 1.0.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/common/file-scan-utils.ts +0 -1
- package/common/storage/constants.ts +1 -0
- package/common/utils/polling.ts +2 -1
- package/core-box/index.ts +1 -0
- package/core-box/recommendation.ts +77 -0
- package/electron/index.ts +1 -1
- package/index.ts +1 -0
- package/market/constants.ts +95 -0
- package/market/index.ts +2 -0
- package/market/types.ts +118 -0
- package/package.json +1 -1
- package/plugin/index.ts +1 -0
- package/plugin/sdk/README.md +216 -0
- package/plugin/sdk/box-sdk.ts +219 -0
- package/plugin/sdk/feature-sdk.ts +235 -0
- package/plugin/sdk/index.ts +2 -0
- package/plugin/sdk/types.ts +21 -8
- package/plugin/widget.ts +25 -0
- package/renderer/storage/intelligence-storage.ts +12 -9
- package/renderer/storage/storage-subscription.ts +196 -0
- package/types/icon.ts +7 -0
- package/types/intelligence.ts +198 -4
- package/types/update.ts +12 -0
- package/electron/clipboard-helper.ts +0 -207
package/common/utils/polling.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
1
2
|
/**
|
|
2
3
|
* @module polling
|
|
3
4
|
* A high-precision, efficient, singleton polling service for scheduling periodic tasks.
|
|
@@ -75,7 +76,7 @@ export class PollingService {
|
|
|
75
76
|
nextRunMs,
|
|
76
77
|
})
|
|
77
78
|
|
|
78
|
-
console.
|
|
79
|
+
console.debug(`[PollingService] Task '${id}' registered to run every ${options.interval} ${options.unit}.`)
|
|
79
80
|
|
|
80
81
|
if (this.isRunning) {
|
|
81
82
|
this._reschedule()
|
package/core-box/index.ts
CHANGED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Time-based usage pattern context for recommendation matching.
|
|
3
|
+
*/
|
|
4
|
+
export interface TimePattern {
|
|
5
|
+
/** Hour of day (0-23) */
|
|
6
|
+
hourOfDay: number
|
|
7
|
+
/** Day of week (0-6, 0=Sunday) */
|
|
8
|
+
dayOfWeek: number
|
|
9
|
+
/** Whether current time falls within working hours (9-18, weekdays) */
|
|
10
|
+
isWorkingHours: boolean
|
|
11
|
+
/** Broad time categorization */
|
|
12
|
+
timeSlot: 'morning' | 'afternoon' | 'evening' | 'night'
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Complete contextual signal for recommendation matching.
|
|
17
|
+
* Gathered from system state, clipboard, and active applications.
|
|
18
|
+
*/
|
|
19
|
+
export interface ContextSignal {
|
|
20
|
+
time: TimePattern
|
|
21
|
+
clipboard?: {
|
|
22
|
+
type: string
|
|
23
|
+
/** Hashed content for privacy (not original text) */
|
|
24
|
+
content: string
|
|
25
|
+
timestamp: number
|
|
26
|
+
contentType?: 'url' | 'text' | 'code' | 'file'
|
|
27
|
+
meta?: {
|
|
28
|
+
isUrl?: boolean
|
|
29
|
+
urlDomain?: string
|
|
30
|
+
textLength?: number
|
|
31
|
+
fileExtension?: string
|
|
32
|
+
fileType?: 'code' | 'text' | 'image' | 'document' | 'other'
|
|
33
|
+
language?: string
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
foregroundApp?: {
|
|
37
|
+
bundleId: string
|
|
38
|
+
name: string
|
|
39
|
+
}
|
|
40
|
+
systemState?: {
|
|
41
|
+
isOnline: boolean
|
|
42
|
+
batteryLevel: number
|
|
43
|
+
isDNDEnabled: boolean
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Scored recommendation item from recommendation engine.
|
|
49
|
+
*/
|
|
50
|
+
export interface ScoredItem {
|
|
51
|
+
sourceId: string
|
|
52
|
+
itemId: string
|
|
53
|
+
score: number
|
|
54
|
+
source: 'frequent' | 'time-based' | 'recent' | 'trending' | 'context'
|
|
55
|
+
reason?: string
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Recommendation badge display configuration for UI rendering.
|
|
60
|
+
*/
|
|
61
|
+
export interface RecommendationBadge {
|
|
62
|
+
text: string
|
|
63
|
+
icon: string
|
|
64
|
+
variant: 'frequent' | 'intelligent' | 'recent' | 'trending'
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Enhanced item metadata for intelligent recommendations.
|
|
69
|
+
* Attached to TuffItem.meta for rendering and filtering.
|
|
70
|
+
*/
|
|
71
|
+
export interface RecommendationMetadata {
|
|
72
|
+
score: number
|
|
73
|
+
source: ScoredItem['source']
|
|
74
|
+
reason: string
|
|
75
|
+
isIntelligent: boolean
|
|
76
|
+
badge: RecommendationBadge
|
|
77
|
+
}
|
package/electron/index.ts
CHANGED
package/index.ts
CHANGED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { StorageList } from '../common/storage/constants'
|
|
2
|
+
import type {
|
|
3
|
+
MarketProviderDefinition,
|
|
4
|
+
MarketSourcesPayload,
|
|
5
|
+
MarketSourcesStorageInfo,
|
|
6
|
+
MarketProviderTrustLevel,
|
|
7
|
+
} from './types'
|
|
8
|
+
|
|
9
|
+
export const MARKET_SOURCES_STORAGE_KEY = StorageList.MARKET_SOURCES
|
|
10
|
+
export const MARKET_SOURCES_STORAGE_VERSION = 1
|
|
11
|
+
|
|
12
|
+
function defineProvider(
|
|
13
|
+
provider: Omit<MarketProviderDefinition, 'trustLevel'> & {
|
|
14
|
+
trustLevel?: MarketProviderTrustLevel
|
|
15
|
+
},
|
|
16
|
+
): MarketProviderDefinition {
|
|
17
|
+
return {
|
|
18
|
+
trustLevel: provider.trustLevel ?? 'unverified',
|
|
19
|
+
...provider,
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const DEFAULT_MARKET_PROVIDERS: MarketProviderDefinition[] = [
|
|
24
|
+
defineProvider({
|
|
25
|
+
id: 'talex-official',
|
|
26
|
+
name: 'Talex Official',
|
|
27
|
+
type: 'nexusStore',
|
|
28
|
+
url: 'https://raw.githubusercontent.com/talex-touch/tuff-official-plugins/main/plugins.json',
|
|
29
|
+
description: '官方插件市场,提供经过审核的核心插件。',
|
|
30
|
+
enabled: true,
|
|
31
|
+
priority: 100,
|
|
32
|
+
trustLevel: 'official',
|
|
33
|
+
readOnly: true,
|
|
34
|
+
config: {
|
|
35
|
+
manifestUrl:
|
|
36
|
+
'https://raw.githubusercontent.com/talex-touch/tuff-official-plugins/main/plugins.json',
|
|
37
|
+
baseUrl: 'https://raw.githubusercontent.com/talex-touch/tuff-official-plugins/main/',
|
|
38
|
+
},
|
|
39
|
+
}),
|
|
40
|
+
defineProvider({
|
|
41
|
+
id: 'github-releases',
|
|
42
|
+
name: 'GitHub Releases',
|
|
43
|
+
type: 'repository',
|
|
44
|
+
description: '从 GitHub 仓库 releases / manifest 中读取插件。',
|
|
45
|
+
enabled: false,
|
|
46
|
+
priority: 80,
|
|
47
|
+
trustLevel: 'unverified',
|
|
48
|
+
config: {
|
|
49
|
+
platform: 'github',
|
|
50
|
+
apiBase: 'https://api.github.com',
|
|
51
|
+
},
|
|
52
|
+
}),
|
|
53
|
+
defineProvider({
|
|
54
|
+
id: 'gitee-repos',
|
|
55
|
+
name: 'Gitee 仓库',
|
|
56
|
+
type: 'repository',
|
|
57
|
+
description: 'Gitee 平台插件仓库,适合国内网络。',
|
|
58
|
+
enabled: false,
|
|
59
|
+
priority: 70,
|
|
60
|
+
trustLevel: 'unverified',
|
|
61
|
+
config: {
|
|
62
|
+
platform: 'gitee',
|
|
63
|
+
apiBase: 'https://gitee.com/api/v5',
|
|
64
|
+
},
|
|
65
|
+
}),
|
|
66
|
+
defineProvider({
|
|
67
|
+
id: 'npm-scope',
|
|
68
|
+
name: 'NPM 包',
|
|
69
|
+
type: 'npmPackage',
|
|
70
|
+
description: '基于 NPM 关键字或 scope 的插件发布渠道。',
|
|
71
|
+
enabled: false,
|
|
72
|
+
priority: 60,
|
|
73
|
+
trustLevel: 'unverified',
|
|
74
|
+
config: {
|
|
75
|
+
registryUrl: 'https://registry.npmjs.org',
|
|
76
|
+
keyword: 'talex-touch-plugin',
|
|
77
|
+
},
|
|
78
|
+
}),
|
|
79
|
+
]
|
|
80
|
+
|
|
81
|
+
export const MARKET_SOURCES_STORAGE_INFO: MarketSourcesStorageInfo = {
|
|
82
|
+
storageKey: MARKET_SOURCES_STORAGE_KEY,
|
|
83
|
+
version: MARKET_SOURCES_STORAGE_VERSION,
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function createDefaultMarketSourcesPayload(): MarketSourcesPayload {
|
|
87
|
+
const clone = typeof structuredClone === 'function'
|
|
88
|
+
? structuredClone(DEFAULT_MARKET_PROVIDERS)
|
|
89
|
+
: JSON.parse(JSON.stringify(DEFAULT_MARKET_PROVIDERS))
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
version: MARKET_SOURCES_STORAGE_VERSION,
|
|
93
|
+
sources: clone,
|
|
94
|
+
}
|
|
95
|
+
}
|
package/market/index.ts
ADDED
package/market/types.ts
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import type { StorageList } from '../common/storage/constants'
|
|
2
|
+
|
|
3
|
+
export type MarketProviderType = 'repository' | 'nexusStore' | 'npmPackage'
|
|
4
|
+
|
|
5
|
+
export type MarketProviderTrustLevel = 'official' | 'verified' | 'unverified'
|
|
6
|
+
|
|
7
|
+
export interface MarketProviderDefinition {
|
|
8
|
+
id: string
|
|
9
|
+
name: string
|
|
10
|
+
type: MarketProviderType
|
|
11
|
+
/**
|
|
12
|
+
* Base URL or identifier for the provider.
|
|
13
|
+
* Individual provider implementations can interpret this differently.
|
|
14
|
+
*/
|
|
15
|
+
url?: string
|
|
16
|
+
/**
|
|
17
|
+
* Additional configuration object for provider specific options.
|
|
18
|
+
*/
|
|
19
|
+
config?: Record<string, any>
|
|
20
|
+
description?: string
|
|
21
|
+
enabled: boolean
|
|
22
|
+
priority: number
|
|
23
|
+
trustLevel?: MarketProviderTrustLevel
|
|
24
|
+
tags?: string[]
|
|
25
|
+
/**
|
|
26
|
+
* Whether this provider should be treated as read-only (no install)
|
|
27
|
+
*/
|
|
28
|
+
readOnly?: boolean
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface MarketSourcesPayload {
|
|
32
|
+
/**
|
|
33
|
+
* Schema version, used for migrations.
|
|
34
|
+
*/
|
|
35
|
+
version: number
|
|
36
|
+
sources: MarketProviderDefinition[]
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type MarketInstallInstruction =
|
|
40
|
+
| {
|
|
41
|
+
type: 'url'
|
|
42
|
+
url: string
|
|
43
|
+
format?: 'zip' | 'tar' | 'tgz' | 'tpex'
|
|
44
|
+
integrity?: string
|
|
45
|
+
}
|
|
46
|
+
| {
|
|
47
|
+
type: 'npm'
|
|
48
|
+
packageName: string
|
|
49
|
+
version?: string
|
|
50
|
+
registry?: string
|
|
51
|
+
}
|
|
52
|
+
| {
|
|
53
|
+
type: 'git'
|
|
54
|
+
repo: string
|
|
55
|
+
ref?: string
|
|
56
|
+
sparse?: boolean
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface MarketPlugin {
|
|
60
|
+
id: string
|
|
61
|
+
name: string
|
|
62
|
+
version?: string
|
|
63
|
+
description?: string
|
|
64
|
+
category?: string
|
|
65
|
+
tags?: string[]
|
|
66
|
+
author?: string
|
|
67
|
+
icon?: string
|
|
68
|
+
metadata?: Record<string, unknown>
|
|
69
|
+
readmeUrl?: string
|
|
70
|
+
homepage?: string
|
|
71
|
+
downloadUrl?: string
|
|
72
|
+
install?: MarketInstallInstruction
|
|
73
|
+
providerId: string
|
|
74
|
+
providerName: string
|
|
75
|
+
providerType: MarketProviderType
|
|
76
|
+
providerTrustLevel: MarketProviderTrustLevel
|
|
77
|
+
trusted: boolean
|
|
78
|
+
official?: boolean
|
|
79
|
+
timestamp?: number | string
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface MarketProviderResultMeta {
|
|
83
|
+
providerId: string
|
|
84
|
+
providerName: string
|
|
85
|
+
providerType: MarketProviderType
|
|
86
|
+
success: boolean
|
|
87
|
+
error?: string
|
|
88
|
+
fetchedAt: number
|
|
89
|
+
itemCount: number
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface MarketProviderListOptions {
|
|
93
|
+
keyword?: string
|
|
94
|
+
force?: boolean
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export interface MarketHttpRequestOptions {
|
|
98
|
+
url: string
|
|
99
|
+
method?: 'GET' | 'POST' | 'PUT' | 'DELETE'
|
|
100
|
+
headers?: Record<string, string>
|
|
101
|
+
params?: Record<string, any>
|
|
102
|
+
data?: any
|
|
103
|
+
timeout?: number
|
|
104
|
+
responseType?: 'json' | 'text' | 'arraybuffer'
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export interface MarketHttpResponse<T = unknown> {
|
|
108
|
+
status: number
|
|
109
|
+
statusText: string
|
|
110
|
+
headers: Record<string, string>
|
|
111
|
+
data: T
|
|
112
|
+
url: string
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export interface MarketSourcesStorageInfo {
|
|
116
|
+
storageKey: StorageList
|
|
117
|
+
version: number
|
|
118
|
+
}
|
package/package.json
CHANGED
package/plugin/index.ts
CHANGED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# Plugin SDK 重构说明
|
|
2
|
+
|
|
3
|
+
## 概述
|
|
4
|
+
|
|
5
|
+
Plugin SDK 已重构为统一的工厂函数模式,参考 `DivisionBoxSDK` 的设计。旧版本 API 已废弃,调用时会抛出错误。
|
|
6
|
+
|
|
7
|
+
## 新的 SDK 结构
|
|
8
|
+
|
|
9
|
+
### 1. BoxSDK - CoreBox 窗口控制
|
|
10
|
+
|
|
11
|
+
控制 CoreBox 窗口的显示、大小和输入框状态。
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
// 隐藏/显示 CoreBox
|
|
15
|
+
plugin.box.hide()
|
|
16
|
+
plugin.box.show()
|
|
17
|
+
|
|
18
|
+
// 扩展窗口(显示更多结果)
|
|
19
|
+
plugin.box.expand({ length: 10 })
|
|
20
|
+
plugin.box.expand({ forceMax: true })
|
|
21
|
+
|
|
22
|
+
// 收缩窗口
|
|
23
|
+
plugin.box.shrink()
|
|
24
|
+
|
|
25
|
+
// 控制输入框
|
|
26
|
+
plugin.box.hideInput()
|
|
27
|
+
plugin.box.showInput()
|
|
28
|
+
|
|
29
|
+
// 获取当前输入
|
|
30
|
+
const input = await plugin.box.getInput()
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 2. FeatureSDK - 搜索结果管理
|
|
34
|
+
|
|
35
|
+
管理插件推送的搜索结果项(TuffItems)。
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
// 推送多个结果
|
|
39
|
+
plugin.feature.pushItems([
|
|
40
|
+
{ id: 'item-1', title: { text: 'Result 1' }, ... },
|
|
41
|
+
{ id: 'item-2', title: { text: 'Result 2' }, ... }
|
|
42
|
+
])
|
|
43
|
+
|
|
44
|
+
// 更新单个结果
|
|
45
|
+
plugin.feature.updateItem('item-1', {
|
|
46
|
+
title: { text: 'Updated Title' }
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
// 删除单个结果
|
|
50
|
+
plugin.feature.removeItem('item-1')
|
|
51
|
+
|
|
52
|
+
// 清空所有结果
|
|
53
|
+
plugin.feature.clearItems()
|
|
54
|
+
|
|
55
|
+
// 获取所有结果
|
|
56
|
+
const items = plugin.feature.getItems()
|
|
57
|
+
|
|
58
|
+
// 监听输入变化(实时搜索)
|
|
59
|
+
const unsubscribe = plugin.feature.onInputChange((input) => {
|
|
60
|
+
console.log('User typed:', input)
|
|
61
|
+
// 执行实时搜索
|
|
62
|
+
performSearch(input)
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
// 取消监听
|
|
66
|
+
unsubscribe()
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## 废弃的 API
|
|
70
|
+
|
|
71
|
+
以下 API 已废弃,调用时会抛出错误:
|
|
72
|
+
|
|
73
|
+
### 旧的 Box API
|
|
74
|
+
```typescript
|
|
75
|
+
// ❌ 废弃
|
|
76
|
+
plugin.$box.hide()
|
|
77
|
+
plugin.$box.show()
|
|
78
|
+
|
|
79
|
+
// ✅ 使用新 API
|
|
80
|
+
plugin.box.hide()
|
|
81
|
+
plugin.box.show()
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 旧的 Feature API
|
|
85
|
+
```typescript
|
|
86
|
+
// ❌ 废弃
|
|
87
|
+
plugin.pushItems(items)
|
|
88
|
+
plugin.clearItems()
|
|
89
|
+
plugin.getItems()
|
|
90
|
+
|
|
91
|
+
// ✅ 使用新 API
|
|
92
|
+
plugin.feature.pushItems(items)
|
|
93
|
+
plugin.feature.clearItems()
|
|
94
|
+
plugin.feature.getItems()
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## 迁移指南
|
|
98
|
+
|
|
99
|
+
### 1. 更新 Box 控制代码
|
|
100
|
+
|
|
101
|
+
**旧代码:**
|
|
102
|
+
```typescript
|
|
103
|
+
plugin.$box.hide()
|
|
104
|
+
plugin.$box.show()
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**新代码:**
|
|
108
|
+
```typescript
|
|
109
|
+
plugin.box.hide()
|
|
110
|
+
plugin.box.show()
|
|
111
|
+
plugin.box.expand({ length: 10 })
|
|
112
|
+
plugin.box.shrink()
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### 2. 更新搜索结果管理
|
|
116
|
+
|
|
117
|
+
**旧代码:**
|
|
118
|
+
```typescript
|
|
119
|
+
plugin.pushItems([...])
|
|
120
|
+
plugin.clearItems()
|
|
121
|
+
const items = plugin.getItems()
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**新代码:**
|
|
125
|
+
```typescript
|
|
126
|
+
plugin.feature.pushItems([...])
|
|
127
|
+
plugin.feature.updateItem('id', { ... })
|
|
128
|
+
plugin.feature.removeItem('id')
|
|
129
|
+
plugin.feature.clearItems()
|
|
130
|
+
const items = plugin.feature.getItems()
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### 3. 添加实时搜索支持
|
|
134
|
+
|
|
135
|
+
**新功能:**
|
|
136
|
+
```typescript
|
|
137
|
+
// 在插件初始化时注册监听器
|
|
138
|
+
onInit(context) {
|
|
139
|
+
context.utils.feature.onInputChange((input) => {
|
|
140
|
+
// 用户输入变化时触发
|
|
141
|
+
this.performRealTimeSearch(input)
|
|
142
|
+
})
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## 完整示例
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
export default {
|
|
150
|
+
onInit(context) {
|
|
151
|
+
const { feature, box } = context.utils
|
|
152
|
+
|
|
153
|
+
// 监听输入变化
|
|
154
|
+
feature.onInputChange((input) => {
|
|
155
|
+
if (input.length > 2) {
|
|
156
|
+
// 执行搜索
|
|
157
|
+
const results = performSearch(input)
|
|
158
|
+
feature.pushItems(results)
|
|
159
|
+
} else {
|
|
160
|
+
feature.clearItems()
|
|
161
|
+
}
|
|
162
|
+
})
|
|
163
|
+
},
|
|
164
|
+
|
|
165
|
+
onFeatureTriggered(featureId, query, feature) {
|
|
166
|
+
const { feature: featureSDK, box } = this.context.utils
|
|
167
|
+
|
|
168
|
+
// 推送结果
|
|
169
|
+
featureSDK.pushItems([
|
|
170
|
+
{
|
|
171
|
+
id: 'result-1',
|
|
172
|
+
title: { text: 'Search Result' },
|
|
173
|
+
subtitle: { text: 'Description' },
|
|
174
|
+
source: { id: this.pluginName, name: this.pluginName }
|
|
175
|
+
}
|
|
176
|
+
])
|
|
177
|
+
|
|
178
|
+
// 扩展窗口显示结果
|
|
179
|
+
box.expand({ length: 5 })
|
|
180
|
+
|
|
181
|
+
// 3秒后隐藏
|
|
182
|
+
setTimeout(() => {
|
|
183
|
+
box.hide()
|
|
184
|
+
}, 3000)
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## 技术细节
|
|
190
|
+
|
|
191
|
+
### SDK 工厂函数
|
|
192
|
+
|
|
193
|
+
所有 SDK 都通过工厂函数创建:
|
|
194
|
+
|
|
195
|
+
- `createBoxSDK(channel)` - 创建 Box SDK 实例
|
|
196
|
+
- `createFeatureSDK(boxItems, channel)` - 创建 Feature SDK 实例
|
|
197
|
+
- `createDivisionBoxSDK(channel)` - 创建 DivisionBox SDK 实例
|
|
198
|
+
|
|
199
|
+
### IPC 通道
|
|
200
|
+
|
|
201
|
+
新增的 IPC 通道:
|
|
202
|
+
|
|
203
|
+
- `core-box:hide-input` - 隐藏输入框
|
|
204
|
+
- `core-box:show-input` - 显示输入框
|
|
205
|
+
- `core-box:get-input` - 获取当前输入值
|
|
206
|
+
- `core-box:input-changed` - 输入变化广播(主进程 → 插件)
|
|
207
|
+
- `core-box:set-input-visibility` - 设置输入框可见性(主进程 → 渲染进程)
|
|
208
|
+
- `core-box:request-input-value` - 请求输入值(主进程 → 渲染进程)
|
|
209
|
+
|
|
210
|
+
### 架构优势
|
|
211
|
+
|
|
212
|
+
1. **统一的 API 风格** - 所有 SDK 使用相同的工厂函数模式
|
|
213
|
+
2. **更好的类型安全** - TypeScript 类型定义完整
|
|
214
|
+
3. **功能分离** - Box 控制和 Feature 管理职责清晰
|
|
215
|
+
4. **扩展性强** - 易于添加新功能
|
|
216
|
+
5. **向后不兼容** - 强制迁移到新 API,避免技术债务
|