@talex-touch/utils 1.0.31 → 1.0.33
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/animation/window-node.ts +15 -12
- package/animation/window.ts +19 -15
- package/auth/clerk-types.ts +1 -1
- package/auth/index.ts +1 -1
- package/auth/useAuthState.ts +6 -5
- package/auth/useClerkConfig.ts +4 -4
- package/auth/useClerkProvider.ts +3 -2
- package/channel/index.ts +23 -22
- package/common/file-scan-constants.ts +137 -121
- package/common/file-scan-utils.ts +48 -27
- package/common/index.ts +3 -3
- package/common/search/gather.ts +1 -1
- package/common/search/index.ts +5 -6
- package/common/storage/constants.ts +3 -2
- package/common/storage/entity/app-settings.ts +5 -3
- package/common/storage/entity/shortcut-settings.ts +10 -10
- package/common/storage/shortcut-storage.ts +6 -4
- package/common/utils/file.ts +14 -6
- package/common/utils/index.ts +62 -52
- package/common/utils/polling.ts +88 -84
- package/common/utils/task-queue.ts +11 -10
- package/common/utils/time.ts +50 -47
- package/common/utils/timing.ts +41 -37
- package/core-box/builder/index.ts +1 -1
- package/core-box/builder/tuff-builder.ts +254 -229
- package/core-box/index.ts +4 -6
- package/core-box/preview/index.ts +1 -0
- package/core-box/preview/types.ts +43 -0
- package/core-box/recommendation.ts +77 -0
- package/core-box/tuff/index.ts +1 -1
- package/core-box/tuff/tuff-dsl.ts +328 -266
- package/electron/download-manager.ts +43 -42
- package/electron/env-tool.ts +19 -18
- package/electron/file-parsers/index.ts +2 -2
- package/electron/file-parsers/parsers/text-parser.ts +15 -14
- package/electron/file-parsers/registry.ts +9 -7
- package/electron/file-parsers/types.ts +4 -4
- package/electron/index.ts +2 -2
- package/eventbus/index.ts +11 -11
- package/index.ts +5 -4
- package/intelligence/client.ts +87 -0
- package/intelligence/index.ts +1 -0
- package/package.json +14 -14
- package/permission/index.ts +8 -8
- package/plugin/channel.ts +77 -68
- package/plugin/index.ts +96 -82
- package/plugin/install.ts +8 -8
- package/plugin/log/types.ts +5 -5
- package/plugin/node/index.ts +1 -1
- package/plugin/node/logger-manager.ts +14 -11
- package/plugin/node/logger.ts +8 -8
- package/plugin/plugin-source.ts +11 -11
- package/plugin/preload.ts +1 -1
- package/plugin/providers/registry.ts +8 -7
- package/plugin/providers/types.ts +6 -6
- package/plugin/sdk/README.md +216 -0
- package/plugin/sdk/box-sdk.ts +219 -0
- package/plugin/sdk/channel.ts +20 -20
- package/plugin/sdk/clipboard.ts +8 -6
- package/plugin/sdk/common.ts +10 -6
- package/plugin/sdk/core-box.ts +2 -3
- package/plugin/sdk/division-box.ts +266 -0
- package/plugin/sdk/enum/bridge-event.ts +1 -1
- package/plugin/sdk/examples/storage-onDidChange-example.js +1 -1
- package/plugin/sdk/feature-sdk.ts +235 -0
- package/plugin/sdk/features.ts +34 -26
- package/plugin/sdk/hooks/bridge.ts +3 -6
- package/plugin/sdk/hooks/index.ts +1 -1
- package/plugin/sdk/hooks/life-cycle.ts +4 -10
- package/plugin/sdk/index.ts +10 -7
- package/plugin/sdk/service/index.ts +3 -3
- package/plugin/sdk/storage.ts +4 -4
- package/plugin/sdk/system.ts +1 -1
- package/plugin/sdk/types.ts +165 -146
- package/plugin/sdk/window/index.ts +8 -5
- package/preload/loading.ts +6 -6
- package/preload/renderer.ts +4 -2
- package/renderer/hooks/arg-mapper.ts +1 -2
- package/renderer/hooks/index.ts +2 -0
- package/renderer/hooks/initialize.ts +10 -8
- package/renderer/hooks/performance.ts +4 -4
- package/renderer/hooks/use-channel.ts +150 -0
- package/renderer/hooks/use-intelligence.ts +236 -0
- package/renderer/index.ts +6 -2
- package/renderer/ref.ts +32 -36
- package/renderer/slots.ts +29 -26
- package/renderer/storage/app-settings.ts +16 -6
- package/renderer/storage/base-storage.ts +222 -114
- package/renderer/storage/index.ts +3 -0
- package/renderer/storage/intelligence-storage.ts +218 -0
- package/renderer/storage/openers.ts +13 -3
- package/renderer/touch-sdk/env.ts +41 -41
- package/renderer/touch-sdk/index.ts +1 -1
- package/renderer/touch-sdk/terminal.ts +5 -5
- package/renderer/touch-sdk/utils.ts +4 -3
- package/search/levenshtein-utils.ts +11 -11
- package/search/types.ts +102 -102
- package/service/index.ts +11 -11
- package/service/protocol/index.ts +217 -14
- package/types/division-box.ts +248 -0
- package/types/download.ts +72 -34
- package/types/index.ts +3 -1
- package/types/intelligence.ts +607 -0
- package/types/modules/base.ts +16 -16
- package/types/modules/index.ts +1 -1
- package/types/modules/module-lifecycle.ts +21 -21
- package/types/modules/module-manager.ts +11 -11
- package/types/modules/module.ts +16 -16
- package/types/storage.ts +0 -1
- package/types/touch-app-core.ts +32 -32
- package/types/update.ts +91 -21
- package/core-box/README.md +0 -218
- package/core-box/builder/tuff-builder.example.ts.bak +0 -258
- package/core-box/run-tests.sh +0 -7
- package/core-box/search.ts +0 -1
- package/electron/clipboard-helper.ts +0 -199
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { defaultRiskPromptHandler } from '../risk'
|
|
2
1
|
import type { PluginInstallRequest, PluginInstallResult, PluginProvider, PluginProviderContext } from './types'
|
|
2
|
+
import { defaultRiskPromptHandler } from '../risk'
|
|
3
3
|
|
|
4
4
|
class ProviderRegistry {
|
|
5
5
|
private providers: PluginProvider[] = []
|
|
6
6
|
|
|
7
7
|
register(provider: PluginProvider): void {
|
|
8
|
-
if (this.providers.some(
|
|
8
|
+
if (this.providers.some(item => item.type === provider.type)) {
|
|
9
9
|
throw new Error(`Plugin provider '${provider.type}' already registered`)
|
|
10
10
|
}
|
|
11
11
|
this.providers.push(provider)
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
unregister(type: PluginProvider['type']): void {
|
|
15
|
-
this.providers = this.providers.filter(
|
|
15
|
+
this.providers = this.providers.filter(item => item.type !== type)
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
clear(): void {
|
|
@@ -20,19 +20,20 @@ class ProviderRegistry {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
resolve(request: PluginInstallRequest): PluginProvider | undefined {
|
|
23
|
-
return this.providers.find(
|
|
23
|
+
return this.providers.find(provider => provider.canHandle(request))
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
async install(
|
|
27
27
|
request: PluginInstallRequest,
|
|
28
|
-
context: PluginProviderContext = {}
|
|
28
|
+
context: PluginProviderContext = {},
|
|
29
29
|
): Promise<PluginInstallResult | undefined> {
|
|
30
30
|
const provider = this.resolve(request)
|
|
31
|
-
if (!provider)
|
|
31
|
+
if (!provider)
|
|
32
|
+
return undefined
|
|
32
33
|
|
|
33
34
|
const composedContext: PluginProviderContext = {
|
|
34
35
|
riskPrompt: defaultRiskPromptHandler,
|
|
35
|
-
...context
|
|
36
|
+
...context,
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
if (!composedContext.riskPrompt) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { IDownloadOptions, IDownloadResult } from '../plugin-source'
|
|
2
1
|
import type { IManifest } from '..'
|
|
2
|
+
import type { IDownloadOptions, IDownloadResult } from '../plugin-source'
|
|
3
3
|
import type { RiskPromptHandler } from '../risk'
|
|
4
4
|
|
|
5
5
|
export enum PluginProviderType {
|
|
@@ -7,7 +7,7 @@ export enum PluginProviderType {
|
|
|
7
7
|
NPM = 'npm',
|
|
8
8
|
TPEX = 'tpex',
|
|
9
9
|
FILE = 'file',
|
|
10
|
-
DEV = 'dev'
|
|
10
|
+
DEV = 'dev',
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export interface PluginInstallRequest {
|
|
@@ -43,11 +43,11 @@ export interface PluginInstallResult extends IDownloadResult {
|
|
|
43
43
|
|
|
44
44
|
export interface PluginProvider {
|
|
45
45
|
readonly type: PluginProviderType
|
|
46
|
-
canHandle(request: PluginInstallRequest)
|
|
47
|
-
install(
|
|
46
|
+
canHandle: (request: PluginInstallRequest) => boolean
|
|
47
|
+
install: (
|
|
48
48
|
request: PluginInstallRequest,
|
|
49
|
-
context?: PluginProviderContext
|
|
50
|
-
)
|
|
49
|
+
context?: PluginProviderContext,
|
|
50
|
+
) => Promise<PluginInstallResult>
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
export interface PluginInstallSummary {
|
|
@@ -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,避免技术债务
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Box SDK for Plugin Development
|
|
3
|
+
*
|
|
4
|
+
* Provides a unified API for plugins to control the CoreBox window behavior,
|
|
5
|
+
* including visibility, size, input field control, and input value access.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Expand options for CoreBox window
|
|
10
|
+
*/
|
|
11
|
+
export interface BoxExpandOptions {
|
|
12
|
+
/** Number of items to show (affects window height) */
|
|
13
|
+
length?: number
|
|
14
|
+
/** Force maximum expansion */
|
|
15
|
+
forceMax?: boolean
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Box SDK interface for plugins
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* // Hide CoreBox
|
|
24
|
+
* plugin.box.hide()
|
|
25
|
+
*
|
|
26
|
+
* // Show CoreBox
|
|
27
|
+
* plugin.box.show()
|
|
28
|
+
*
|
|
29
|
+
* // Expand to show 10 items
|
|
30
|
+
* plugin.box.expand({ length: 10 })
|
|
31
|
+
*
|
|
32
|
+
* // Get current input
|
|
33
|
+
* const input = plugin.box.getInput()
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export interface BoxSDK {
|
|
37
|
+
/**
|
|
38
|
+
* Hides the CoreBox window
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* plugin.box.hide()
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
hide(): void
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Shows the CoreBox window
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* plugin.box.show()
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
show(): void
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Expands the CoreBox window
|
|
59
|
+
*
|
|
60
|
+
* @param options - Optional expansion configuration
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```typescript
|
|
64
|
+
* // Expand to show 10 items
|
|
65
|
+
* plugin.box.expand({ length: 10 })
|
|
66
|
+
*
|
|
67
|
+
* // Force maximum expansion
|
|
68
|
+
* plugin.box.expand({ forceMax: true })
|
|
69
|
+
*
|
|
70
|
+
* // Default expansion
|
|
71
|
+
* plugin.box.expand()
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
expand(options?: BoxExpandOptions): Promise<void>
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Shrinks the CoreBox window to compact size
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```typescript
|
|
81
|
+
* plugin.box.shrink()
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
shrink(): Promise<void>
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Hides the input field in CoreBox
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```typescript
|
|
91
|
+
* plugin.box.hideInput()
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
hideInput(): Promise<void>
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Shows the input field in CoreBox
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```typescript
|
|
101
|
+
* plugin.box.showInput()
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
showInput(): Promise<void>
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Gets the current input value from CoreBox search field
|
|
108
|
+
*
|
|
109
|
+
* @returns Promise resolving to the current input string
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* ```typescript
|
|
113
|
+
* const input = await plugin.box.getInput()
|
|
114
|
+
* console.log('Current input:', input)
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
getInput(): Promise<string>
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Creates a Box SDK instance for plugin use
|
|
122
|
+
*
|
|
123
|
+
* @param channel - The plugin channel bridge for IPC communication
|
|
124
|
+
* @returns Configured Box SDK instance
|
|
125
|
+
*
|
|
126
|
+
* @internal
|
|
127
|
+
*/
|
|
128
|
+
export function createBoxSDK(channel: any): BoxSDK {
|
|
129
|
+
const sendFn = channel.sendToMain || channel.send
|
|
130
|
+
|
|
131
|
+
if (!sendFn) {
|
|
132
|
+
throw new Error('[Box SDK] Channel send function not available')
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return {
|
|
136
|
+
hide(): void {
|
|
137
|
+
sendFn('core-box:hide').catch((error: any) => {
|
|
138
|
+
console.error('[Box SDK] Failed to hide CoreBox:', error)
|
|
139
|
+
})
|
|
140
|
+
},
|
|
141
|
+
|
|
142
|
+
show(): void {
|
|
143
|
+
sendFn('core-box:show').catch((error: any) => {
|
|
144
|
+
console.error('[Box SDK] Failed to show CoreBox:', error)
|
|
145
|
+
})
|
|
146
|
+
},
|
|
147
|
+
|
|
148
|
+
async expand(options?: BoxExpandOptions): Promise<void> {
|
|
149
|
+
try {
|
|
150
|
+
await sendFn('core-box:expand', options || {})
|
|
151
|
+
} catch (error) {
|
|
152
|
+
console.error('[Box SDK] Failed to expand CoreBox:', error)
|
|
153
|
+
throw error
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
|
|
157
|
+
async shrink(): Promise<void> {
|
|
158
|
+
try {
|
|
159
|
+
await sendFn('core-box:expand', { mode: 'collapse' })
|
|
160
|
+
} catch (error) {
|
|
161
|
+
console.error('[Box SDK] Failed to shrink CoreBox:', error)
|
|
162
|
+
throw error
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
|
|
166
|
+
async hideInput(): Promise<void> {
|
|
167
|
+
try {
|
|
168
|
+
await sendFn('core-box:hide-input')
|
|
169
|
+
} catch (error) {
|
|
170
|
+
console.error('[Box SDK] Failed to hide input:', error)
|
|
171
|
+
throw error
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
|
|
175
|
+
async showInput(): Promise<void> {
|
|
176
|
+
try {
|
|
177
|
+
await sendFn('core-box:show-input')
|
|
178
|
+
} catch (error) {
|
|
179
|
+
console.error('[Box SDK] Failed to show input:', error)
|
|
180
|
+
throw error
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
|
|
184
|
+
async getInput(): Promise<string> {
|
|
185
|
+
try {
|
|
186
|
+
const result = await sendFn('core-box:get-input')
|
|
187
|
+
return result?.data?.input || result?.input || ''
|
|
188
|
+
} catch (error) {
|
|
189
|
+
console.error('[Box SDK] Failed to get input:', error)
|
|
190
|
+
throw error
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Hook for using Box SDK in plugin context
|
|
198
|
+
*
|
|
199
|
+
* @returns Box SDK instance
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
* ```typescript
|
|
203
|
+
* const box = useBox()
|
|
204
|
+
*
|
|
205
|
+
* box.hide()
|
|
206
|
+
* box.expand({ length: 10 })
|
|
207
|
+
* const input = await box.getInput()
|
|
208
|
+
* ```
|
|
209
|
+
*/
|
|
210
|
+
export function useBox(): BoxSDK {
|
|
211
|
+
// @ts-ignore - window.$channel is injected by the plugin system
|
|
212
|
+
const channel = window.$channel
|
|
213
|
+
|
|
214
|
+
if (!channel) {
|
|
215
|
+
throw new Error('[Box SDK] Channel not available. Make sure this is called in a plugin context.')
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return createBoxSDK(channel)
|
|
219
|
+
}
|
package/plugin/sdk/channel.ts
CHANGED
|
@@ -1,48 +1,48 @@
|
|
|
1
|
-
import type { ITouchClientChannel } from '@talex-touch/utils/channel'
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
1
|
+
import type { ITouchClientChannel } from '@talex-touch/utils/channel'
|
|
2
|
+
import type { IPluginRendererChannel, PluginChannelHandler } from './types'
|
|
3
|
+
import { genChannel } from '../channel'
|
|
4
4
|
|
|
5
|
-
const ensureClientChannel = (): ITouchClientChannel => genChannel()
|
|
5
|
+
const ensureClientChannel = (): ITouchClientChannel => genChannel()
|
|
6
6
|
|
|
7
7
|
export function createPluginRendererChannel(): IPluginRendererChannel {
|
|
8
|
-
const client = ensureClientChannel()
|
|
8
|
+
const client = ensureClientChannel()
|
|
9
9
|
|
|
10
10
|
return {
|
|
11
11
|
send(eventName, payload) {
|
|
12
|
-
return client.send(eventName, payload)
|
|
12
|
+
return client.send(eventName, payload)
|
|
13
13
|
},
|
|
14
14
|
|
|
15
15
|
sendSync(eventName, payload) {
|
|
16
|
-
return client.sendSync(eventName, payload)
|
|
16
|
+
return client.sendSync(eventName, payload)
|
|
17
17
|
},
|
|
18
18
|
|
|
19
19
|
on(eventName, handler) {
|
|
20
|
-
return client.regChannel(eventName, handler)
|
|
20
|
+
return client.regChannel(eventName, handler)
|
|
21
21
|
},
|
|
22
22
|
|
|
23
23
|
once(eventName, handler) {
|
|
24
|
-
let dispose: () => void = () => void 0
|
|
24
|
+
let dispose: () => void = () => void 0
|
|
25
25
|
const wrapped: PluginChannelHandler = (event) => {
|
|
26
|
-
dispose()
|
|
27
|
-
handler(event)
|
|
28
|
-
}
|
|
26
|
+
dispose()
|
|
27
|
+
handler(event)
|
|
28
|
+
}
|
|
29
29
|
|
|
30
|
-
dispose = client.regChannel(eventName, wrapped)
|
|
31
|
-
return dispose
|
|
30
|
+
dispose = client.regChannel(eventName, wrapped)
|
|
31
|
+
return dispose
|
|
32
32
|
},
|
|
33
33
|
|
|
34
34
|
get raw() {
|
|
35
|
-
return client
|
|
36
|
-
}
|
|
37
|
-
}
|
|
35
|
+
return client
|
|
36
|
+
},
|
|
37
|
+
}
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
let cachedRendererChannel: IPluginRendererChannel | null = null
|
|
40
|
+
let cachedRendererChannel: IPluginRendererChannel | null = null
|
|
41
41
|
|
|
42
42
|
export function usePluginRendererChannel(): IPluginRendererChannel {
|
|
43
43
|
if (!cachedRendererChannel) {
|
|
44
|
-
cachedRendererChannel = createPluginRendererChannel()
|
|
44
|
+
cachedRendererChannel = createPluginRendererChannel()
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
return cachedRendererChannel
|
|
47
|
+
return cachedRendererChannel
|
|
48
48
|
}
|
package/plugin/sdk/clipboard.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { PluginClipboardHistoryResponse, PluginClipboardItem } from './types'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
function ensurePluginChannel() {
|
|
4
4
|
const channel = (window as any)?.$channel
|
|
5
5
|
if (!channel) {
|
|
6
6
|
throw new Error('[Plugin SDK] Clipboard channel requires plugin renderer context with $channel available.')
|
|
@@ -8,13 +8,15 @@ const ensurePluginChannel = () => {
|
|
|
8
8
|
return channel
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
if (!item)
|
|
11
|
+
function normalizeItem(item: PluginClipboardItem | null): PluginClipboardItem | null {
|
|
12
|
+
if (!item)
|
|
13
|
+
return item
|
|
13
14
|
if (!item.meta && typeof item.metadata === 'string') {
|
|
14
15
|
try {
|
|
15
16
|
const parsed = JSON.parse(item.metadata)
|
|
16
17
|
return { ...item, meta: parsed }
|
|
17
|
-
}
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
18
20
|
return { ...item, meta: null }
|
|
19
21
|
}
|
|
20
22
|
}
|
|
@@ -61,7 +63,7 @@ export function useClipboardHistory() {
|
|
|
61
63
|
: []
|
|
62
64
|
return {
|
|
63
65
|
...response,
|
|
64
|
-
history
|
|
66
|
+
history,
|
|
65
67
|
}
|
|
66
68
|
},
|
|
67
69
|
|
|
@@ -94,6 +96,6 @@ export function useClipboardHistory() {
|
|
|
94
96
|
return Boolean((response as any).success)
|
|
95
97
|
}
|
|
96
98
|
return true
|
|
97
|
-
}
|
|
99
|
+
},
|
|
98
100
|
}
|
|
99
101
|
}
|
package/plugin/sdk/common.ts
CHANGED
|
@@ -17,8 +17,10 @@ export function regShortcut(key: string, func: Function): boolean {
|
|
|
17
17
|
const channel = genChannel()
|
|
18
18
|
|
|
19
19
|
const res = channel.sendSync('shortcon:reg', { key })
|
|
20
|
-
if (res instanceof String)
|
|
21
|
-
|
|
20
|
+
if (res instanceof String)
|
|
21
|
+
throw new Error(String(res))
|
|
22
|
+
if (res === false)
|
|
23
|
+
return false
|
|
22
24
|
|
|
23
25
|
channel.regChannel('shortcon:trigger', ({ data }) => key === data.key && func())
|
|
24
26
|
|
|
@@ -33,16 +35,17 @@ export function regShortcut(key: string, func: Function): boolean {
|
|
|
33
35
|
*/
|
|
34
36
|
export async function communicateWithPlugin(
|
|
35
37
|
key: string,
|
|
36
|
-
info: any = {}
|
|
38
|
+
info: any = {},
|
|
37
39
|
): Promise<any> {
|
|
38
40
|
const channel = genChannel()
|
|
39
41
|
|
|
40
42
|
try {
|
|
41
43
|
return await channel.send('index:communicate', {
|
|
42
44
|
key,
|
|
43
|
-
info
|
|
45
|
+
info,
|
|
44
46
|
})
|
|
45
|
-
}
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
46
49
|
console.error(`[Plugin SDK] Failed to communicate`, error)
|
|
47
50
|
throw error
|
|
48
51
|
}
|
|
@@ -59,7 +62,8 @@ export async function sendMessage(message: string, data: any = {}): Promise<any>
|
|
|
59
62
|
|
|
60
63
|
try {
|
|
61
64
|
return await channel.send(`plugin:${message}`, data)
|
|
62
|
-
}
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
63
67
|
console.error(`[Plugin SDK] Failed to send message: ${message}`, error)
|
|
64
68
|
throw error
|
|
65
69
|
}
|
package/plugin/sdk/core-box.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { IPluginRendererChannel } from './types'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
function ensurePluginContext(): { channel: IPluginRendererChannel, pluginName: string } {
|
|
4
4
|
const plugin = (window as any)?.$plugin
|
|
5
5
|
if (!plugin?.name) {
|
|
6
6
|
throw new Error('[TouchSDK] Unable to resolve plugin name inside renderer context.')
|
|
@@ -13,7 +13,7 @@ const ensurePluginContext = (): { channel: IPluginRendererChannel; pluginName: s
|
|
|
13
13
|
|
|
14
14
|
return {
|
|
15
15
|
channel,
|
|
16
|
-
pluginName: plugin.name as string
|
|
16
|
+
pluginName: plugin.name as string,
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
|
|
@@ -24,4 +24,3 @@ export async function clearCoreBoxItems(): Promise<void> {
|
|
|
24
24
|
const { channel, pluginName } = ensurePluginContext()
|
|
25
25
|
await channel.send('core-box:clear-items', { pluginName })
|
|
26
26
|
}
|
|
27
|
-
|