@talex-touch/utils 1.0.24 → 1.0.26

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/channel/index.ts CHANGED
@@ -9,6 +9,8 @@ export enum DataCode {
9
9
  ERROR = 100
10
10
  }
11
11
 
12
+ export type ChannelCallback = (data: StandardChannelData) => any
13
+
12
14
  export interface ITouchChannel {
13
15
 
14
16
  /**
@@ -18,7 +20,17 @@ export interface ITouchChannel {
18
20
  * @param eventName {string} The name of event, must be unique in the channel {@link ChannelType}
19
21
  * @param callback {Function} The callback function
20
22
  */
21
- regChannel(type: ChannelType, eventName: string, callback: (data: StandardChannelData) => any): () => void
23
+ regChannel(type: ChannelType, eventName: string, callback: ChannelCallback): () => void
24
+
25
+ /**
26
+ * Unregister a channel
27
+ * @description Unregister a channel by type, event name and callback
28
+ * @param type {@link ChannelType} The type of channel
29
+ * @param eventName {string} The name of event
30
+ * @param callback {Function} The callback function to unregister
31
+ * @returns {boolean} Returns true if the channel was successfully unregistered, false otherwise
32
+ */
33
+ unregChannel(type: ChannelType, eventName: string, callback: ChannelCallback): boolean
22
34
 
23
35
  /**
24
36
  * @deprecated Use sendMain instead
@@ -96,6 +108,15 @@ export interface ITouchClientChannel {
96
108
  */
97
109
  regChannel(eventName: string, callback: (data: StandardChannelData) => any): () => void
98
110
 
111
+ /**
112
+ * Unregister a channel
113
+ * @description Unregister a channel by event name and callback
114
+ * @param eventName {string} The name of event
115
+ * @param callback {Function} The callback function to unregister
116
+ * @returns {boolean} Returns true if the channel was successfully unregistered, false otherwise
117
+ */
118
+ unRegChannel(eventName: string, callback: (data: StandardChannelData) => any): boolean
119
+
99
120
  /**
100
121
  * Send a message to a channel
101
122
  * @param eventName {string} The name of event, must be unique in the channel {@link ChannelType}
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "module": "./index.ts",
6
6
  "license": "MPL-2.0",
7
7
  "private": false,
8
- "version": "1.0.24",
8
+ "version": "1.0.26",
9
9
  "scripts": {
10
10
  "publish": "npm publish --access public"
11
11
  },
package/plugin/channel.ts CHANGED
@@ -164,6 +164,29 @@ class TouchChannel implements ITouchClientChannel {
164
164
  };
165
165
  }
166
166
 
167
+ unRegChannel(eventName: string, callback: Function): boolean {
168
+ const listeners = this.channelMap.get(eventName);
169
+
170
+ if (!listeners) {
171
+ return false;
172
+ }
173
+
174
+ const index = listeners.indexOf(callback);
175
+
176
+ if (index === -1) {
177
+ return false;
178
+ }
179
+
180
+ listeners.splice(index, 1);
181
+
182
+ // If no listeners remain for this event, remove the event from the map
183
+ if (listeners.length === 0) {
184
+ this.channelMap.delete(eventName);
185
+ }
186
+
187
+ return true;
188
+ }
189
+
167
190
  send(eventName: string, arg: any): Promise<any> {
168
191
  const uniqueId = `${new Date().getTime()}#${eventName}@${Math.random().toString(
169
192
  12
package/plugin/index.ts CHANGED
@@ -59,7 +59,7 @@ export interface IPluginBaseInfo {
59
59
  export interface IPluginDev {
60
60
  enable: boolean
61
61
  address: string
62
- source?: string // 修改此处,允许 source 为字符串或 undefined
62
+ source?: boolean
63
63
  }
64
64
 
65
65
  export interface ITouchPlugin extends IPluginBaseInfo {
@@ -81,6 +81,47 @@ export interface ITouchPlugin extends IPluginBaseInfo {
81
81
 
82
82
  enable(): Promise<boolean>
83
83
  disable(): Promise<boolean>
84
+
85
+ /**
86
+ * Get the plugin file.
87
+ * @param fileName The name of the file.
88
+ * @returns The content of the file.
89
+ */
90
+ getPluginFile(fileName: string): object
91
+
92
+ /**
93
+ * Save the plugin file.
94
+ * @param fileName The name of the file.
95
+ * @param content The content of the file.
96
+ * @returns The result of the save operation.
97
+ */
98
+ savePluginFile(fileName: string, content: object): { success: boolean; error?: string }
99
+
100
+ /**
101
+ * Delete the plugin file.
102
+ * @param fileName The name of the file.
103
+ * @returns The result of the delete operation.
104
+ */
105
+ deletePluginFile(fileName: string): { success: boolean; error?: string }
106
+
107
+ /**
108
+ * List all files in the plugin.
109
+ * @returns The list of files.
110
+ */
111
+ listPluginFiles(): string[]
112
+
113
+ /**
114
+ * Get the plugin configuration.
115
+ * @returns The configuration content.
116
+ */
117
+ getPluginConfig(): object
118
+
119
+ /**
120
+ * Save the plugin configuration.
121
+ * @param content The configuration content.
122
+ * @returns The result of the save operation.
123
+ */
124
+ savePluginConfig(content: object): { success: boolean; error?: string }
84
125
  }
85
126
 
86
127
  export interface IFeatureCommand {
@@ -124,6 +165,13 @@ export interface IFeatureLifeCycle {
124
165
  * Can be used to prepare data or UI specific to this session.
125
166
  */
126
167
  onInit?(): void
168
+
169
+ /**
170
+ * Called when a message is received from the main application.
171
+ * @param key - The key of the message
172
+ * @param info - The information of the message
173
+ */
174
+ onMessage?(key: string, info: any): void
127
175
  /**
128
176
  * Called when a feature is actively launched from the launcher.
129
177
  * Can be used to prepare data or UI specific to this session.
@@ -1,28 +1,77 @@
1
- import { genChannel } from '../channel';
2
- import { IPluginFeature } from '../index'
1
+ /**
2
+ * Plugin SDK Common Utilities
3
+ *
4
+ * @description
5
+ * 提供插件SDK的通用功能,包括通信、快捷键等
6
+ */
3
7
 
4
- export function regShortcut(key: string, func: Function) {
5
- const channel = genChannel()
8
+ import { genChannel } from '../channel'
6
9
 
7
- const res = channel.sendSync('shortcon:reg', { key })
8
- if ( res instanceof String ) throw new Error(String(res))
9
- if ( res === false ) return false;
10
+ /**
11
+ * Register a shortcut
12
+ * @param key - The shortcut combination
13
+ * @param func - The trigger function
14
+ * @returns Whether the shortcut is registered successfully
15
+ */
16
+ export function regShortcut(key: string, func: Function): boolean {
17
+ const channel = genChannel()
18
+
19
+ const res = channel.sendSync('shortcon:reg', { key })
20
+ if (res instanceof String) throw new Error(String(res))
21
+ if (res === false) return false
10
22
 
11
- channel.regChannel('shortcon:trigger', ({ data }) => key === data.key && func())
23
+ channel.regChannel('shortcon:trigger', ({ data }) => key === data.key && func())
12
24
 
13
- return true;
25
+ return true
14
26
  }
15
27
 
16
- export function regFeature(feature: IPluginFeature): boolean {
28
+ /**
29
+ * Communicate with other plugins via the index:communicate channel
30
+ * @param key - The message key
31
+ * @param info - The message data
32
+ * @returns Promise<any> The communication result
33
+ */
34
+ export async function communicateWithPlugin(
35
+ key: string,
36
+ info: any = {}
37
+ ): Promise<any> {
17
38
  const channel = genChannel()
18
39
 
19
- return channel.sendSync('feature:reg', { feature })
40
+ try {
41
+ return await channel.send('index:communicate', {
42
+ key,
43
+ info
44
+ })
45
+ } catch (error) {
46
+ console.error(`[Plugin SDK] Failed to communicate`, error)
47
+ throw error
48
+ }
20
49
  }
21
50
 
22
- export function unRegFeature(id: string): boolean {
51
+ /**
52
+ * Send a message to the main application
53
+ * @param message - The message type
54
+ * @param data - The message data
55
+ * @returns Promise<any> The message result
56
+ */
57
+ export async function sendMessage(message: string, data: any = {}): Promise<any> {
23
58
  const channel = genChannel()
24
59
 
25
- return channel.sendSync('feature:unreg', { feature: id })
60
+ try {
61
+ return await channel.send(`plugin:${message}`, data)
62
+ } catch (error) {
63
+ console.error(`[Plugin SDK] Failed to send message: ${message}`, error)
64
+ throw error
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Get the channel object for the plugin
70
+ * Attention: Using this function make sure you know what you are doing.
71
+ * @returns The channel object for the plugin
72
+ */
73
+ export function getChannel() {
74
+ return genChannel()
26
75
  }
27
76
 
28
- export * from './window';
77
+ export * from './window'
@@ -0,0 +1,217 @@
1
+ /**
2
+ * Storage onDidChange 示例
3
+ * 展示如何使用 storage.onDidChange 监听存储文件变化
4
+ * 注意:这里只能获取新值,旧值无法获取
5
+ */
6
+
7
+ // 获取SDK实例
8
+ const sdk = window.$touchSDK
9
+
10
+ // 示例1: 监听特定配置文件的变化
11
+ function setupConfigListener() {
12
+ console.log('[Storage] Setting up listener for config.json changes')
13
+
14
+ const unsubscribe = sdk.storage.onDidChange('config.json', (newConfig) => {
15
+ console.log('[Storage] config.json changed:')
16
+ console.log(' New config:', newConfig)
17
+
18
+ // 处理特定键的变化
19
+ if (newConfig && newConfig.user_preference && newConfig.user_preference.theme) {
20
+ console.log(`[Storage] Theme changed to: ${newConfig.user_preference.theme}`)
21
+ }
22
+ })
23
+
24
+ // 返回取消监听的函数
25
+ return unsubscribe
26
+ }
27
+
28
+ // 示例2: 监听多个配置文件的变化
29
+ function setupMultipleFileListeners() {
30
+ console.log('[Storage] Setting up multiple file listeners')
31
+
32
+ const unsubscribers = []
33
+
34
+ // 监听 config.json
35
+ const configUnsubscribe = sdk.storage.onDidChange('config.json', (newConfig) => {
36
+ console.log('[Storage] config.json changed:', newConfig)
37
+ if (newConfig.user_preference) {
38
+ handleUserPreferenceChange(newConfig.user_preference)
39
+ }
40
+ })
41
+ unsubscribers.push(configUnsubscribe)
42
+
43
+ // 监听 settings.json
44
+ const settingsUnsubscribe = sdk.storage.onDidChange('settings.json', (newSettings) => {
45
+ console.log('[Storage] settings.json changed:', newSettings)
46
+ if (newSettings) {
47
+ handleSettingsChange(newSettings)
48
+ }
49
+ })
50
+ unsubscribers.push(settingsUnsubscribe)
51
+
52
+ // 监听 cache.json
53
+ const cacheUnsubscribe = sdk.storage.onDidChange('cache.json', (newCache) => {
54
+ console.log('[Storage] cache.json changed:', newCache)
55
+ if (newCache) {
56
+ handleCacheChange(newCache)
57
+ }
58
+ })
59
+ unsubscribers.push(cacheUnsubscribe)
60
+
61
+ // 返回取消所有监听的函数
62
+ return () => {
63
+ unsubscribers.forEach(unsubscribe => unsubscribe())
64
+ }
65
+ }
66
+
67
+ // 示例3: 动态监听
68
+ function setupDynamicListener() {
69
+ let currentListener = null
70
+
71
+ // 开始监听
72
+ function startListening(fileName) {
73
+ console.log(`[Storage] Starting to listen for ${fileName} changes`)
74
+
75
+ // 如果已有监听器,先取消
76
+ if (currentListener) {
77
+ currentListener()
78
+ }
79
+
80
+ currentListener = sdk.storage.onDidChange(fileName, (newConfig) => {
81
+ console.log(`[Storage] Dynamic listener for ${fileName} changes:`)
82
+ console.log(' New config:', newConfig)
83
+ })
84
+ }
85
+
86
+ // 停止监听
87
+ function stopListening() {
88
+ if (currentListener) {
89
+ console.log('[Storage] Stopping current listener')
90
+ currentListener()
91
+ currentListener = null
92
+ }
93
+ }
94
+
95
+ return { startListening, stopListening }
96
+ }
97
+
98
+ // 示例4: 条件监听
99
+ function setupConditionalListener() {
100
+ console.log('[Storage] Setting up conditional listener for user preferences')
101
+
102
+ const unsubscribe = sdk.storage.onDidChange('config.json', (newConfig) => {
103
+ // 处理用户偏好变化
104
+ if (newConfig.user_preference) {
105
+ const pref = newConfig.user_preference
106
+
107
+ // 处理主题变化
108
+ if (pref.theme) {
109
+ console.log(`[Storage] Theme: ${pref.theme}`)
110
+ applyTheme(pref.theme)
111
+ }
112
+
113
+ // 处理语言变化
114
+ if (pref.language) {
115
+ console.log(`[Storage] Language: ${pref.language}`)
116
+ reloadInterface(pref.language)
117
+ }
118
+ }
119
+ })
120
+
121
+ return unsubscribe
122
+ }
123
+
124
+ // 示例5: 批量操作监听
125
+ function setupBatchOperationListener() {
126
+ console.log('[Storage] Setting up batch operation listener')
127
+
128
+ const unsubscribe = sdk.storage.onDidChange('batch_data.json', (newConfig) => {
129
+ console.log('[Storage] batch_data.json changed:')
130
+ console.log(' New config:', newConfig)
131
+
132
+ // 处理批量数据变化
133
+ if (newConfig) {
134
+ console.log('[Storage] Processing batch data changes')
135
+ console.log(' Batch data count:', Object.keys(newConfig).length)
136
+
137
+ // 应用变化
138
+ applyChanges(newConfig)
139
+ }
140
+ })
141
+
142
+ return unsubscribe
143
+ }
144
+
145
+ // 辅助函数
146
+ function handleUserPreferenceChange(newValue) {
147
+ console.log('[Storage] Handling user preference change')
148
+ // 处理用户偏好变化
149
+ }
150
+
151
+ function handleSettingsChange(newValue) {
152
+ console.log('[Storage] Handling settings change')
153
+ // 处理设置变化
154
+ }
155
+
156
+ function handleCacheChange(newValue) {
157
+ console.log('[Storage] Handling cache change')
158
+ // 处理缓存变化
159
+ }
160
+
161
+ function applyTheme(theme) {
162
+ console.log(`[Storage] Applying theme: ${theme}`)
163
+ // 应用主题逻辑
164
+ }
165
+
166
+ function reloadInterface(language) {
167
+ console.log(`[Storage] Reloading interface for language: ${language}`)
168
+ // 重新加载界面逻辑
169
+ }
170
+
171
+ function findChanges(oldValue, newValue) {
172
+ const changes = []
173
+ // 比较两个对象并找出变化
174
+ return changes
175
+ }
176
+
177
+ function applyChanges(changes) {
178
+ console.log('[Storage] Applying changes:', changes)
179
+ // 应用变化逻辑
180
+ }
181
+
182
+ // 导出函数供外部调用
183
+ window.storageOnDidChangeExample = {
184
+ setupConfigListener,
185
+ setupMultipleFileListeners,
186
+ setupDynamicListener,
187
+ setupConditionalListener,
188
+ setupBatchOperationListener
189
+ }
190
+
191
+ // 自动运行示例(可选)
192
+ if (typeof window !== 'undefined' && window.location.hostname === 'localhost') {
193
+ console.log('[Auto] Setting up storage listeners...')
194
+
195
+ // 设置配置监听
196
+ const unsubscribe1 = setupConfigListener()
197
+
198
+ // 设置多文件监听
199
+ const unsubscribeAll = setupMultipleFileListeners()
200
+
201
+ // 设置动态监听
202
+ const { startListening, stopListening } = setupDynamicListener()
203
+
204
+ // 5秒后切换到监听其他键
205
+ setTimeout(() => {
206
+ stopListening()
207
+ startListening('settings')
208
+ }, 5000)
209
+
210
+ // 10秒后停止所有监听
211
+ setTimeout(() => {
212
+ console.log('[Auto] Stopping all listeners...')
213
+ unsubscribe1()
214
+ unsubscribeAll()
215
+ stopListening()
216
+ }, 10000)
217
+ }
@@ -74,10 +74,10 @@ export function usePluginStorage() {
74
74
  }
75
75
  }
76
76
 
77
- channel.on('plugin:storage:update', listener)
77
+ channel.regChannel('plugin:storage:update', listener)
78
78
 
79
79
  return () => {
80
- channel.off('plugin:storage:update', listener)
80
+ channel.unRegChannel('plugin:storage:update', listener)
81
81
  }
82
82
  }
83
83
  }