@talex-touch/utils 1.0.4 → 1.0.6
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 +1 -1
- package/eventbus/index.ts +2 -2
- package/package.json +1 -1
- package/permission/index.ts +0 -1
- package/plugin/channel.ts +22 -13
- package/plugin/index.ts +27 -0
- package/plugin/preload.ts +6 -4
- package/plugin/sdk/common.ts +30 -0
- package/plugin/sdk/hooks/life-cycle.ts +7 -2
- package/plugin/sdk/service/index.ts +30 -0
- package/service/index.ts +68 -0
- package/service/protocol/index.ts +78 -0
package/channel/index.ts
CHANGED
|
@@ -15,7 +15,7 @@ export interface ITouchChannel {
|
|
|
15
15
|
* Register a channel
|
|
16
16
|
* @description Register a channel, and return a function to cancel the registration
|
|
17
17
|
* @param type {@link ChannelType} The type of channel
|
|
18
|
-
* @param eventName {string} The name of event, must be unique in the channel {@link ChannelType
|
|
18
|
+
* @param eventName {string} The name of event, must be unique in the channel {@link ChannelType}
|
|
19
19
|
* @param callback {Function} The callback function
|
|
20
20
|
*/
|
|
21
21
|
regChannel(type: ChannelType, eventName: string, callback: (data: StandardChannelData) => any): () => void
|
package/eventbus/index.ts
CHANGED
|
@@ -40,7 +40,7 @@ export interface ITouchEventBus<E> {
|
|
|
40
40
|
* @param handler Event handler (extends from EventHandler)
|
|
41
41
|
* @returns true if the event was added, otherwise false
|
|
42
42
|
*/
|
|
43
|
-
on(event: E, handler: EventHandler): boolean;
|
|
43
|
+
on(event: E, handler: EventHandler): boolean | void;
|
|
44
44
|
|
|
45
45
|
/**
|
|
46
46
|
* Subscribe touch-app events (any kind of events extends from TouchEvent)
|
|
@@ -48,7 +48,7 @@ export interface ITouchEventBus<E> {
|
|
|
48
48
|
* @param handler Event handler (extends from EventHandler)
|
|
49
49
|
* @returns true if the event was added, otherwise false
|
|
50
50
|
*/
|
|
51
|
-
once(event: E, handler: EventHandler): boolean;
|
|
51
|
+
once(event: E, handler: EventHandler): boolean | void;
|
|
52
52
|
|
|
53
53
|
/**
|
|
54
54
|
* UnSubscribe touch-app events (any kind of events extends from TouchEvent)
|
package/package.json
CHANGED
package/permission/index.ts
CHANGED
package/plugin/channel.ts
CHANGED
|
@@ -18,13 +18,13 @@ class TouchChannel implements ITouchClientChannel {
|
|
|
18
18
|
constructor(pluginName: string) {
|
|
19
19
|
this.plugin = pluginName;
|
|
20
20
|
|
|
21
|
-
ipcRenderer.on("@
|
|
21
|
+
ipcRenderer.on("@plugin-process-message", this.__handle_main.bind(this));
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
__parse_raw_data(e, arg): RawStandardChannelData | null {
|
|
25
|
-
|
|
24
|
+
__parse_raw_data(e: typeof IpcMainEvent, arg: any): RawStandardChannelData | null {
|
|
25
|
+
console.log("Raw data: ", arg, e);
|
|
26
26
|
if (arg) {
|
|
27
|
-
const { name, header, code,
|
|
27
|
+
const { name, header, code, data, sync } = arg;
|
|
28
28
|
|
|
29
29
|
if (header) {
|
|
30
30
|
return {
|
|
@@ -36,7 +36,6 @@ class TouchChannel implements ITouchClientChannel {
|
|
|
36
36
|
sync,
|
|
37
37
|
code,
|
|
38
38
|
data,
|
|
39
|
-
plugin,
|
|
40
39
|
name: name as string,
|
|
41
40
|
};
|
|
42
41
|
}
|
|
@@ -47,7 +46,8 @@ class TouchChannel implements ITouchClientChannel {
|
|
|
47
46
|
// throw new Error("Invalid message!");
|
|
48
47
|
}
|
|
49
48
|
|
|
50
|
-
__handle_main(e: typeof IpcMainEvent,
|
|
49
|
+
__handle_main(e: typeof IpcMainEvent, _arg: any): any {
|
|
50
|
+
const arg = JSON.parse(_arg)
|
|
51
51
|
const rawData = this.__parse_raw_data(e, arg);
|
|
52
52
|
if ( !rawData ) return
|
|
53
53
|
|
|
@@ -57,13 +57,13 @@ class TouchChannel implements ITouchClientChannel {
|
|
|
57
57
|
return this.pendingMap.get(id)?.(rawData);
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
if ( rawData.plugin !== this.plugin ) return
|
|
60
|
+
// if ( rawData.plugin !== this.plugin ) return
|
|
61
61
|
|
|
62
62
|
this.channelMap.get(rawData.name)?.forEach((func) => {
|
|
63
63
|
const handInData: StandardChannelData = {
|
|
64
|
-
reply: (code: DataCode, data: any
|
|
64
|
+
reply: (code: DataCode, data: any) => {
|
|
65
65
|
e.sender.send(
|
|
66
|
-
"@
|
|
66
|
+
"@plugin-process-message",
|
|
67
67
|
this.__parse_sender(code, rawData, data, rawData.sync)
|
|
68
68
|
);
|
|
69
69
|
},
|
|
@@ -148,9 +148,9 @@ class TouchChannel implements ITouchClientChannel {
|
|
|
148
148
|
|
|
149
149
|
return new Promise((resolve) => {
|
|
150
150
|
|
|
151
|
-
ipcRenderer.send("@
|
|
151
|
+
ipcRenderer.send("@plugin-process-message", data);
|
|
152
152
|
|
|
153
|
-
this.pendingMap.set(uniqueId, (res) => {
|
|
153
|
+
this.pendingMap.set(uniqueId, (res: any) => {
|
|
154
154
|
this.pendingMap.delete(uniqueId);
|
|
155
155
|
|
|
156
156
|
resolve(res.data);
|
|
@@ -170,7 +170,7 @@ class TouchChannel implements ITouchClientChannel {
|
|
|
170
170
|
},
|
|
171
171
|
} as RawStandardChannelData;
|
|
172
172
|
|
|
173
|
-
const res = this.__parse_raw_data(null, ipcRenderer.sendSync("@
|
|
173
|
+
const res = this.__parse_raw_data(null, ipcRenderer.sendSync("@plugin-process-message", data))!
|
|
174
174
|
|
|
175
175
|
if ( res.header.status === 'reply' ) return res.data;
|
|
176
176
|
|
|
@@ -179,4 +179,13 @@ class TouchChannel implements ITouchClientChannel {
|
|
|
179
179
|
}
|
|
180
180
|
}
|
|
181
181
|
|
|
182
|
-
|
|
182
|
+
let touchChannel: ITouchClientChannel
|
|
183
|
+
|
|
184
|
+
export function genChannel() {
|
|
185
|
+
if (!touchChannel) {
|
|
186
|
+
// @ts-ignore
|
|
187
|
+
touchChannel = window.$channel = new TouchChannel(window.$plugin.name)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return touchChannel
|
|
191
|
+
}
|
package/plugin/index.ts
CHANGED
|
@@ -68,3 +68,30 @@ export interface IPluginManager {
|
|
|
68
68
|
loadPlugin(pluginName: string): Promise<boolean>
|
|
69
69
|
unloadPlugin(pluginName: string): Promise<boolean>
|
|
70
70
|
}
|
|
71
|
+
|
|
72
|
+
export interface IManifest {
|
|
73
|
+
name: string
|
|
74
|
+
version: string
|
|
75
|
+
description: string
|
|
76
|
+
plugin?: {
|
|
77
|
+
dev: {
|
|
78
|
+
enable: boolean
|
|
79
|
+
address: string
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
build?: {
|
|
83
|
+
files: string[]
|
|
84
|
+
secret: {
|
|
85
|
+
pos: string
|
|
86
|
+
addon: string[]
|
|
87
|
+
}
|
|
88
|
+
verify?: {
|
|
89
|
+
enable: boolean
|
|
90
|
+
online: 'custom' | 'always' | 'once'
|
|
91
|
+
}
|
|
92
|
+
version?: {
|
|
93
|
+
update: 'auto' | 'ask' | 'readable'
|
|
94
|
+
downgrade: boolean
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
package/plugin/preload.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { genChannel } from './channel'
|
|
2
2
|
import './sdk/index'
|
|
3
3
|
|
|
4
4
|
// window type
|
|
@@ -31,7 +31,9 @@ export function init(window: Window) {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
export function initBridge(window: Window) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
window.$
|
|
34
|
+
const touchChannel = genChannel()
|
|
35
|
+
|
|
36
|
+
window.$send = touchChannel.send.bind(touchChannel)
|
|
37
|
+
window.$sendSync = touchChannel.sendSync.bind(touchChannel)
|
|
38
|
+
window.$regChannel = touchChannel.regChannel.bind(touchChannel)
|
|
37
39
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { genChannel } from '../channel';
|
|
2
|
+
import {
|
|
3
|
+
BrowserWindowConstructorOptions
|
|
4
|
+
} from "electron";
|
|
5
|
+
|
|
6
|
+
export function regShortcut(key: string, func: Function) {
|
|
7
|
+
const channel = genChannel()
|
|
8
|
+
|
|
9
|
+
const res = channel.sendSync('shortcon:reg', { key })
|
|
10
|
+
if ( res instanceof String ) throw new Error(res)
|
|
11
|
+
if ( res === false ) return false;
|
|
12
|
+
|
|
13
|
+
channel.regChannel('shortcon:trigger', ({ data }) => key === data.key && func())
|
|
14
|
+
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function createWindow(options: BrowserWindowConstructorOptions & { file?: string } & { url?: string }): number {
|
|
19
|
+
const res = genChannel().sendSync('window:new', options)
|
|
20
|
+
if ( res.error ) throw new Error(res.error)
|
|
21
|
+
|
|
22
|
+
return res.id
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function toggleWinVisible(id: number, visible?: boolean): boolean {
|
|
26
|
+
const res = genChannel().sendSync('window:visible', visible !== undefined ? { id, visible } : { id })
|
|
27
|
+
if ( res.error ) throw new Error(res.error)
|
|
28
|
+
|
|
29
|
+
return res.visible
|
|
30
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { genChannel } from './../../channel';
|
|
2
2
|
|
|
3
3
|
export enum LifecycleHooks {
|
|
4
4
|
ENABLE = 'en',
|
|
@@ -9,22 +9,27 @@ export enum LifecycleHooks {
|
|
|
9
9
|
CRASH = 'cr'
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
// @ts-ignore
|
|
12
13
|
export function injectHook(type: LifecycleHooks, hook: Function, processFunc = ({ data, reply }) => {
|
|
14
|
+
// @ts-ignore
|
|
13
15
|
const hooks: Array<Function> = window.$touchSDK.__hooks[type]
|
|
14
16
|
if (hooks) {
|
|
15
17
|
hooks.forEach(hook => hook(data))
|
|
16
18
|
}
|
|
17
19
|
reply(true)
|
|
18
20
|
}) {
|
|
21
|
+
// @ts-ignore
|
|
19
22
|
const __hooks = window.$touchSDK.__hooks
|
|
23
|
+
// @ts-ignore
|
|
20
24
|
const hooks: Array<Function> = __hooks[type] || (__hooks[type] = [])
|
|
21
25
|
|
|
22
26
|
if (hooks.length === 0) {
|
|
23
27
|
|
|
24
|
-
|
|
28
|
+
genChannel().regChannel("@lifecycle:" + type, (obj: any) => {
|
|
25
29
|
|
|
26
30
|
processFunc(obj)
|
|
27
31
|
|
|
32
|
+
// @ts-ignore
|
|
28
33
|
delete window.$touchSDK.__hooks[type]
|
|
29
34
|
})
|
|
30
35
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { genChannel } from '../../channel';
|
|
2
|
+
import { IService } from "../../../service";
|
|
3
|
+
|
|
4
|
+
export function regService(service: IService, handler: Function): boolean {
|
|
5
|
+
const res = !!genChannel().sendSync('service:reg', { service: service.name })
|
|
6
|
+
|
|
7
|
+
if (res)
|
|
8
|
+
onHandleService(service, handler)
|
|
9
|
+
|
|
10
|
+
return res
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function unRegService(service: IService): boolean {
|
|
14
|
+
return !!genChannel().sendSync('service:unreg', { service: service.name })
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function onHandleService(service: IService, handler: Function) {
|
|
18
|
+
// @ts-ignore
|
|
19
|
+
genChannel().regChannel('service:handle', ({ data: _data }) => {
|
|
20
|
+
const { data } = _data
|
|
21
|
+
|
|
22
|
+
// console.log('service:handle', data, service)
|
|
23
|
+
|
|
24
|
+
if (data.service === service.name) {
|
|
25
|
+
return handler(data)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return false
|
|
29
|
+
})
|
|
30
|
+
}
|
package/service/index.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
export interface IService {
|
|
2
|
+
/**
|
|
3
|
+
* service id
|
|
4
|
+
*/
|
|
5
|
+
id: Symbol;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* service name
|
|
9
|
+
*/
|
|
10
|
+
name: string;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* service description
|
|
14
|
+
*/
|
|
15
|
+
description: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface IServiceEvent {
|
|
19
|
+
|
|
20
|
+
service: IService;
|
|
21
|
+
|
|
22
|
+
setCancelled(cancelled: boolean): void;
|
|
23
|
+
|
|
24
|
+
isCancelled(): boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface IServiceHandler {
|
|
28
|
+
/**
|
|
29
|
+
* The plugin scope of the service handler
|
|
30
|
+
* @description
|
|
31
|
+
* When service registered, the service center will use the plugin scope to find the service handler.
|
|
32
|
+
* If plugin is disabled, the app will automatically enable plugin and hand on the service to the plugin.
|
|
33
|
+
* When plugin enabled, you must immediately register service handler to the service center, app will waiting for the service handler, until the service handler handled.
|
|
34
|
+
*/
|
|
35
|
+
pluginScope: string
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Handle the service data
|
|
39
|
+
* @param data service data
|
|
40
|
+
*/
|
|
41
|
+
handle(event: IServiceEvent, data: object): any;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface IServiceCenter {
|
|
45
|
+
/**
|
|
46
|
+
* The service center will register the service
|
|
47
|
+
* @param service will be registered service
|
|
48
|
+
* @param handler service handler
|
|
49
|
+
* @returns register result (true: success, false: fail)
|
|
50
|
+
*/
|
|
51
|
+
regService(service: IService, handler: IServiceHandler): boolean;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* The service center will unregister the service
|
|
55
|
+
* @param service will be unregistered service
|
|
56
|
+
* @returns unregister result (true: success, false: fail)
|
|
57
|
+
*/
|
|
58
|
+
unRegService(service: IService): boolean;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Get the service by service id
|
|
62
|
+
* @param id service id
|
|
63
|
+
* @returns service
|
|
64
|
+
*/
|
|
65
|
+
// getService(id: symbol): IService;
|
|
66
|
+
|
|
67
|
+
useService(service: IService, data: object): Promise<boolean> | boolean;
|
|
68
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { IService } from './../index';
|
|
2
|
+
|
|
3
|
+
export abstract class ProtocolService<T extends string> implements IService {
|
|
4
|
+
id: symbol;
|
|
5
|
+
name: string;
|
|
6
|
+
description: string;
|
|
7
|
+
|
|
8
|
+
protocol: string[]
|
|
9
|
+
|
|
10
|
+
type: T
|
|
11
|
+
|
|
12
|
+
constructor(id: symbol, protocol: string[]) {
|
|
13
|
+
this.id = id;
|
|
14
|
+
this.name = id.description!;
|
|
15
|
+
this.description = `${this.name} Protocol Service`;
|
|
16
|
+
this.protocol = protocol
|
|
17
|
+
|
|
18
|
+
this.type = id.description as T
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const IMAGE_SUFFIX = [
|
|
23
|
+
'jpg', 'png', 'gif', 'bmp', 'webp', 'svg', 'ico', 'tiff', 'tif', 'jpeg', 'avif'
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
export class ImageProtocolService extends ProtocolService<'image'> {
|
|
27
|
+
constructor() {
|
|
28
|
+
super(Symbol('Image'), IMAGE_SUFFIX)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const AUDIO_SUFFIX = [
|
|
33
|
+
'mp3', 'wav', 'ogg', 'aac', 'flac', 'wma', 'ape', 'm4a', 'm4r', 'm4b', 'm4p', 'm4v', 'mp4', '3gp', 'avi', 'mov', 'wmv', 'flv', 'mkv', 'rmvb', 'rm', 'asf', 'dat', 'mpg', 'mpeg', 'vob', 'f4v', 'm3u8', 'webm', 'ts', 'mts', 'm2ts', 'mts', 'dv', 'divx', 'xvid', 'mpe', 'mod', 'sdp', 'm2v', 'm2p', 'm2t', 'm2ts', 'm2v', 'm2p', 'm2t', 'm2ts', 'm2v', 'm2p', 'm2t', 'm2ts', 'm2v', 'm2p', 'm2t', 'm2ts', 'm2v', 'm2p', 'm2t', 'm2ts', 'm2v', 'm2p', 'm2t', 'm2ts'
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
export class AudioProtocolService extends ProtocolService<'audio'> {
|
|
37
|
+
constructor() {
|
|
38
|
+
super(Symbol('Audio'), AUDIO_SUFFIX)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const VIDEO_SUFFIX = [
|
|
43
|
+
'mp4', '3gp', 'avi', 'mov', 'wmv', 'flv', 'mkv', 'rmvb', 'rm', 'asf', 'dat', 'mpg', 'mpeg', 'vob', 'f4v', 'm3u8', 'webm', 'ts', 'mts', 'm2ts', 'mts', 'dv', 'divx', 'xvid', 'mpe', 'mod', 'sdp', 'm2v', 'm2p', 'm2t', 'm2ts', 'm2v', 'm2p', 'm2t', 'm2ts', 'm2v', 'm2p', 'm2t', 'm2ts', 'm2v', 'm2p', 'm2t', 'm2ts', 'm2v', 'm2p', 'm2t', 'm2ts'
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
export class VideoProtocolService extends ProtocolService<'video'> {
|
|
47
|
+
constructor() {
|
|
48
|
+
super(Symbol('Video'), VIDEO_SUFFIX)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const TEXT_SUFFIX = [
|
|
53
|
+
'txt', 'md', 'markdown', 'json', 'js', 'ts', 'html', 'css', 'scss', 'sass', 'less', 'xml', 'yaml', 'yml', 'ini', 'log', 'bat', 'sh', 'cmd', 'c', 'cpp', 'h', 'hpp', 'java', 'py', 'go', 'php', 'sql', 'swift', 'vb', 'vbs', 'lua', 'rb', 'r', 'cs', 'm', 'mm', 'pl', 'perl', 'asm', 'asmx', 'inc', 'coffee', 'ts', 'tsx', 'jsx', 'vue', 'php', 'php3', 'php4', 'php5', 'php7', 'phps', 'phtml', 'pht', 'phar', 'phpt', 'php-cgi', 'php-cs-fixer', 'phpunit', 'phpunit.xml', 'phpunit.xml.dist', 'phpunit.phar', 'phpunit.phar.dist', 'phpunit-4.8.36.phar', 'phpunit-4.8.36.phar.dist', 'phpunit-5.7.27.phar', 'phpunit-5.7.27.phar.dist', 'phpunit-6.5.14.phar', 'phpunit-6.5.14.phar.dist', 'phpunit-7.5.20.phar', 'phpunit-7.5.20.phar.dist', 'phpunit-8.5.8.phar', 'phpunit-8.5.8.phar.dist', 'phpunit-9.3.10.phar', 'phpunit-9.3.10.phar.dist', 'phpunit-9.4.3.phar', 'phpunit-9.4.3.phar.dist', 'phpunit-9.5.0.phar', 'phpunit-9.5.0.phar.dist', 'phpunit-9.5.1.phar', 'phpunit-9.5.1.phar.dist', 'phpunit-9.5.2.phar', 'phpunit-9.5.2.phar.dist', 'phpunit-9.5.4.phar', 'phpunit-9.5.4.phar.dist', 'php'
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
export class TextProtocolService extends ProtocolService<'text'> {
|
|
57
|
+
constructor() {
|
|
58
|
+
super(Symbol('Text'), TEXT_SUFFIX)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export const serviceSuffixMap = new Map<ProtocolService<string>, string[]>
|
|
63
|
+
|
|
64
|
+
serviceSuffixMap.set(new ImageProtocolService(), IMAGE_SUFFIX)
|
|
65
|
+
serviceSuffixMap.set(new AudioProtocolService(), AUDIO_SUFFIX)
|
|
66
|
+
serviceSuffixMap.set(new VideoProtocolService(), VIDEO_SUFFIX)
|
|
67
|
+
serviceSuffixMap.set(new TextProtocolService(), TEXT_SUFFIX)
|
|
68
|
+
|
|
69
|
+
export function suffix2Service(suffix: string): ProtocolService<string> | null {
|
|
70
|
+
|
|
71
|
+
for (const [type, suffixes] of serviceSuffixMap.entries()) {
|
|
72
|
+
if (suffixes.includes(suffix)) {
|
|
73
|
+
return type
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return null
|
|
78
|
+
}
|