assistsx-js 0.2.3 → 0.2.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "assistsx-js",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "description": "assistsx-js自动化开发SDK",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",
@@ -8,6 +8,7 @@ import { CallResponse } from "./call-response";
8
8
  import { Bounds } from "./bounds";
9
9
  import { generateUUID } from "./utils";
10
10
  import { AppInfo } from "./app-info";
11
+ import { PluginInfo } from "./plugin-info";
11
12
  import { DeviceInfo } from "./device-info";
12
13
  import type { NodeLookupScope } from "./node-lookup-scope";
13
14
  import {
@@ -15,6 +16,7 @@ import {
15
16
  callbacks,
16
17
  WebFloatingWindowOptions,
17
18
  } from "./assistsx";
19
+ import { WindowFlags } from "./window-flags";
18
20
 
19
21
  /**
20
22
  * 截图识别位置信息
@@ -142,6 +144,21 @@ export class AssistsXAsync {
142
144
  });
143
145
  return response.getDataOrDefault(false);
144
146
  }
147
+
148
+ /**
149
+ * 设置悬浮窗可获取焦点(WebView 内输入框 focus 时调用)
150
+ */
151
+ public static async setOverlayInputFocus(timeout?: number): Promise<boolean> {
152
+ return this.setOverlayFlagList(WindowFlags.getOverlayInputFocusFlagList(), timeout);
153
+ }
154
+
155
+ /**
156
+ * 取消悬浮窗焦点(WebView 内输入框 blur 时调用)
157
+ */
158
+ public static async clearOverlayInputFocus(timeout?: number): Promise<boolean> {
159
+ return this.setOverlayFlagList(WindowFlags.getOverlayInputBlurFlagList(), timeout);
160
+ }
161
+
145
162
  /**
146
163
  * 获取所有符合条件的节点
147
164
  * @param filterClass 类名过滤
@@ -1169,6 +1186,22 @@ export class AssistsXAsync {
1169
1186
  });
1170
1187
  return AppInfo.fromJSON(response.getDataOrDefault({}));
1171
1188
  }
1189
+ /**
1190
+ * 获取当前运行的 AssistsX 插件信息(仅 AssistsX 宿主有效,否则返回 null)
1191
+ */
1192
+ public static async getCurrentPlugin(timeout?: number): Promise<PluginInfo | null> {
1193
+ const response = await this.asyncCall(CallMethod.getCurrentPlugin, {
1194
+ timeout,
1195
+ });
1196
+ if (!response.isSuccess()) {
1197
+ return null;
1198
+ }
1199
+ const data = response.getDataOrNull();
1200
+ if (!data) {
1201
+ return null;
1202
+ }
1203
+ return PluginInfo.fromJSON(data);
1204
+ }
1172
1205
  public static async getUniqueDeviceId(timeout?: number): Promise<any> {
1173
1206
  const response = await this.asyncCall(CallMethod.getUniqueDeviceId, {
1174
1207
  timeout,
package/src/assistsx.ts CHANGED
@@ -9,8 +9,10 @@ import { Bounds } from "./bounds";
9
9
  import { decodeBase64UTF8, generateUUID } from "./utils";
10
10
  import { AccessibilityEventFilter } from "./accessibility-event-filter";
11
11
  import { AppInfo } from "./app-info";
12
+ import { PluginInfo } from "./plugin-info";
12
13
  import { DeviceInfo } from "./device-info";
13
14
  import type { NodeLookupScope } from "./node-lookup-scope";
15
+ import { WindowFlags } from "./window-flags";
14
16
 
15
17
  /**
16
18
  * 无障碍事件数据结构
@@ -234,6 +236,23 @@ export class AssistsX {
234
236
  });
235
237
  return response.getDataOrDefault(false);
236
238
  }
239
+
240
+ /**
241
+ * 设置悬浮窗可获取焦点(WebView 内输入框 focus 时调用)
242
+ * @returns 是否设置成功
243
+ */
244
+ public static setOverlayInputFocus(): boolean {
245
+ return this.setOverlayFlagList(WindowFlags.getOverlayInputFocusFlagList());
246
+ }
247
+
248
+ /**
249
+ * 取消悬浮窗焦点(WebView 内输入框 blur 时调用)
250
+ * @returns 是否设置成功
251
+ */
252
+ public static clearOverlayInputFocus(): boolean {
253
+ return this.setOverlayFlagList(WindowFlags.getOverlayInputBlurFlagList());
254
+ }
255
+
237
256
  /**
238
257
  * 获取所有符合条件的节点
239
258
  * @param filterClass 类名过滤
@@ -1022,6 +1041,20 @@ export class AssistsX {
1022
1041
  });
1023
1042
  return AppInfo.fromJSON(response.getDataOrDefault({}));
1024
1043
  }
1044
+ /**
1045
+ * 获取当前运行的 AssistsX 插件信息(仅 AssistsX 宿主有效,否则返回 null)
1046
+ */
1047
+ public static getCurrentPlugin(): PluginInfo | null {
1048
+ const response = this.call(CallMethod.getCurrentPlugin);
1049
+ if (!response.isSuccess()) {
1050
+ return null;
1051
+ }
1052
+ const data = response.getDataOrNull();
1053
+ if (!data) {
1054
+ return null;
1055
+ }
1056
+ return PluginInfo.fromJSON(data);
1057
+ }
1025
1058
  public static getUniqueDeviceId(): any {
1026
1059
  const response = this.call(CallMethod.getUniqueDeviceId);
1027
1060
  return response.getDataOrDefault("");
@@ -46,6 +46,7 @@ export const CallMethod = {
46
46
  longPressGestureAutoPaste: "longPressGestureAutoPaste",
47
47
 
48
48
  getAppInfo: "getAppInfo",
49
+ getCurrentPlugin: "getCurrentPlugin",
49
50
  getMacAddress: "getMacAddress",
50
51
  getAndroidID: "getAndroidID",
51
52
  getUniqueDeviceId: "getUniqueDeviceId",
@@ -0,0 +1,11 @@
1
+ /**
2
+ * SQLite 数据库桥接方法名常量
3
+ */
4
+ export const DbCallMethod = {
5
+ exec: "exec",
6
+ query: "query",
7
+ execBatch: "execBatch",
8
+ close: "close",
9
+ } as const;
10
+
11
+ export type DbCallMethodType = (typeof DbCallMethod)[keyof typeof DbCallMethod];
package/src/db/db.ts ADDED
@@ -0,0 +1,254 @@
1
+ /**
2
+ * SQLite 数据库 Bridge:assistsxDb
3
+ */
4
+ import { CallResponse } from "../call-response";
5
+ import { decodeBase64UTF8, generateUUID } from "../utils";
6
+ import { DbCallMethod } from "./db-call-method";
7
+
8
+ /** 数据库定位;dbPath 与 dbName 均可选,均未传时默认 default.db */
9
+ export interface DbTarget {
10
+ dbPath?: string;
11
+ dbName?: string;
12
+ }
13
+
14
+ /** exec 成功返回 */
15
+ export interface DbExecResult {
16
+ rowsAffected: number;
17
+ lastInsertRowId: number;
18
+ }
19
+
20
+ /** query 单行记录;BLOB 字段为 Base64 字符串 */
21
+ export type DbRow = Record<string, string | number | null>;
22
+
23
+ /** query 成功返回 */
24
+ export interface DbQueryResult {
25
+ columns: string[];
26
+ rows: DbRow[];
27
+ rowCount: number;
28
+ }
29
+
30
+ /** execBatch 单条结果 */
31
+ export interface DbBatchItemResult {
32
+ rowsAffected: number;
33
+ lastInsertRowId: number;
34
+ }
35
+
36
+ /** execBatch 成功返回 */
37
+ export interface DbExecBatchResult {
38
+ count: number;
39
+ results: DbBatchItemResult[];
40
+ }
41
+
42
+ /** 公共调用选项 */
43
+ export interface DbCallOptions extends DbTarget {
44
+ bindArgs?: (string | number | boolean | null)[];
45
+ /** 超时时间(秒),默认 30 */
46
+ timeout?: number;
47
+ }
48
+
49
+ export interface DbExecBatchOptions extends DbTarget {
50
+ /** 超时时间(秒),默认 30 */
51
+ timeout?: number;
52
+ }
53
+
54
+ // 回调函数存储对象
55
+ const callbacks: Map<string, (data: string) => void> = new Map();
56
+
57
+ // 初始化全局回调函数
58
+ if (typeof window !== "undefined" && !window.assistsxDbCallback) {
59
+ window.assistsxDbCallback = (data: string) => {
60
+ let callbackId: string | undefined;
61
+ try {
62
+ const json = decodeBase64UTF8(data);
63
+ const response = JSON.parse(json);
64
+ callbackId = response.callbackId;
65
+ if (callbackId) {
66
+ const callback = callbacks.get(callbackId);
67
+ if (callback) {
68
+ callback(json);
69
+ }
70
+ }
71
+ } catch (e) {
72
+ console.error("Db callback error:", e);
73
+ } finally {
74
+ if (callbackId) {
75
+ callbacks.delete(callbackId);
76
+ }
77
+ }
78
+ };
79
+ }
80
+
81
+ function buildDbArguments(
82
+ target: DbTarget,
83
+ extra?: Record<string, unknown>
84
+ ): Record<string, unknown> {
85
+ const args: Record<string, unknown> = { ...extra };
86
+ if (target.dbPath) {
87
+ args.dbPath = target.dbPath;
88
+ }
89
+ if (target.dbName) {
90
+ args.dbName = target.dbName;
91
+ }
92
+ return args;
93
+ }
94
+
95
+ function normalizeBindArgs(
96
+ bindArgs?: (string | number | boolean | null)[]
97
+ ): (string | null)[] | undefined {
98
+ if (!bindArgs || bindArgs.length === 0) {
99
+ return undefined;
100
+ }
101
+ return bindArgs.map((value) => {
102
+ if (value === null) {
103
+ return null;
104
+ }
105
+ return String(value);
106
+ });
107
+ }
108
+
109
+ function parseExecResult(data: unknown): DbExecResult {
110
+ const record = (data ?? {}) as Record<string, unknown>;
111
+ return {
112
+ rowsAffected: Number(record.rowsAffected ?? 0),
113
+ lastInsertRowId: Number(record.lastInsertRowId ?? 0),
114
+ };
115
+ }
116
+
117
+ function parseQueryResult(data: unknown): DbQueryResult {
118
+ const record = (data ?? {}) as Record<string, unknown>;
119
+ const columns = Array.isArray(record.columns)
120
+ ? record.columns.map((item) => String(item))
121
+ : [];
122
+ const rows = Array.isArray(record.rows) ? (record.rows as DbRow[]) : [];
123
+ return {
124
+ columns,
125
+ rows,
126
+ rowCount: Number(record.rowCount ?? rows.length),
127
+ };
128
+ }
129
+
130
+ function parseExecBatchResult(data: unknown): DbExecBatchResult {
131
+ const record = (data ?? {}) as Record<string, unknown>;
132
+ const results = Array.isArray(record.results)
133
+ ? record.results.map((item) => parseExecResult(item))
134
+ : [];
135
+ return {
136
+ count: Number(record.count ?? results.length),
137
+ results,
138
+ };
139
+ }
140
+
141
+ export class Db {
142
+ /**
143
+ * 执行异步调用
144
+ */
145
+ private async asyncCall(
146
+ method: string,
147
+ args?: Record<string, unknown>,
148
+ timeout: number = 30
149
+ ): Promise<CallResponse> {
150
+ const uuid = generateUUID();
151
+ const params = {
152
+ method,
153
+ arguments: args ? args : undefined,
154
+ callbackId: uuid,
155
+ };
156
+ const promise = new Promise<string>((resolve) => {
157
+ callbacks.set(uuid, (data: string) => {
158
+ resolve(data);
159
+ });
160
+ setTimeout(() => {
161
+ callbacks.delete(uuid);
162
+ resolve(JSON.stringify(new CallResponse(0, null, uuid)));
163
+ }, timeout * 1000);
164
+ });
165
+ window.assistsxDb.call(JSON.stringify(params));
166
+ const promiseResult = await promise;
167
+ if (typeof promiseResult !== "string") {
168
+ throw new Error("Db call failed");
169
+ }
170
+ const responseData = JSON.parse(promiseResult);
171
+ if (responseData.code !== 0) {
172
+ throw new Error(responseData.message || "Db call failed");
173
+ }
174
+ return new CallResponse(
175
+ responseData.code,
176
+ responseData.data,
177
+ responseData.callbackId
178
+ );
179
+ }
180
+
181
+ /**
182
+ * 将 query 结果中的 Base64 BLOB 字段解码为 Uint8Array
183
+ */
184
+ decodeBlobBase64(base64: string): Uint8Array {
185
+ const binary = atob(base64);
186
+ const bytes = new Uint8Array(binary.length);
187
+ for (let i = 0; i < binary.length; i++) {
188
+ bytes[i] = binary.charCodeAt(i);
189
+ }
190
+ return bytes;
191
+ }
192
+
193
+ /**
194
+ * 执行非查询 SQL
195
+ */
196
+ async exec(sql: string, options: DbCallOptions = {}): Promise<DbExecResult> {
197
+ const { timeout = 30, bindArgs, ...target } = options;
198
+ const response = await this.asyncCall(
199
+ DbCallMethod.exec,
200
+ buildDbArguments(target, {
201
+ sql,
202
+ bindArgs: normalizeBindArgs(bindArgs),
203
+ }),
204
+ timeout
205
+ );
206
+ return parseExecResult(response.getDataOrNull());
207
+ }
208
+
209
+ /**
210
+ * 执行查询 SQL
211
+ */
212
+ async query(sql: string, options: DbCallOptions = {}): Promise<DbQueryResult> {
213
+ const { timeout = 30, bindArgs, ...target } = options;
214
+ const response = await this.asyncCall(
215
+ DbCallMethod.query,
216
+ buildDbArguments(target, {
217
+ sql,
218
+ bindArgs: normalizeBindArgs(bindArgs),
219
+ }),
220
+ timeout
221
+ );
222
+ return parseQueryResult(response.getDataOrNull());
223
+ }
224
+
225
+ /**
226
+ * 事务内批量执行多条 SQL
227
+ */
228
+ async execBatch(
229
+ statements: string[],
230
+ options: DbExecBatchOptions = {}
231
+ ): Promise<DbExecBatchResult> {
232
+ const { timeout = 30, ...target } = options;
233
+ const response = await this.asyncCall(
234
+ DbCallMethod.execBatch,
235
+ buildDbArguments(target, { statements }),
236
+ timeout
237
+ );
238
+ return parseExecBatchResult(response.getDataOrNull());
239
+ }
240
+
241
+ /**
242
+ * 关闭并释放指定数据库连接
243
+ */
244
+ async close(options: DbTarget & { timeout?: number } = {}): Promise<void> {
245
+ const { timeout = 30, ...target } = options;
246
+ await this.asyncCall(
247
+ DbCallMethod.close,
248
+ buildDbArguments(target),
249
+ timeout
250
+ );
251
+ }
252
+ }
253
+
254
+ export const db = new Db();
package/src/global.d.ts CHANGED
@@ -55,6 +55,14 @@ declare global {
55
55
  call(method: string): string | null;
56
56
  };
57
57
  assistsxLogCallback: (data: string) => void;
58
+ assistsxScreenshot: {
59
+ call(method: string): string | null;
60
+ };
61
+ assistsxScreenshotCallback: (data: string) => void;
62
+ assistsxDb: {
63
+ call(method: string): string | null;
64
+ };
65
+ assistsxDbCallback: (data: string) => void;
58
66
  onAssistsLogUpdate: (encoded: string) => void;
59
67
  }
60
68
  }
package/src/index.ts CHANGED
@@ -15,6 +15,7 @@ export * from "./assistsx-async";
15
15
  export * from "./step-async";
16
16
  export * from "./accessibility-event-filter";
17
17
  export * from "./app-info";
18
+ export * from "./plugin-info";
18
19
  export * from "./device-info";
19
20
  export * from "./step-error";
20
21
  export * from "./network/http";
@@ -26,6 +27,10 @@ export * from "./imageutils/image-utils";
26
27
  export * from "./gallery/gallery";
27
28
  export * from "./mlkit/mlkit";
28
29
  export * from "./mlkit/mlkit-call-method";
30
+ export * from "./screenshot/screenshot";
31
+ export * from "./screenshot/screenshot-call-method";
32
+ export * from "./db/db";
33
+ export * from "./db/db-call-method";
29
34
  export * from "./barutils/bar-utils";
30
35
  export * from "./barutils/bar-utils-call-method";
31
36
  export * from "./floatingwindow/float";
@@ -14,6 +14,9 @@ export const LogCallMethod = {
14
14
 
15
15
  /** 获取日志服务当前域名(origin,无路径;与上传、管理后台同源),对应 AssistsLogDiagnostics.adminWebBaseUrl() */
16
16
  getLogServiceBaseUrl: "getLogServiceBaseUrl",
17
+
18
+ /** 解析日志文件绝对路径(不创建文件) */
19
+ resolveLogPath: "resolveLogPath",
17
20
  } as const;
18
21
 
19
22
  /** 与 ASWebView / AssistsLogJavascriptInterface companion 对齐 */