@lingxia/types 0.17.0 → 0.18.0
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/dist/automation/index.d.ts +104 -34
- package/dist/automation/index.d.ts.map +1 -1
- package/dist/error.d.ts +19 -0
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +23 -1
- package/dist/error.js.map +1 -1
- package/dist/esm/error.js +21 -0
- package/dist/esm/error.js.map +1 -1
- package/dist/esm/generated/error.js +1 -0
- package/dist/esm/generated/error.js.map +1 -1
- package/dist/esm/generated/i18n.js +10 -1
- package/dist/esm/generated/i18n.js.map +1 -1
- package/dist/esm/testing/public-api.js +72 -46
- package/dist/esm/testing/public-api.js.map +1 -1
- package/dist/generated/error.d.ts +4 -0
- package/dist/generated/error.d.ts.map +1 -1
- package/dist/generated/error.js +1 -0
- package/dist/generated/error.js.map +1 -1
- package/dist/generated/i18n.d.ts +1 -1
- package/dist/generated/i18n.d.ts.map +1 -1
- package/dist/generated/i18n.js +10 -1
- package/dist/generated/i18n.js.map +1 -1
- package/dist/generated/logic-web.d.ts +24 -3
- package/dist/generated/logic.d.ts +734 -378
- package/dist/generated/logic.d.ts.map +1 -1
- package/dist/index.d.ts +7 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/process.d.ts +15 -4
- package/dist/process.d.ts.map +1 -1
- package/dist/testing/public-api.d.ts +70 -45
- package/dist/testing/public-api.d.ts.map +1 -1
- package/dist/testing/public-api.js +72 -46
- package/dist/testing/public-api.js.map +1 -1
- package/package.json +2 -2
- package/src/automation/index.ts +81 -33
- package/src/error.ts +23 -0
- package/src/generated/error.ts +1 -0
- package/src/generated/i18n.ts +10 -1
- package/src/generated/logic-web.d.ts +24 -3
- package/src/generated/logic.ts +790 -402
- package/src/index.ts +9 -6
- package/src/process.ts +14 -4
- package/src/testing/public-api.ts +80 -47
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
declare const appDownloadPathBrand: unique symbol;
|
|
2
2
|
declare const systemDownloadsPathBrand: unique symbol;
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
/** Managed paths and relative userdata paths; system Downloads references are excluded. */
|
|
4
|
+
export type ManagedPath = string & {
|
|
5
|
+
readonly [systemDownloadsPathBrand]?: never;
|
|
6
|
+
};
|
|
7
|
+
/** JSON-shaped state; undefined removes a property in setData. */
|
|
8
|
+
export type PageDataValue<T> = unknown extends T ? T : T extends string | number | boolean | null | undefined ? T : T extends (...args: never[]) => unknown ? never : T extends object ? {
|
|
9
|
+
[K in keyof T]: PageDataValue<T[K]>;
|
|
10
|
+
} : never;
|
|
11
|
+
export type NoReservedPageMembers<T> = {
|
|
12
|
+
[K in keyof T]: K extends 'data' ? T[K] : K extends keyof PageInstance | '_setData' | '_cancelPendingSetData' ? never : T[K];
|
|
13
|
+
};
|
|
14
|
+
export interface PageConfig<TData extends object = Record<string, unknown>> {
|
|
15
|
+
data?: TData & PageDataValue<TData>;
|
|
5
16
|
onLoad?: (options?: PageLoadOptions) => void | Promise<void>;
|
|
6
17
|
onShow?: () => void | Promise<void>;
|
|
7
18
|
onReady?: () => void | Promise<void>;
|
|
@@ -31,25 +42,53 @@ export type NoLifecycleTypos<TCustom, TNames extends string> = {
|
|
|
31
42
|
};
|
|
32
43
|
/**
|
|
33
44
|
* A `setData` key that addresses inside `data` — `'a.b'` or `'rows[0].name'`.
|
|
34
|
-
*
|
|
35
|
-
*
|
|
45
|
+
* Kept for documentation; nested writes go through `setPath` (checked) or
|
|
46
|
+
* `setDataPath` (unchecked). `setData` no longer accepts these keys.
|
|
36
47
|
*/
|
|
37
48
|
export type PageDataPath = `${string}.${string}` | `${string}[${number}]${string}`;
|
|
38
49
|
/**
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
50
|
+
* @deprecated Page `data` is no longer widened for `null` / `[]` initializers.
|
|
51
|
+
* Annotate the field (`null as Profile | null`) when a later fill should be
|
|
52
|
+
* checked.
|
|
42
53
|
*/
|
|
43
|
-
export type LazyInitField<T> =
|
|
54
|
+
export type LazyInitField<T> = T;
|
|
55
|
+
type PageReadonlyDepth = [never, 0, 1, 2, 3, 4, 5, 6];
|
|
56
|
+
type PagePrimitive = string | number | boolean | bigint | symbol | null | undefined;
|
|
44
57
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
58
|
+
* Deep readonly view of page `data`. Static only — the runtime object is not
|
|
59
|
+
* frozen.
|
|
60
|
+
*/
|
|
61
|
+
export type DeepReadonly<T, D extends number = 6> = [D] extends [never] ? T : T extends PagePrimitive ? T : T extends Function ? T : T extends readonly unknown[] ? {
|
|
62
|
+
readonly [K in keyof T]: DeepReadonly<T[K], PageReadonlyDepth[D]>;
|
|
63
|
+
} : T extends object ? {
|
|
64
|
+
readonly [K in keyof T]: DeepReadonly<T[K], PageReadonlyDepth[D]>;
|
|
65
|
+
} : T;
|
|
66
|
+
/**
|
|
67
|
+
* Tuple path into `data`, depth-capped so large page states stay completable.
|
|
68
|
+
*/
|
|
69
|
+
export type DataPath<T, D extends number = 5> = [D] extends [never] ? never : T extends readonly (infer U)[] ? [number] | [number, ...DataPath<U, PageReadonlyDepth[D]>] : T extends object ? {
|
|
70
|
+
[K in keyof T & (string | number)]: [K] | (DataPath<T[K], PageReadonlyDepth[D]> extends infer Rest ? Rest extends readonly PropertyKey[] ? [K, ...Rest] : never : never);
|
|
71
|
+
}[keyof T & (string | number)] : never;
|
|
72
|
+
export type DataPathValue<T, P extends readonly PropertyKey[]> = T extends null | undefined ? never : T extends unknown ? P extends readonly [
|
|
73
|
+
infer K,
|
|
74
|
+
...infer Rest
|
|
75
|
+
] ? Rest extends readonly PropertyKey[] ? Rest['length'] extends 0 ? K extends keyof T ? T[K] : K extends number ? T extends readonly (infer U)[] ? U : never : never : K extends keyof T ? DataPathValue<T[K], Rest> : K extends number ? T extends readonly (infer U)[] ? DataPathValue<U, Rest> : never : never : never : never : never;
|
|
76
|
+
/**
|
|
77
|
+
* Top-level keys are checked against `data`. Nested writes use `setPath` or
|
|
78
|
+
* the unchecked `setDataPath`.
|
|
47
79
|
*/
|
|
48
80
|
export type SetDataPatch<TData> = {
|
|
49
|
-
[K in keyof TData]?:
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
|
|
81
|
+
[K in keyof TData]?: TData[K];
|
|
82
|
+
};
|
|
83
|
+
type SetDataValue<TData, K> = K extends PageDataPath ? {
|
|
84
|
+
"LingXia type error": "use setPath or setDataPath for nested writes";
|
|
85
|
+
} : K extends keyof TData ? TData[K] | DeepReadonly<TData[K]> : {
|
|
86
|
+
"LingXia type error": "unknown data key";
|
|
87
|
+
};
|
|
88
|
+
export interface PageInstance<TData extends object = Record<string, unknown>> {
|
|
89
|
+
readonly data: {
|
|
90
|
+
readonly [K in keyof TData]: DeepReadonly<TData[K]>;
|
|
91
|
+
};
|
|
53
92
|
route: string;
|
|
54
93
|
/**
|
|
55
94
|
* Available when this page was opened as a surface via
|
|
@@ -60,7 +99,14 @@ export interface PageInstance<TData extends Record<string, unknown> = Record<str
|
|
|
60
99
|
* Available when this page was opened by `lx.navigateTo(...)`.
|
|
61
100
|
*/
|
|
62
101
|
opener?: PageMessagePort;
|
|
63
|
-
setData
|
|
102
|
+
setData<TPatch extends Record<string, unknown>>(data: TPatch & {
|
|
103
|
+
[K in keyof TPatch]: SetDataValue<TData, K>;
|
|
104
|
+
}): void;
|
|
105
|
+
setPath<const P extends DataPath<TData>>(path: P, value: DataPathValue<TData, P>): void;
|
|
106
|
+
/** Nested write by a runtime-resolved string path. JSON shape is checked; the path/value relationship is not. */
|
|
107
|
+
setDataPath(path: string, value: JsonValue | undefined): void;
|
|
108
|
+
/** Drain pending state writes; an attached View acknowledges application, not paint. Rejects on unload. */
|
|
109
|
+
flush(): Promise<void>;
|
|
64
110
|
}
|
|
65
111
|
/**
|
|
66
112
|
* Injected by the runtime into methods listed in `stream_handlers` page metadata.
|
|
@@ -76,6 +122,12 @@ export interface StreamHandle<T = unknown> {
|
|
|
76
122
|
end(result?: unknown): void;
|
|
77
123
|
/** End the stream with an error. */
|
|
78
124
|
error(code: string, message?: string): void;
|
|
125
|
+
/**
|
|
126
|
+
* Called once if View cancels before `end`/`error`. Returns unsubscribe.
|
|
127
|
+
* The generator form still observes cancel in `finally`; use this for the
|
|
128
|
+
* callback-based handle.
|
|
129
|
+
*/
|
|
130
|
+
onCancel(handler: () => void): () => void;
|
|
79
131
|
}
|
|
80
132
|
/**
|
|
81
133
|
* Injected by the runtime as the second parameter when View opens a channel.
|
|
@@ -88,12 +140,12 @@ export interface ChannelHandle<TSend = unknown, TReceive = unknown> {
|
|
|
88
140
|
send(payload: TSend): void;
|
|
89
141
|
/** Close the channel from Logic side. */
|
|
90
142
|
close(code?: string, reason?: string): void;
|
|
91
|
-
/** Register a listener for incoming events. */
|
|
92
|
-
on(event: 'data', handler: (payload: TReceive) => void): void;
|
|
143
|
+
/** Register a listener for incoming events. Returns unsubscribe. */
|
|
144
|
+
on(event: 'data', handler: (payload: TReceive) => void): () => void;
|
|
93
145
|
on(event: 'close', handler: (info: {
|
|
94
146
|
code: string;
|
|
95
147
|
reason: string;
|
|
96
|
-
}) => void): void;
|
|
148
|
+
}) => void): () => void;
|
|
97
149
|
}
|
|
98
150
|
/**
|
|
99
151
|
* Download options.
|
|
@@ -107,30 +159,47 @@ export interface ChannelHandle<TSend = unknown, TReceive = unknown> {
|
|
|
107
159
|
*/
|
|
108
160
|
export type DownloadOptions<TDestination extends DownloadDestination = DownloadDestination> = TDestination extends 'downloads' ? DownloadsDownloadOptions : AppDownloadOptions;
|
|
109
161
|
export type DownloadResultForDestination<TDestination extends DownloadDestination> = TDestination extends 'downloads' ? DownloadsDownloadResult : AppDownloadResult;
|
|
110
|
-
export
|
|
111
|
-
kind: 'progress' | 'paused' | 'resumed'
|
|
162
|
+
export type DownloadProgressEvent<TResult extends DownloadResult = DownloadResult> = {
|
|
163
|
+
kind: 'progress' | 'paused' | 'resumed';
|
|
112
164
|
downloadedBytes?: number;
|
|
113
165
|
totalBytes?: number;
|
|
114
166
|
/** Present only when the total size is known. */
|
|
115
167
|
progress?: number;
|
|
116
|
-
|
|
168
|
+
} | {
|
|
169
|
+
kind: 'canceled';
|
|
170
|
+
downloadedBytes?: number;
|
|
171
|
+
totalBytes?: number;
|
|
172
|
+
progress?: number;
|
|
173
|
+
} | {
|
|
174
|
+
kind: 'completed';
|
|
175
|
+
downloadedBytes?: number;
|
|
176
|
+
totalBytes?: number;
|
|
177
|
+
progress?: number;
|
|
178
|
+
result: TResult;
|
|
179
|
+
};
|
|
180
|
+
export type DownloadIteratorResult<TResult extends DownloadResult = DownloadResult> = IteratorResult<DownloadProgressEvent<TResult>, void>;
|
|
181
|
+
export type AppTempDownloadResult = Extract<AppDownloadResult, {
|
|
182
|
+
storage: 'temp';
|
|
183
|
+
}>;
|
|
184
|
+
export type AppPersistedDownloadResult = Extract<AppDownloadResult, {
|
|
185
|
+
storage: 'userdata';
|
|
186
|
+
}>;
|
|
187
|
+
export type ChooseFileSingleResult = {
|
|
188
|
+
status: 'ok';
|
|
189
|
+
paths: [string];
|
|
190
|
+
} | CanceledResult;
|
|
191
|
+
/** A running operation. Progress has one consumer; stopping observation does not cancel it. */
|
|
192
|
+
export interface Task<TResult, TProgress> {
|
|
193
|
+
readonly result: Promise<TResult>;
|
|
194
|
+
readonly progress: AsyncIterable<TProgress>;
|
|
117
195
|
}
|
|
118
|
-
export interface
|
|
119
|
-
|
|
120
|
-
|
|
196
|
+
export interface CancelableTask<TResult, TProgress> extends Task<TResult, TProgress> {
|
|
197
|
+
/** Requests cancellation. Await result to observe the terminal outcome. */
|
|
198
|
+
cancel(): Promise<void>;
|
|
121
199
|
}
|
|
122
|
-
export interface DownloadTask<
|
|
123
|
-
next(): Promise<DownloadIteratorResult<TDownloadResult>>;
|
|
124
|
-
/** Stops iteration only. Does not cancel the underlying download task. */
|
|
125
|
-
return(): Promise<DownloadIteratorResult<TDownloadResult>>;
|
|
126
|
-
catch<TRejected = never>(onrejected?: ((reason: unknown) => TRejected | PromiseLike<TRejected>) | null): Promise<TDownloadResult | TRejected>;
|
|
127
|
-
finally(onfinally?: (() => void) | null): Promise<TDownloadResult>;
|
|
200
|
+
export interface DownloadTask<TResult extends DownloadResult = DownloadResult> extends CancelableTask<TResult, DownloadProgressEvent<TResult>> {
|
|
128
201
|
pause(): Promise<void>;
|
|
129
202
|
resume(): Promise<void>;
|
|
130
|
-
cancel(): Promise<void>;
|
|
131
|
-
/** Alias for cancel(), matching browser/mini-program abort naming. */
|
|
132
|
-
abort(): Promise<void>;
|
|
133
|
-
wait(): Promise<TDownloadResult>;
|
|
134
203
|
}
|
|
135
204
|
declare global {
|
|
136
205
|
/**
|
|
@@ -151,28 +220,44 @@ declare global {
|
|
|
151
220
|
readonly env: HostAppEnv;
|
|
152
221
|
/**
|
|
153
222
|
* Launch-at-startup control. Absent where the host cannot register a
|
|
154
|
-
* startup item; its presence and `lx.supports(
|
|
155
|
-
* agree, so `lx.
|
|
223
|
+
* startup item; its presence and `lx.supports('app.autostart')` always
|
|
224
|
+
* agree, so `lx.host.autostart?.…` and the query are interchangeable.
|
|
156
225
|
*/
|
|
157
226
|
autostart?: AutostartApi;
|
|
227
|
+
/**
|
|
228
|
+
* Local notifications. Absent where the host cannot post them; its presence
|
|
229
|
+
* and `lx.supports('app.notification')` always agree.
|
|
230
|
+
*/
|
|
231
|
+
notification?: NotificationApi;
|
|
232
|
+
/**
|
|
233
|
+
* Product-drawn desktop banner (top-right). Absent off desktop and in
|
|
234
|
+
* guest lxapps; its presence and `lx.supports('app.banner')`
|
|
235
|
+
* always agree.
|
|
236
|
+
*/
|
|
237
|
+
banner?: BannerApi;
|
|
158
238
|
/** The language this lxapp renders in. Every lxapp follows it. */
|
|
159
239
|
readonly displayLanguage: DisplayLanguageApi;
|
|
160
240
|
/** The light/dark scheme this lxapp renders in. */
|
|
161
241
|
readonly appearance: AppearanceApi;
|
|
162
242
|
/**
|
|
163
243
|
* Product-wide settings, and their single writer. Present only in the
|
|
164
|
-
* Control app the host sealed at build time
|
|
165
|
-
* `lx.
|
|
166
|
-
* `lx.app.control?.…` and the query are interchangeable.
|
|
244
|
+
* Control app the host sealed at build time. Use
|
|
245
|
+
* `lx.host.control !== undefined` to inspect that identity.
|
|
167
246
|
*/
|
|
168
247
|
readonly control?: ControlApi;
|
|
169
248
|
/**
|
|
170
249
|
* Product-wide cache reporting and clearing for a settings screen.
|
|
171
|
-
* Present only in the Control app;
|
|
172
|
-
* `lx.
|
|
173
|
-
* `lx.app.cache?.…` and the query are interchangeable.
|
|
250
|
+
* Present only in the Control app; presence agrees with
|
|
251
|
+
* `lx.host.control !== undefined`.
|
|
174
252
|
*/
|
|
175
253
|
cache?: AppCacheApi;
|
|
254
|
+
/**
|
|
255
|
+
* Take over host updates for the rest of this process. Irreversible: the
|
|
256
|
+
* built-in auto-flow will not prompt or download again, including after
|
|
257
|
+
* the calling page unloads. Does not cancel an already-started update task.
|
|
258
|
+
* `update.apply()` claims as well. `checkUpdate()` does not.
|
|
259
|
+
*/
|
|
260
|
+
claimCustomUpdate(): void;
|
|
176
261
|
}
|
|
177
262
|
/** Runtime environment constants backed by abstract `lx://` paths. */
|
|
178
263
|
interface LxEnv {
|
|
@@ -181,15 +266,37 @@ declare global {
|
|
|
181
266
|
/**
|
|
182
267
|
* Terminal product settings. Present only in the host-bundled Terminal
|
|
183
268
|
* Settings lxapp when the host declares `capabilities.terminal`; its
|
|
184
|
-
* presence and `lx.supports(
|
|
269
|
+
* presence and `lx.supports('terminal')` always agree.
|
|
185
270
|
*/
|
|
186
271
|
readonly terminal?: TerminalApi;
|
|
187
272
|
/** Download to the downloads directory. */
|
|
188
273
|
downloadFile(options: DownloadsDownloadOptions): DownloadTask<DownloadsDownloadResult>;
|
|
274
|
+
/** Download to a durable app-owned path. */
|
|
275
|
+
downloadFile(options: AppDownloadOptions & {
|
|
276
|
+
filePath: string;
|
|
277
|
+
}): DownloadTask<AppPersistedDownloadResult>;
|
|
278
|
+
/** Download to a temporary app-owned path. */
|
|
279
|
+
downloadFile(options: AppDownloadOptions & {
|
|
280
|
+
filePath?: undefined;
|
|
281
|
+
}): DownloadTask<AppTempDownloadResult>;
|
|
189
282
|
/** Download to the lxapp-managed app directory. */
|
|
190
283
|
downloadFile(options: AppDownloadOptions): DownloadTask<AppDownloadResult>;
|
|
191
284
|
/** Download with a destination-correlated result type. */
|
|
192
285
|
downloadFile<TDestination extends DownloadDestination = "app">(options: DownloadOptions<TDestination>): DownloadTask<DownloadResultForDestination<TDestination>>;
|
|
286
|
+
/** Single-file picker: a completed selection is exactly one path. */
|
|
287
|
+
chooseFile(options: ChooseFileOptions & {
|
|
288
|
+
multiple: false;
|
|
289
|
+
}): Promise<ChooseFileSingleResult>;
|
|
290
|
+
chooseFile(options: ChooseFileOptions & {
|
|
291
|
+
multiple: true;
|
|
292
|
+
}): Promise<ChooseFileResult>;
|
|
293
|
+
/**
|
|
294
|
+
* Opens a file picker.
|
|
295
|
+
* Resolves `{ status: 'canceled' }` only when the user dismisses the picker. A
|
|
296
|
+
* completed selection resolves `{ status: 'ok', paths }` with at least one
|
|
297
|
+
* path. Rejects when the picker fails or returns an invalid payload.
|
|
298
|
+
*/
|
|
299
|
+
chooseFile(options?: ChooseFileOptions): Promise<ChooseFileResult>;
|
|
193
300
|
/**
|
|
194
301
|
* Open this lxapp's store with every key's shape pinned on the handle.
|
|
195
302
|
* `get` / `set` / `delete` then share that schema instead of
|
|
@@ -207,7 +314,7 @@ declare global {
|
|
|
207
314
|
export type StorageSchema = object;
|
|
208
315
|
type StorageKey<S extends object> = Extract<keyof S, string>;
|
|
209
316
|
type StorageEntry<S extends object> = {
|
|
210
|
-
[K in StorageKey<S>]: [key: K, value: S[K]];
|
|
317
|
+
[K in StorageKey<S>]: [key: K, value: S[K] | DeepReadonly<S[K]>];
|
|
211
318
|
}[StorageKey<S>];
|
|
212
319
|
/**
|
|
213
320
|
* Schema-typed view of the same store `lx.getStorage()` returns.
|
|
@@ -220,7 +327,7 @@ type StorageEntry<S extends object> = {
|
|
|
220
327
|
* unchecked assertion this type exists to remove from `get<T>()`.
|
|
221
328
|
*/
|
|
222
329
|
export type TypedStorage<S extends object> = {
|
|
223
|
-
get<K extends StorageKey<S>>(key: K): Promise<S[K] | undefined>;
|
|
330
|
+
get<K extends StorageKey<S>>(key: K, decode?: (value: unknown) => S[K]): Promise<S[K] | undefined>;
|
|
224
331
|
set(...entry: StorageEntry<S>): Promise<void>;
|
|
225
332
|
has(key: StorageKey<S>): Promise<boolean>;
|
|
226
333
|
delete(key: StorageKey<S>): Promise<void>;
|
|
@@ -229,21 +336,23 @@ export type TypedStorage<S extends object> = {
|
|
|
229
336
|
info(): Promise<StorageInfo>;
|
|
230
337
|
};
|
|
231
338
|
/**
|
|
232
|
-
* Result of `lx.showActionSheet`. Branch on `
|
|
233
|
-
* the selected item
|
|
339
|
+
* Result of `lx.showActionSheet`. Branch on `status` before reading
|
|
340
|
+
* the selected item id.
|
|
234
341
|
*/
|
|
235
342
|
export type ActionSheetResult = {
|
|
236
|
-
|
|
237
|
-
/**
|
|
238
|
-
|
|
343
|
+
status: 'ok';
|
|
344
|
+
/** Stable id of the selected action. */
|
|
345
|
+
id: string;
|
|
239
346
|
} | CanceledResult;
|
|
347
|
+
/** An acknowledgement dialog has no cancel button. */
|
|
348
|
+
export type AlertOptions = Omit<ShowModalOptions, 'showCancel' | 'cancelText' | 'cancelColor'>;
|
|
240
349
|
/** Every surface handle, narrowable by `kind`. */
|
|
241
350
|
export type AnySurface = PageSurface | DeclaredSurface | AppSurface | TabSurface | BuiltinSurface;
|
|
242
351
|
/**
|
|
243
352
|
* The product-wide cache a settings screen reports and clears.
|
|
244
353
|
* App-scoped, not lxapp-scoped: the figure covers every lxapp the host
|
|
245
354
|
* has run. Injected only into the Control app, same gate as
|
|
246
|
-
* `lx.
|
|
355
|
+
* `lx.host.control` — guests do not have the member.
|
|
247
356
|
*/
|
|
248
357
|
export type AppCacheApi = {
|
|
249
358
|
/** Estimated reclaimable managed bytes; excludes live session storage and WebView cache. */
|
|
@@ -278,7 +387,7 @@ export type AppDownloadOptions = DownloadOptionsBase & {
|
|
|
278
387
|
/**
|
|
279
388
|
* Optional app-owned durable output path.
|
|
280
389
|
*
|
|
281
|
-
* Omit `filePath` to receive a temporary result in `
|
|
390
|
+
* Omit `filePath` to receive a temporary result in `uri`. Relative
|
|
282
391
|
* paths resolve under user data. `lx://` paths must target `lx://userdata`;
|
|
283
392
|
* `lx://usercache` is not accepted here.
|
|
284
393
|
*/
|
|
@@ -289,24 +398,15 @@ export type AppDownloadOptions = DownloadOptionsBase & {
|
|
|
289
398
|
destination?: 'app';
|
|
290
399
|
};
|
|
291
400
|
export type AppDownloadResult = {
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
*
|
|
295
|
-
* Not durable; move or copy it to `lx://userdata` if you need to keep it.
|
|
296
|
-
*
|
|
297
|
-
* When `filePath` is omitted, the runtime must be able to infer a file
|
|
298
|
-
* type from the URL or the server's `Content-Type` header.
|
|
299
|
-
*/
|
|
300
|
-
tempFilePath: string;
|
|
301
|
-
filePath?: never;
|
|
401
|
+
uri: AppDownloadFilePath;
|
|
402
|
+
storage: 'temp';
|
|
302
403
|
mimeType?: string;
|
|
303
|
-
|
|
404
|
+
sizeBytes: number;
|
|
304
405
|
} | {
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
tempFilePath?: never;
|
|
406
|
+
uri: AppDownloadFilePath;
|
|
407
|
+
storage: 'userdata';
|
|
308
408
|
mimeType?: string;
|
|
309
|
-
|
|
409
|
+
sizeBytes: number;
|
|
310
410
|
};
|
|
311
411
|
export type AppInstance = AppConfig & {
|
|
312
412
|
globalData: Record<string, unknown>;
|
|
@@ -350,7 +450,7 @@ export type AppScreenshotOptions = {
|
|
|
350
450
|
};
|
|
351
451
|
export type AppScreenshotResult = {
|
|
352
452
|
/** `lx://` URI of the captured PNG in the lxapp temp directory. */
|
|
353
|
-
|
|
453
|
+
uri: string;
|
|
354
454
|
/** Image width in pixels, when the runtime could read it from the PNG. */
|
|
355
455
|
width?: number;
|
|
356
456
|
/** Image height in pixels, when the runtime could read it from the PNG. */
|
|
@@ -361,7 +461,7 @@ export type AppSurface = SurfaceBase & SurfaceShowable & {
|
|
|
361
461
|
readonly kind: 'app';
|
|
362
462
|
readonly realized: 'main' | 'aside';
|
|
363
463
|
};
|
|
364
|
-
/** `lx.
|
|
464
|
+
/** `lx.host.appearance` — the scheme this lxapp renders in. */
|
|
365
465
|
export type AppearanceApi = {
|
|
366
466
|
/**
|
|
367
467
|
* The scheme this lxapp is rendering in. An lxapp that pinned one in its
|
|
@@ -381,25 +481,6 @@ export type AppearanceApi = {
|
|
|
381
481
|
* the system.
|
|
382
482
|
*/
|
|
383
483
|
export type AppearancePreference = 'auto' | 'light' | 'dark';
|
|
384
|
-
/**
|
|
385
|
-
* Launch-at-startup control for the host app.
|
|
386
|
-
* Absent (`undefined`) wherever the host cannot register a startup item.
|
|
387
|
-
* `lx.supports({ capability: 'autostart' })` and the member's presence always
|
|
388
|
-
* agree, so either gate works:
|
|
389
|
-
* ```ts
|
|
390
|
-
* if (lx.supports({ capability: 'autostart' })) {
|
|
391
|
-
* // render the "Launch at startup" toggle
|
|
392
|
-
* }
|
|
393
|
-
* ```
|
|
394
|
-
* Requires `capabilities.autostart: true` in `lingxia.yaml`; without it the
|
|
395
|
-
* member is absent on all platforms. Declaring the capability never enables
|
|
396
|
-
* autostart by itself — the SDK registers the app only when `setEnabled(true)`
|
|
397
|
-
* is called, so the decision stays with the user (typically a settings-page
|
|
398
|
-
* toggle, default off).
|
|
399
|
-
* Host-app-level capability: like `checkUpdate` and `screenshot`, the methods
|
|
400
|
-
* are available only to the native-assigned Control app; other lxapps receive
|
|
401
|
-
* a permission error.
|
|
402
|
-
*/
|
|
403
484
|
export type AutostartApi = {
|
|
404
485
|
/**
|
|
405
486
|
* Whether the app is currently registered to launch at startup, read from
|
|
@@ -416,6 +497,40 @@ export type AutostartApi = {
|
|
|
416
497
|
*/
|
|
417
498
|
setEnabled(on: boolean): Promise<void>;
|
|
418
499
|
};
|
|
500
|
+
/**
|
|
501
|
+
* Product-drawn desktop banner, top-right. Not an OS notification and
|
|
502
|
+
* not bound to App Link. Present only in the desktop Control app;
|
|
503
|
+
* presence and `lx.supports('app.banner')` always agree.
|
|
504
|
+
* No buttons: an informational card that auto-dismisses (5s unless
|
|
505
|
+
* `timeoutMs` is set). With buttons: a gate that waits for a choice,
|
|
506
|
+
* dismiss, timeout, or replace. User outcomes resolve; presentation
|
|
507
|
+
* failures reject.
|
|
508
|
+
*/
|
|
509
|
+
export type BannerApi = {
|
|
510
|
+
show(options: {
|
|
511
|
+
id?: string;
|
|
512
|
+
title: string;
|
|
513
|
+
body?: string;
|
|
514
|
+
actions?: Array<{
|
|
515
|
+
id: string;
|
|
516
|
+
label: string;
|
|
517
|
+
style?: 'default' | 'primary' | 'destructive';
|
|
518
|
+
}>;
|
|
519
|
+
timeoutMs?: number;
|
|
520
|
+
/** Omit/`system` follows the OS. `light`/`dark` force chrome. `#RGB`/`#RRGGBB`/`#RRGGBBAA` is a solid fill. */
|
|
521
|
+
background?: 'system' | 'light' | 'dark' | string;
|
|
522
|
+
}): Promise<{
|
|
523
|
+
status: 'ok';
|
|
524
|
+
id: string;
|
|
525
|
+
action: string;
|
|
526
|
+
} | {
|
|
527
|
+
status: 'canceled';
|
|
528
|
+
id: string;
|
|
529
|
+
reason: 'dismissed' | 'timeout' | 'replaced';
|
|
530
|
+
}>;
|
|
531
|
+
/** Unknown ids are fine. */
|
|
532
|
+
dismiss(id: string): Promise<void>;
|
|
533
|
+
};
|
|
419
534
|
export type BinaryFileData = ArrayBuffer | ArrayBufferView;
|
|
420
535
|
/**
|
|
421
536
|
* Built-in browser product page. Opening one requires
|
|
@@ -425,26 +540,25 @@ export type BuiltinShellPage = 'downloads';
|
|
|
425
540
|
/**
|
|
426
541
|
* A host builtin page such as downloads. The shell owns
|
|
427
542
|
* its lifetime and its visibility, so this handle reports identity:
|
|
428
|
-
* there is no `show
|
|
429
|
-
* with `unsupported_placement`.
|
|
543
|
+
* there is no `show`, `hide`, `close`, or `onClose`.
|
|
430
544
|
*/
|
|
431
|
-
export type BuiltinSurface = SurfaceBase & {
|
|
545
|
+
export type BuiltinSurface = Omit<SurfaceBase, 'close' | 'onClose'> & {
|
|
432
546
|
readonly kind: 'builtin';
|
|
433
547
|
};
|
|
434
548
|
/** The user dismissed the operation. Never an error. */
|
|
435
549
|
export type CanceledResult = {
|
|
436
|
-
|
|
550
|
+
status: 'canceled';
|
|
437
551
|
};
|
|
438
552
|
export type ChooseDirectoryOptions = {
|
|
439
553
|
/** Initial directory the dialog opens in. Platform default if omitted. */
|
|
440
554
|
defaultPath?: string;
|
|
441
555
|
};
|
|
442
556
|
/**
|
|
443
|
-
* Result of `lx.chooseDirectory`. Branch on `
|
|
557
|
+
* Result of `lx.chooseDirectory`. Branch on `status` before reading
|
|
444
558
|
* the selected directory.
|
|
445
559
|
*/
|
|
446
560
|
export type ChooseDirectoryResult = {
|
|
447
|
-
|
|
561
|
+
status: 'ok';
|
|
448
562
|
/** Native-consumable directory reference (path or URI). */
|
|
449
563
|
path: string;
|
|
450
564
|
} | CanceledResult;
|
|
@@ -462,11 +576,11 @@ export type ChooseFileOptions = {
|
|
|
462
576
|
defaultPath?: string;
|
|
463
577
|
};
|
|
464
578
|
/**
|
|
465
|
-
* Result of `lx.chooseFile`. Branch on `
|
|
579
|
+
* Result of `lx.chooseFile`. Branch on `status` before reading the
|
|
466
580
|
* selected paths.
|
|
467
581
|
*/
|
|
468
582
|
export type ChooseFileResult = {
|
|
469
|
-
|
|
583
|
+
status: 'ok';
|
|
470
584
|
/**
|
|
471
585
|
* File paths returned by LingXia; always at least one. Values may be
|
|
472
586
|
* app-local paths, `lx://...` paths, or platform system-picker references.
|
|
@@ -480,22 +594,79 @@ export type ChooseMediaOptions = {
|
|
|
480
594
|
mediaType?: ('image' | 'video')[];
|
|
481
595
|
sourceType?: ('album' | 'camera')[];
|
|
482
596
|
camera?: 'back' | 'front';
|
|
483
|
-
|
|
597
|
+
maxDurationSeconds?: number;
|
|
484
598
|
};
|
|
485
599
|
/**
|
|
486
|
-
* Result of `lx.chooseMedia`. Branch on `
|
|
600
|
+
* Result of `lx.chooseMedia`. Branch on `status` before reading the
|
|
487
601
|
* selected entries.
|
|
488
602
|
*/
|
|
489
603
|
export type ChooseMediaResult = {
|
|
490
|
-
|
|
604
|
+
status: 'ok';
|
|
491
605
|
/** Picked media; always at least one entry. */
|
|
492
606
|
entries: [ChosenMediaEntry, ...ChosenMediaEntry[]];
|
|
493
607
|
} | CanceledResult;
|
|
494
608
|
export type ChosenMediaEntry = {
|
|
495
|
-
|
|
609
|
+
uri: string;
|
|
496
610
|
fileType: 'image' | 'video';
|
|
497
611
|
isOriginal: boolean;
|
|
498
612
|
};
|
|
613
|
+
export type ClipboardApi = globalThis.ClipboardApi;
|
|
614
|
+
export type ClipboardItem = {
|
|
615
|
+
type: 'text';
|
|
616
|
+
text: string;
|
|
617
|
+
} | {
|
|
618
|
+
type: 'image';
|
|
619
|
+
/**
|
|
620
|
+
* Temporary `lx://temp` PNG, session-scoped and auto-cleaned. Move or
|
|
621
|
+
* copy it with `lx.fs` if you need to keep it.
|
|
622
|
+
*/
|
|
623
|
+
filePath: string;
|
|
624
|
+
};
|
|
625
|
+
export type ClipboardReadOptions = {
|
|
626
|
+
/** Omit to receive every representation the host can surface. */
|
|
627
|
+
type?: ClipboardType;
|
|
628
|
+
};
|
|
629
|
+
/**
|
|
630
|
+
* Result of `lx.clipboard.read`. Omit `type` to receive every
|
|
631
|
+
* representation this host can surface. A requested type that is
|
|
632
|
+
* absent is `{ status: 'empty' }`, not an error.
|
|
633
|
+
*/
|
|
634
|
+
export type ClipboardReadResult = {
|
|
635
|
+
status: 'empty';
|
|
636
|
+
} | {
|
|
637
|
+
status: 'ok';
|
|
638
|
+
items: ClipboardItem[];
|
|
639
|
+
} | CanceledResult;
|
|
640
|
+
/**
|
|
641
|
+
* Result of `lx.clipboard.readText`. Branch on `status`.
|
|
642
|
+
* A copied empty string is `{ status: 'ok', text: '' }`;
|
|
643
|
+
* an image-only clipboard is `{ status: 'empty' }`.
|
|
644
|
+
*/
|
|
645
|
+
export type ClipboardTextResult = {
|
|
646
|
+
status: 'empty';
|
|
647
|
+
} | {
|
|
648
|
+
status: 'ok';
|
|
649
|
+
text: string;
|
|
650
|
+
} | CanceledResult;
|
|
651
|
+
/** Representations the runtime can round-trip. Closed union. */
|
|
652
|
+
export type ClipboardType = 'text' | 'image';
|
|
653
|
+
/**
|
|
654
|
+
* One clipboard write. Every host accepts both: `image` takes a PNG or
|
|
655
|
+
* JPEG file and re-encodes it as the platform's native image format.
|
|
656
|
+
*/
|
|
657
|
+
export type ClipboardWriteItem = {
|
|
658
|
+
type: 'text';
|
|
659
|
+
/** Unicode text. Rejects `E_INVALID_ARG` when larger than 1 MiB. */
|
|
660
|
+
text: string;
|
|
661
|
+
} | {
|
|
662
|
+
type: 'image';
|
|
663
|
+
/**
|
|
664
|
+
* Managed `lx://` path, or a picker result from `lx.chooseFile` /
|
|
665
|
+
* `lx.chooseMedia` — the same file rules as `lx.share`. Rejects
|
|
666
|
+
* `E_INVALID_ARG` when the file is not a decodable image.
|
|
667
|
+
*/
|
|
668
|
+
filePath: string;
|
|
669
|
+
};
|
|
499
670
|
export type CompressImageOptions = {
|
|
500
671
|
path: string;
|
|
501
672
|
quality?: number;
|
|
@@ -503,25 +674,30 @@ export type CompressImageOptions = {
|
|
|
503
674
|
compressedHeight?: number;
|
|
504
675
|
};
|
|
505
676
|
export type CompressImageResult = {
|
|
506
|
-
|
|
507
|
-
};
|
|
508
|
-
export type CompressVideoIteratorResult = {
|
|
509
|
-
done: boolean;
|
|
510
|
-
value?: CompressVideoProgressEvent;
|
|
677
|
+
uri: string;
|
|
511
678
|
};
|
|
679
|
+
export type CompressVideoIteratorResult = IteratorResult<CompressVideoProgressEvent, void>;
|
|
512
680
|
export type CompressVideoOptions = {
|
|
681
|
+
signal?: AbortSignal;
|
|
513
682
|
/**
|
|
514
683
|
* Source video path or `lx://` URI.
|
|
515
684
|
*/
|
|
516
685
|
path: string;
|
|
517
686
|
/**
|
|
518
|
-
*
|
|
519
|
-
|
|
520
|
-
|
|
687
|
+
* Optional output path for compressed file.
|
|
688
|
+
*/
|
|
689
|
+
outputPath?: string;
|
|
690
|
+
} & ({
|
|
691
|
+
/**
|
|
521
692
|
* Compression quality preset.
|
|
522
|
-
*
|
|
693
|
+
* Mutually exclusive with `bitrate`, `fps`, and `resolution`.
|
|
523
694
|
*/
|
|
524
|
-
quality
|
|
695
|
+
quality: VideoCompressQuality;
|
|
696
|
+
bitrate?: never;
|
|
697
|
+
fps?: never;
|
|
698
|
+
resolution?: never;
|
|
699
|
+
} | {
|
|
700
|
+
quality?: never;
|
|
525
701
|
/**
|
|
526
702
|
* Preferred target video bitrate in kbps.
|
|
527
703
|
* May be adjusted or ignored by platform codec/runtime limitations.
|
|
@@ -537,17 +713,13 @@ export type CompressVideoOptions = {
|
|
|
537
713
|
* May be approximated or ignored by platform transcoder capabilities.
|
|
538
714
|
*/
|
|
539
715
|
resolution?: number;
|
|
540
|
-
|
|
541
|
-
* Optional output path for compressed file.
|
|
542
|
-
*/
|
|
543
|
-
outputPath?: string;
|
|
544
|
-
};
|
|
716
|
+
});
|
|
545
717
|
export type CompressVideoProgressEvent = {
|
|
546
718
|
/** Transcode progress in percent, `0`-`100`. */
|
|
547
719
|
progress: number;
|
|
548
720
|
};
|
|
549
721
|
export type CompressVideoResult = {
|
|
550
|
-
|
|
722
|
+
uri: string;
|
|
551
723
|
width: number;
|
|
552
724
|
height: number;
|
|
553
725
|
durationMs: number;
|
|
@@ -560,23 +732,11 @@ export type CompressVideoResult = {
|
|
|
560
732
|
};
|
|
561
733
|
/**
|
|
562
734
|
* Handle returned by `lx.compressVideo`.
|
|
563
|
-
* Awaiting
|
|
564
|
-
* Iterating
|
|
735
|
+
* Awaiting `task.result` resolves with the final {@link CompressVideoResult}.
|
|
736
|
+
* Iterating `task.progress` with `for await` yields {@link CompressVideoProgressEvent}s
|
|
565
737
|
* while the transcode runs.
|
|
566
738
|
*/
|
|
567
|
-
export type CompressVideoTask =
|
|
568
|
-
next(): Promise<CompressVideoIteratorResult>;
|
|
569
|
-
/** Stops iteration only. Does not cancel the compression. */
|
|
570
|
-
return(): Promise<CompressVideoIteratorResult>;
|
|
571
|
-
catch<TResult = never>(onrejected?: ((reason: unknown) => TResult | PromiseLike<TResult>) | null): Promise<CompressVideoResult | TResult>;
|
|
572
|
-
finally(onfinally?: (() => void) | null): Promise<CompressVideoResult>;
|
|
573
|
-
/**
|
|
574
|
-
* Cancels the transcode and deletes any partial output.
|
|
575
|
-
* The task promise rejects with an `AbortError` (`code: 'E_ABORT'`).
|
|
576
|
-
*/
|
|
577
|
-
cancel(): void;
|
|
578
|
-
wait(): Promise<CompressVideoResult>;
|
|
579
|
-
};
|
|
739
|
+
export type CompressVideoTask = CancelableTask<CompressVideoResult, CompressVideoProgressEvent>;
|
|
580
740
|
/**
|
|
581
741
|
* Configured page name from `lxapp.json` / `lingxia.yaml`. JavaScript
|
|
582
742
|
* navigation accepts only this name; full routes such as
|
|
@@ -587,16 +747,18 @@ export type CompressVideoTask = PromiseLike<CompressVideoResult> & AsyncIterable
|
|
|
587
747
|
* a project that never ran a build still compiles.
|
|
588
748
|
*/
|
|
589
749
|
export type ConfiguredPageName = keyof LxAppPages extends never ? string : keyof LxAppPages;
|
|
750
|
+
/** A confirmation dialog always permits declining. */
|
|
751
|
+
export type ConfirmOptions = Omit<ShowModalOptions, 'showCancel'>;
|
|
590
752
|
export type ConnectWifiOptions = {
|
|
591
|
-
|
|
753
|
+
ssid: string;
|
|
592
754
|
password?: string;
|
|
593
755
|
};
|
|
594
756
|
/**
|
|
595
|
-
* `lx.
|
|
757
|
+
* `lx.host.control` — product-wide settings, and their single writer.
|
|
596
758
|
* Present only in the Control app. Bind it once rather than repeating
|
|
597
|
-
* `lx.
|
|
759
|
+
* `lx.host.control!`:
|
|
598
760
|
* ```js
|
|
599
|
-
* const control = lx.
|
|
761
|
+
* const control = lx.host.control;
|
|
600
762
|
* if (!control) return; // not the Control app
|
|
601
763
|
* await control.appearance.setPreference('dark');
|
|
602
764
|
* ```
|
|
@@ -605,7 +767,7 @@ export type ControlApi = {
|
|
|
605
767
|
readonly displayLanguage: ControlDisplayLanguageApi;
|
|
606
768
|
readonly appearance: ControlAppearanceApi;
|
|
607
769
|
};
|
|
608
|
-
/** `lx.
|
|
770
|
+
/** `lx.host.control.appearance` — the product's own light/dark setting. */
|
|
609
771
|
export type ControlAppearanceApi = {
|
|
610
772
|
/** What the user chose for the whole product. */
|
|
611
773
|
getPreference(): AppearancePreference;
|
|
@@ -616,14 +778,14 @@ export type ControlAppearanceApi = {
|
|
|
616
778
|
setPreference(preference: AppearancePreference): Promise<void>;
|
|
617
779
|
/**
|
|
618
780
|
* Follow the choice, not what it resolves to: a system flip under `'auto'`
|
|
619
|
-
* moves `lx.
|
|
781
|
+
* moves `lx.host.appearance.watch` and leaves this quiet. Starts with the
|
|
620
782
|
* current value; that first callback runs synchronously, before
|
|
621
783
|
* `watchPreference` returns.
|
|
622
784
|
*/
|
|
623
785
|
watchPreference(callback: (preference: AppearancePreference) => void): () => void;
|
|
624
786
|
};
|
|
625
787
|
/**
|
|
626
|
-
* `lx.
|
|
788
|
+
* `lx.host.control.displayLanguage` — the preference behind that
|
|
627
789
|
* language, for the one surface that edits it.
|
|
628
790
|
*/
|
|
629
791
|
export type ControlDisplayLanguageApi = {
|
|
@@ -648,7 +810,7 @@ export type DeviceOrientation = "portrait" | "landscape";
|
|
|
648
810
|
export type DeviceOrientationChangeEvent = {
|
|
649
811
|
value: DeviceOrientation;
|
|
650
812
|
};
|
|
651
|
-
/** `lx.
|
|
813
|
+
/** `lx.host.displayLanguage` — the language this lxapp renders in. */
|
|
652
814
|
export type DisplayLanguageApi = {
|
|
653
815
|
/**
|
|
654
816
|
* The language in effect right now, as a canonical BCP-47 tag. Map it to
|
|
@@ -685,7 +847,7 @@ export type DownloadOptionsBase = {
|
|
|
685
847
|
*/
|
|
686
848
|
headers?: Record<string, string>;
|
|
687
849
|
/** Request timeout in milliseconds. */
|
|
688
|
-
|
|
850
|
+
timeoutMs?: number;
|
|
689
851
|
/** Optional abort signal. */
|
|
690
852
|
signal?: AbortSignal;
|
|
691
853
|
};
|
|
@@ -695,16 +857,16 @@ export type DownloadsDownloadOptions = DownloadOptionsBase & {
|
|
|
695
857
|
* Optional filename hint for the system Downloads destination.
|
|
696
858
|
* This is not an app-owned `lx.fs` path.
|
|
697
859
|
*/
|
|
698
|
-
|
|
860
|
+
suggestedName?: string;
|
|
861
|
+
filePath?: never;
|
|
699
862
|
/** Save into the user's system Downloads directory. */
|
|
700
863
|
destination: 'downloads';
|
|
701
864
|
};
|
|
702
865
|
export type DownloadsDownloadResult = {
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
tempFilePath?: never;
|
|
866
|
+
uri: SystemDownloadsPath;
|
|
867
|
+
storage: 'downloads';
|
|
706
868
|
mimeType?: string;
|
|
707
|
-
|
|
869
|
+
sizeBytes: number;
|
|
708
870
|
};
|
|
709
871
|
/**
|
|
710
872
|
* Configured page name belonging to *another* lxapp. This app's own
|
|
@@ -745,7 +907,7 @@ export type ExtractVideoThumbnailResult = {
|
|
|
745
907
|
/**
|
|
746
908
|
* Generated thumbnail file path.
|
|
747
909
|
*/
|
|
748
|
-
|
|
910
|
+
uri: string;
|
|
749
911
|
/**
|
|
750
912
|
* Output image width in pixels.
|
|
751
913
|
*/
|
|
@@ -795,10 +957,10 @@ export type GetImageInfoOptions = {
|
|
|
795
957
|
};
|
|
796
958
|
/** Location APIs. */
|
|
797
959
|
export type GetLocationOptions = {
|
|
798
|
-
|
|
960
|
+
coordinateSystem?: 'wgs84' | 'gcj02';
|
|
799
961
|
altitude?: boolean;
|
|
800
962
|
isHighAccuracy?: boolean;
|
|
801
|
-
|
|
963
|
+
timeoutMs?: number;
|
|
802
964
|
};
|
|
803
965
|
export type GetVideoInfoOptions = {
|
|
804
966
|
/**
|
|
@@ -832,7 +994,7 @@ export type HostAppUpdateEvent = {
|
|
|
832
994
|
downloadedBytes?: number;
|
|
833
995
|
progress?: number;
|
|
834
996
|
} | {
|
|
835
|
-
state: 'downloaded' | 'installRequested';
|
|
997
|
+
state: 'downloaded' | 'installRequested' | 'storeOpened';
|
|
836
998
|
} | {
|
|
837
999
|
state: 'failed';
|
|
838
1000
|
stage: HostAppUpdateApplyStage;
|
|
@@ -842,38 +1004,36 @@ export type HostAppUpdateInfo = {
|
|
|
842
1004
|
version: string;
|
|
843
1005
|
size?: number;
|
|
844
1006
|
releaseNotes?: string[];
|
|
845
|
-
isForceUpdate: boolean;
|
|
846
1007
|
/**
|
|
847
|
-
*
|
|
1008
|
+
* How this update is applied. `store` opens the platform marketplace;
|
|
1009
|
+
* `direct` downloads and self-installs. `lx.supports('app.selfUpdate')`
|
|
1010
|
+
* is true only for `direct`.
|
|
1011
|
+
*/
|
|
1012
|
+
channel: 'direct' | 'store';
|
|
1013
|
+
/**
|
|
1014
|
+
* Apply this checked update.
|
|
848
1015
|
*
|
|
849
|
-
* `apply()` is single-use for this update object.
|
|
1016
|
+
* `apply()` is single-use for this update object. It also claims custom
|
|
1017
|
+
* host updates for the rest of this process, same as
|
|
1018
|
+
* {@link HostAppApi.claimCustomUpdate}.
|
|
850
1019
|
*
|
|
851
|
-
*
|
|
852
|
-
*
|
|
1020
|
+
* Await `task.result` when progress is not needed, or iterate
|
|
1021
|
+
* `task.progress` to render it.
|
|
853
1022
|
*
|
|
854
|
-
*
|
|
855
|
-
*
|
|
856
|
-
*
|
|
1023
|
+
* On `direct`, downloads and hands off install. On `store`, opens the
|
|
1024
|
+
* platform store listing (no package is downloaded) and resolves
|
|
1025
|
+
* `storeOpened`; whether the user then updates is not reported.
|
|
857
1026
|
*/
|
|
858
1027
|
apply(): HostAppUpdateTask;
|
|
859
1028
|
};
|
|
860
|
-
export type HostAppUpdateIteratorResult =
|
|
861
|
-
done: boolean;
|
|
862
|
-
value?: HostAppUpdateEvent;
|
|
863
|
-
};
|
|
1029
|
+
export type HostAppUpdateIteratorResult = IteratorResult<HostAppUpdateEvent, void>;
|
|
864
1030
|
export type HostAppUpdateResult = {
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
export type HostAppUpdateTask = PromiseLike<HostAppUpdateResult> & AsyncIterable<HostAppUpdateEvent> & {
|
|
868
|
-
next(): Promise<HostAppUpdateIteratorResult>;
|
|
869
|
-
/** Stops iteration only. It does not cancel an app update already handed to the platform. */
|
|
870
|
-
return(): Promise<HostAppUpdateIteratorResult>;
|
|
871
|
-
catch<TResult = never>(onrejected?: ((reason: unknown) => TResult | PromiseLike<TResult>) | null): Promise<HostAppUpdateResult | TResult>;
|
|
872
|
-
finally(onfinally?: (() => void) | null): Promise<HostAppUpdateResult>;
|
|
873
|
-
wait(): Promise<HostAppUpdateResult>;
|
|
1031
|
+
/** `storeOpened` on a `store` channel: the listing opened, nothing was installed. */
|
|
1032
|
+
state: 'installRequested' | 'storeOpened';
|
|
874
1033
|
};
|
|
1034
|
+
export type HostAppUpdateTask = Task<HostAppUpdateResult, HostAppUpdateEvent>;
|
|
875
1035
|
/**
|
|
876
|
-
* Canonical platform-family label shared by `lx.
|
|
1036
|
+
* Canonical platform-family label shared by `lx.host.getBaseInfo().os`
|
|
877
1037
|
* and `lx.getDeviceInfo().osName`. `"unknown"` is a non-product build.
|
|
878
1038
|
*/
|
|
879
1039
|
export type HostOs = 'iOS' | 'macOS' | 'Android' | 'Windows' | 'Harmony' | 'unknown';
|
|
@@ -883,6 +1043,38 @@ export type InstalledTerminalFont = {
|
|
|
883
1043
|
ligatures: boolean;
|
|
884
1044
|
nerdIcons: boolean;
|
|
885
1045
|
};
|
|
1046
|
+
/**
|
|
1047
|
+
* Launch-at-startup control for the host app.
|
|
1048
|
+
* Absent (`undefined`) wherever the host cannot register a startup item.
|
|
1049
|
+
* `lx.supports('app.autostart')` and the member's presence always
|
|
1050
|
+
* agree, so either gate works:
|
|
1051
|
+
* ```ts
|
|
1052
|
+
* if (lx.supports('app.autostart')) {
|
|
1053
|
+
* // render the "Launch at startup" toggle
|
|
1054
|
+
* }
|
|
1055
|
+
* ```
|
|
1056
|
+
* Requires `capabilities.autostart: true` in `lingxia.yaml`; without it the
|
|
1057
|
+
* member is absent on all platforms. Declaring the capability never enables
|
|
1058
|
+
* autostart by itself — the SDK registers the app only when `setEnabled(true)`
|
|
1059
|
+
* is called, so the decision stays with the user (typically a settings-page
|
|
1060
|
+
* toggle, default off).
|
|
1061
|
+
* Host-app-level capability: like `checkUpdate` and `screenshot`, the methods
|
|
1062
|
+
* are available only to the native-assigned Control app; other lxapps receive
|
|
1063
|
+
* a permission error.
|
|
1064
|
+
* Local notifications as a Control-app resume affordance.
|
|
1065
|
+
* Absent unless the host declared `capabilities.notifications` and the
|
|
1066
|
+
* platform implements the local API. Presence and
|
|
1067
|
+
* `lx.supports('app.notification')` always agree.
|
|
1068
|
+
* Declaring the capability never prompts; permission runs on
|
|
1069
|
+
* `requestPermission()` or the first `show()` that reaches the OS.
|
|
1070
|
+
* Control app only. Guest lxapps receive a permission error.
|
|
1071
|
+
* A JSON value: what a navigation route parameter may hold. Not a way
|
|
1072
|
+
* to smuggle a payload — every route declares its own parameter
|
|
1073
|
+
* schema, and the framework caps size, count, and nesting.
|
|
1074
|
+
*/
|
|
1075
|
+
export type JsonValue = null | boolean | number | string | JsonValue[] | {
|
|
1076
|
+
[key: string]: JsonValue;
|
|
1077
|
+
};
|
|
886
1078
|
/**
|
|
887
1079
|
* Input event APIs.
|
|
888
1080
|
* Platform support: Android only
|
|
@@ -902,34 +1094,7 @@ export type KeyEventCallback = (event: KeyEvent) => void;
|
|
|
902
1094
|
export type LxAppEnvVersion = 'release' | 'draft';
|
|
903
1095
|
/** LxApp metadata APIs. */
|
|
904
1096
|
export type LxAppReleaseType = 'release' | 'draft';
|
|
905
|
-
/** Boolean capability names accepted by `lx.supports`. */
|
|
906
|
-
export type LxCapabilityFlag = 'control' | 'terminal' | 'autostart' | 'notifications' | 'browser' | 'proxy' | 'selfUpdate' | 'process' | 'appUse' | 'computerUse' | 'browserUse' | 'mediaCapture';
|
|
907
|
-
/**
|
|
908
|
-
* One capability question per call. The catalog is closed, so
|
|
909
|
-
* completion enumerates it and a typo is a type error. `capability`
|
|
910
|
-
* is the discriminant; only the `surface` branch accepts a `value`.
|
|
911
|
-
* Two surface answers describe an *affordance*, not whether the call
|
|
912
|
-
* succeeds: `tab` is "the host has an in-app browser" — without it a
|
|
913
|
-
* url still opens, in the OS browser instead — and `aside` is "a
|
|
914
|
-
* docked region exists right now", while a compact layout still opens
|
|
915
|
-
* the url through the in-app browser's own chrome. Ask them to decide
|
|
916
|
-
* what to render, not whether to call.
|
|
917
|
-
* `chrome` qualifies a window and only a window: it asks whether this
|
|
918
|
-
* host can produce that decoration, not merely a window.
|
|
919
|
-
*/
|
|
920
|
-
export type LxCapabilityQuery = {
|
|
921
|
-
capability: 'surface';
|
|
922
|
-
value: 'window';
|
|
923
|
-
chrome?: WindowChrome;
|
|
924
|
-
} | {
|
|
925
|
-
capability: 'surface';
|
|
926
|
-
value: Exclude<LxSurfaceCapability, 'window'>;
|
|
927
|
-
} | {
|
|
928
|
-
capability: LxCapabilityFlag;
|
|
929
|
-
};
|
|
930
1097
|
export type LxEnv = globalThis.LxEnv;
|
|
931
|
-
/** Surface placements accepted by `lx.supports`. */
|
|
932
|
-
export type LxSurfaceCapability = 'main' | 'aside' | 'float' | 'window' | 'tab';
|
|
933
1098
|
/** Device action APIs. */
|
|
934
1099
|
export type MakePhoneCallOptions = {
|
|
935
1100
|
phoneNumber: string;
|
|
@@ -937,11 +1102,11 @@ export type MakePhoneCallOptions = {
|
|
|
937
1102
|
export type MediaObjectFit = 'cover' | 'contain' | 'fill' | 'fit';
|
|
938
1103
|
export type MediaRotation = 0 | 90 | 180 | 270;
|
|
939
1104
|
/**
|
|
940
|
-
* Result of `lx.showModal`. `
|
|
1105
|
+
* Result of `lx.showModal`. `status: 'ok'` means the user confirmed;
|
|
941
1106
|
* there is no third resolved outcome. Presentation failures reject.
|
|
942
1107
|
*/
|
|
943
1108
|
export type ModalResult = {
|
|
944
|
-
|
|
1109
|
+
status: 'ok';
|
|
945
1110
|
} | CanceledResult;
|
|
946
1111
|
/**
|
|
947
1112
|
* One app-declared action shown in the host-provided More affordance.
|
|
@@ -997,6 +1162,36 @@ export type NavigationBarStylePatch = {
|
|
|
997
1162
|
foregroundColor?: string | null;
|
|
998
1163
|
dividerColor?: string | null;
|
|
999
1164
|
};
|
|
1165
|
+
/**
|
|
1166
|
+
* Where a notification tap, a menu item, or the tray goes.
|
|
1167
|
+
* `page` and `app` are the same contract as `lx.navigateTo` /
|
|
1168
|
+
* `lx.navigateToApp`: a configured page name and a query, ordinary
|
|
1169
|
+
* scene. `route` is a host-registered location that is not a page.
|
|
1170
|
+
* `appLink` is an `https://` product URL that is also a real inbound
|
|
1171
|
+
* App Link (`scene === 8003`). `activate` just brings the product
|
|
1172
|
+
* forward.
|
|
1173
|
+
* A branch carries its own fields and no others: a mixed target is a
|
|
1174
|
+
* parameter error, not a best guess.
|
|
1175
|
+
*/
|
|
1176
|
+
export type NavigationTarget = {
|
|
1177
|
+
kind: 'activate';
|
|
1178
|
+
} | {
|
|
1179
|
+
kind: 'page';
|
|
1180
|
+
page: ConfiguredPageName;
|
|
1181
|
+
query?: PageQuery;
|
|
1182
|
+
} | {
|
|
1183
|
+
kind: 'app';
|
|
1184
|
+
appId: string;
|
|
1185
|
+
page?: ExternalPageName;
|
|
1186
|
+
query?: PageQuery;
|
|
1187
|
+
} | {
|
|
1188
|
+
kind: 'route';
|
|
1189
|
+
name: string;
|
|
1190
|
+
params?: Record<string, JsonValue>;
|
|
1191
|
+
} | {
|
|
1192
|
+
kind: 'appLink';
|
|
1193
|
+
url: string;
|
|
1194
|
+
};
|
|
1000
1195
|
export type NetworkChangeCallback = (info: NetworkInfo) => void;
|
|
1001
1196
|
export type NetworkInfo = {
|
|
1002
1197
|
isConnected: boolean;
|
|
@@ -1006,6 +1201,72 @@ export type NetworkInfo = {
|
|
|
1006
1201
|
};
|
|
1007
1202
|
/** Network status APIs. */
|
|
1008
1203
|
export type NetworkType = 'none' | 'unknown' | 'wifi' | '2g' | '3g' | '4g' | '5g' | 'ethernet';
|
|
1204
|
+
export type NotificationApi = {
|
|
1205
|
+
/**
|
|
1206
|
+
* Read the current permission without prompting. `'default'` means the
|
|
1207
|
+
* user has not been asked yet.
|
|
1208
|
+
*/
|
|
1209
|
+
getPermission(): Promise<'granted' | 'denied' | 'default'>;
|
|
1210
|
+
/**
|
|
1211
|
+
* Ask for notification permission. Prompts where the OS has a prompt and
|
|
1212
|
+
* the user has not answered; otherwise reports the current setting.
|
|
1213
|
+
* Rejects when the prompt is left unanswered.
|
|
1214
|
+
*/
|
|
1215
|
+
requestPermission(): Promise<'granted' | 'denied'>;
|
|
1216
|
+
/**
|
|
1217
|
+
* Post or replace a local notification. `id` is the replace key: anything
|
|
1218
|
+
* pending or delivered under it is replaced, whatever `status` comes back,
|
|
1219
|
+
* and its old tap target stops resolving. Omit `id` to get a generated
|
|
1220
|
+
* one. Omit `schedule`, or pass a time that is not in the future, to post
|
|
1221
|
+
* now.
|
|
1222
|
+
*
|
|
1223
|
+
* `target` is where the tap goes, and an omitted one means
|
|
1224
|
+
* `{ kind: 'activate' }` — bring the product forward, nothing else.
|
|
1225
|
+
* `{ kind: 'page' }` opens a page of this Control app the way
|
|
1226
|
+
* `lx.navigateTo` does. `{ kind: 'app' }` opens another lxapp the way
|
|
1227
|
+
* `lx.navigateToApp` does. `{ kind: 'route' }` names a location the host
|
|
1228
|
+
* registered at startup that is not a page. `{ kind: 'appLink' }` takes
|
|
1229
|
+
* an `https://` URL that is also a real inbound App Link
|
|
1230
|
+
* (`scene === 8003`). An unknown page or route, a parameter the route
|
|
1231
|
+
* did not declare, or a host that is not configured rejects here, before
|
|
1232
|
+
* anything is posted.
|
|
1233
|
+
*
|
|
1234
|
+
* `status` says what happened: `'posted'` — the OS accepted it for
|
|
1235
|
+
* display now, which is not a receipt that anyone saw or read it;
|
|
1236
|
+
* `'scheduled'` — queued with the OS for `schedule`; `'suppressed'` — an
|
|
1237
|
+
* immediate post while the product is already frontmost, where nothing is
|
|
1238
|
+
* posted and no permission is needed. A scheduled notification is
|
|
1239
|
+
* presented even if the product is frontmost when it fires.
|
|
1240
|
+
*
|
|
1241
|
+
* A tap resolves through the host, so a target that is gone by then — a
|
|
1242
|
+
* route the build no longer registers, a cancelled or replaced
|
|
1243
|
+
* notification, cleared app data — brings the product forward and says it
|
|
1244
|
+
* is unavailable rather than opening something else.
|
|
1245
|
+
*/
|
|
1246
|
+
show(options: {
|
|
1247
|
+
id?: string;
|
|
1248
|
+
title: string;
|
|
1249
|
+
body?: string;
|
|
1250
|
+
target?: NavigationTarget;
|
|
1251
|
+
schedule?: {
|
|
1252
|
+
at: number;
|
|
1253
|
+
} | {
|
|
1254
|
+
delayMs: number;
|
|
1255
|
+
};
|
|
1256
|
+
/** No sound. The banner still appears. */
|
|
1257
|
+
silent?: boolean;
|
|
1258
|
+
}): Promise<{
|
|
1259
|
+
id: string;
|
|
1260
|
+
status: 'posted' | 'scheduled' | 'suppressed';
|
|
1261
|
+
}>;
|
|
1262
|
+
/**
|
|
1263
|
+
* Remove what is pending or delivered under `id`, and retire its tap
|
|
1264
|
+
* target. Unknown ids are fine.
|
|
1265
|
+
*/
|
|
1266
|
+
cancel(id: string): Promise<void>;
|
|
1267
|
+
/** Remove every local notification this API posted or scheduled. */
|
|
1268
|
+
cancelAll(): Promise<void>;
|
|
1269
|
+
};
|
|
1009
1270
|
/** File system APIs. */
|
|
1010
1271
|
export type OpenFileOptions = {
|
|
1011
1272
|
/** Local file path or runtime-managed temp path. */
|
|
@@ -1058,7 +1319,7 @@ export type OpenPageShared = {
|
|
|
1058
1319
|
size?: OverlaySurfaceSize;
|
|
1059
1320
|
interaction?: SurfaceInteraction;
|
|
1060
1321
|
query?: PageQuery;
|
|
1061
|
-
/** Caller-owned identity, for `lx.surface.
|
|
1322
|
+
/** Caller-owned identity, for `lx.surface.getByKey(key)` later. */
|
|
1062
1323
|
key?: string;
|
|
1063
1324
|
};
|
|
1064
1325
|
export type OpenUrlOptions = {
|
|
@@ -1070,7 +1331,7 @@ export type OpenUrlOptions = {
|
|
|
1070
1331
|
/** Preferred docking side when the realized placement is an aside. */
|
|
1071
1332
|
edge?: SurfaceEdge;
|
|
1072
1333
|
size?: OverlaySurfaceSize;
|
|
1073
|
-
/** Stable identity for `lx.surface.
|
|
1334
|
+
/** Stable identity for `lx.surface.getByKey(key)`. */
|
|
1074
1335
|
key?: string;
|
|
1075
1336
|
};
|
|
1076
1337
|
export type OverlaySurfaceSize = {
|
|
@@ -1109,6 +1370,11 @@ export type PageTargetOptions = {
|
|
|
1109
1370
|
page: ConfiguredPageName;
|
|
1110
1371
|
query?: PageQuery;
|
|
1111
1372
|
};
|
|
1373
|
+
export type PickFileOptions = Omit<ChooseFileOptions, 'multiple'>;
|
|
1374
|
+
export type PickFileResult = {
|
|
1375
|
+
status: 'ok';
|
|
1376
|
+
uri: string;
|
|
1377
|
+
} | CanceledResult;
|
|
1112
1378
|
export type PreviewMediaAdvance = 'manual' | 'next' | 'loop';
|
|
1113
1379
|
/** One change-stream event / the `current` snapshot. */
|
|
1114
1380
|
export type PreviewMediaChange = {
|
|
@@ -1117,28 +1383,17 @@ export type PreviewMediaChange = {
|
|
|
1117
1383
|
};
|
|
1118
1384
|
export type PreviewMediaCloseReason = 'manual' | 'completed' | 'interrupted' | 'error';
|
|
1119
1385
|
/**
|
|
1120
|
-
*
|
|
1121
|
-
*
|
|
1122
|
-
*
|
|
1123
|
-
* been composited to screen. Use this to time the hide of an overlay
|
|
1124
|
-
* surface above the preview so the swap is seamless. Never rejects;
|
|
1125
|
-
* resolves with no value when the first frame is up. Safe to ignore.
|
|
1126
|
-
* - `current` is a live `{ index, source }` snapshot of the item on screen,
|
|
1127
|
-
* updated as the user swipes and as the session auto-advances.
|
|
1128
|
-
* - `onChange(listener)` fires for every item change. Returns an
|
|
1129
|
-
* unsubscribe function.
|
|
1130
|
-
* - `completed` resolves `{ reason, index, source }` when the preview
|
|
1131
|
-
* session ends (manual / auto / interrupted / error), or rejects on abort.
|
|
1132
|
-
* If the call was aborted before any frame was presented, `presented` still
|
|
1133
|
-
* resolves (with no value) once the abort takes effect — it never rejects,
|
|
1134
|
-
* to keep fire-and-forget usage safe.
|
|
1135
|
-
* @example
|
|
1136
|
-
* const preview = lx.previewMedia({ sources, startIndex: 2 });
|
|
1137
|
-
* preview.onChange(({ source }) => markAsViewed(source.path));
|
|
1138
|
-
* const { reason, source } = await preview.completed;
|
|
1386
|
+
* A media session. `presented` distinguishes a rendered first frame from
|
|
1387
|
+
* an early close, cancellation, or failure. `completed` reports closure;
|
|
1388
|
+
* native playback errors may report reason `error`, while request failures reject.
|
|
1139
1389
|
*/
|
|
1140
1390
|
export type PreviewMediaHandle = {
|
|
1141
|
-
readonly presented: Promise<
|
|
1391
|
+
readonly presented: Promise<{
|
|
1392
|
+
status: 'presented';
|
|
1393
|
+
} | {
|
|
1394
|
+
status: 'notPresented';
|
|
1395
|
+
reason: 'canceled' | 'failed' | 'closed';
|
|
1396
|
+
}>;
|
|
1142
1397
|
readonly current: PreviewMediaChange;
|
|
1143
1398
|
onChange(listener: (change: PreviewMediaChange) => void): () => void;
|
|
1144
1399
|
readonly completed: Promise<PreviewMediaResult>;
|
|
@@ -1270,14 +1525,40 @@ export type ScanCodeOptions = {
|
|
|
1270
1525
|
scanType?: ('barCode' | 'qrCode' | 'datamatrix' | 'pdf417')[];
|
|
1271
1526
|
};
|
|
1272
1527
|
/**
|
|
1273
|
-
* Result of `lx.scanCode`. Branch on `
|
|
1528
|
+
* Result of `lx.scanCode`. Branch on `status` before reading the scan
|
|
1274
1529
|
* payload.
|
|
1275
1530
|
*/
|
|
1276
1531
|
export type ScanCodeResult = {
|
|
1277
|
-
|
|
1532
|
+
status: 'ok';
|
|
1278
1533
|
scanResult: string;
|
|
1279
1534
|
scanType: string;
|
|
1280
1535
|
} | CanceledResult;
|
|
1536
|
+
/**
|
|
1537
|
+
* Where `lx.host.setBadge` paints.
|
|
1538
|
+
* `auto` (the default) marks every product-owned surface this platform
|
|
1539
|
+
* has: the dock and the menu-bar item on macOS, the taskbar and the
|
|
1540
|
+
* notification-area item on Windows, the home-screen icon on iOS and
|
|
1541
|
+
* HarmonyOS. Name one only when that surface is the point.
|
|
1542
|
+
* Asynchronous because it reports what actually happened: a platform that
|
|
1543
|
+
* answers through its own callback has to be waited for to be believed.
|
|
1544
|
+
* A surface with nothing to paint on is reported, not raised: a macOS
|
|
1545
|
+
* status item exists from the moment a tray is declared but stays hidden
|
|
1546
|
+
* until `lx.tray.show()`, and a badge on a hidden item is not a badge
|
|
1547
|
+
* anyone can see. That resolves `false` whether you named the surface or
|
|
1548
|
+
* took `auto`; only a malfunction rejects.
|
|
1549
|
+
* Apple ties the badge to notification permission. On macOS the label
|
|
1550
|
+
* always reaches the system, but the Dock declines to draw it for an app
|
|
1551
|
+
* that is registered with Notification Center and not allowed — so a host
|
|
1552
|
+
* that declares `capabilities.notifications` and never got a yes resolves
|
|
1553
|
+
* `false` here. A host that never asks is unaffected.
|
|
1554
|
+
* On iOS the home-screen badge is drawn by the notification system, so
|
|
1555
|
+
* it needs notification permission and only accepts a number — that is
|
|
1556
|
+
* the OS's rule, not an API coupling. Android has no cross-vendor
|
|
1557
|
+
* launcher badge at all, so `setBadge` returns `false` there.
|
|
1558
|
+
*/
|
|
1559
|
+
export type SetBadgeOptions = {
|
|
1560
|
+
surface?: 'auto' | 'appIcon' | 'tray';
|
|
1561
|
+
};
|
|
1281
1562
|
/** Share images, PDFs, or other files. */
|
|
1282
1563
|
export type ShareFilesOptions = ShareTitleOptions & {
|
|
1283
1564
|
/**
|
|
@@ -1401,7 +1682,7 @@ export type ShellOpenAppOptions = {
|
|
|
1401
1682
|
*/
|
|
1402
1683
|
channel?: LxAppEnvVersion;
|
|
1403
1684
|
targetVersion?: string;
|
|
1404
|
-
/** Stable identity for `lx.surface.
|
|
1685
|
+
/** Stable identity for `lx.surface.getByKey(key)`. */
|
|
1405
1686
|
key?: string;
|
|
1406
1687
|
};
|
|
1407
1688
|
/**
|
|
@@ -1413,7 +1694,7 @@ export type ShellOpenAppOptions = {
|
|
|
1413
1694
|
*/
|
|
1414
1695
|
export type ShellOpenDeclaredOptions = {
|
|
1415
1696
|
/**
|
|
1416
|
-
* Caller-owned identity, for `lx.surface.
|
|
1697
|
+
* Caller-owned identity, for `lx.surface.getByKey(key)` later — the same key
|
|
1417
1698
|
* every opener takes. It carries one extra power here: a declaration can
|
|
1418
1699
|
* be opened more than once, and the key is which instance you mean, so a
|
|
1419
1700
|
* new key creates one. 1 to 128 UTF-8 bytes. Declarations without
|
|
@@ -1508,7 +1789,10 @@ export type ShellSurfacePatch = {
|
|
|
1508
1789
|
edge?: SurfaceEdge;
|
|
1509
1790
|
};
|
|
1510
1791
|
export type ShowActionSheetOptions = {
|
|
1511
|
-
|
|
1792
|
+
items: readonly {
|
|
1793
|
+
id: string;
|
|
1794
|
+
label: string;
|
|
1795
|
+
}[];
|
|
1512
1796
|
itemColor?: string;
|
|
1513
1797
|
};
|
|
1514
1798
|
export type ShowModalOptions = {
|
|
@@ -1525,7 +1809,7 @@ export type ShowToastOptions = {
|
|
|
1525
1809
|
title: string;
|
|
1526
1810
|
icon?: 'success' | 'error' | 'loading' | 'none';
|
|
1527
1811
|
image?: string;
|
|
1528
|
-
|
|
1812
|
+
durationMs?: number;
|
|
1529
1813
|
mask?: boolean;
|
|
1530
1814
|
position?: 'top' | 'center' | 'bottom';
|
|
1531
1815
|
};
|
|
@@ -1542,7 +1826,7 @@ export type Storage = {
|
|
|
1542
1826
|
* shape, exactly like a `JSON.parse` boundary; a missing key resolves
|
|
1543
1827
|
* `undefined`, which a stored `null` never does.
|
|
1544
1828
|
*/
|
|
1545
|
-
get<T = unknown>(key: string): Promise<T | undefined>;
|
|
1829
|
+
get<T = unknown>(key: string, decode?: (value: unknown) => T): Promise<T | undefined>;
|
|
1546
1830
|
set(key: string, value: unknown): Promise<void>;
|
|
1547
1831
|
/**
|
|
1548
1832
|
* Resolves whether an exact key exists, without reading its value. Prefer
|
|
@@ -1565,7 +1849,7 @@ export type StorageInfo = {
|
|
|
1565
1849
|
export type StreamSourceOptions = {
|
|
1566
1850
|
provider: string;
|
|
1567
1851
|
isLive: boolean;
|
|
1568
|
-
|
|
1852
|
+
durationSeconds?: number;
|
|
1569
1853
|
params?: Record<string, unknown>;
|
|
1570
1854
|
};
|
|
1571
1855
|
/**
|
|
@@ -1584,19 +1868,16 @@ export type SurfaceApi = {
|
|
|
1584
1868
|
*/
|
|
1585
1869
|
openDeclared(id: string): Promise<DeclaredSurface>;
|
|
1586
1870
|
/**
|
|
1587
|
-
*
|
|
1588
|
-
*
|
|
1589
|
-
* to reuse or close them. A surface opened without a `key` is not
|
|
1590
|
-
* addressable — nothing else refers to a runtime-assigned id, so nothing
|
|
1591
|
-
* registers it. A key you chose wins over an id it happens to spell.
|
|
1871
|
+
* Find a live surface by the explicit key passed when opening it.
|
|
1872
|
+
* Runtime-assigned ids are not lookup keys.
|
|
1592
1873
|
*/
|
|
1593
|
-
|
|
1874
|
+
getByKey(key: string): AnySurface | undefined;
|
|
1594
1875
|
/**
|
|
1595
1876
|
* Observe this presentation's viewport. Invoked immediately with the
|
|
1596
1877
|
* current context, then again whenever it changes. Returns an unsubscribe
|
|
1597
1878
|
* function.
|
|
1598
1879
|
*/
|
|
1599
|
-
|
|
1880
|
+
watchContext(handler: (context: SurfaceContext) => void): () => void;
|
|
1600
1881
|
};
|
|
1601
1882
|
/** What every surface handle carries, whatever opened it. */
|
|
1602
1883
|
export type SurfaceBase = {
|
|
@@ -1641,12 +1922,15 @@ export type SurfaceClosedEvent = {
|
|
|
1641
1922
|
reason: SurfaceCloseReason;
|
|
1642
1923
|
};
|
|
1643
1924
|
/**
|
|
1644
|
-
* The current surface viewport context, delivered to `lx.surface.
|
|
1645
|
-
* so an lxapp can
|
|
1925
|
+
* The current surface viewport context, delivered to `lx.surface.watchContext()`
|
|
1926
|
+
* so an lxapp can choose a compact or workspace View. Column count and
|
|
1927
|
+
* spacing inside `regular` use CSS or the raw `width` / `height`.
|
|
1646
1928
|
*/
|
|
1647
1929
|
export type SurfaceContext = {
|
|
1648
|
-
/**
|
|
1649
|
-
|
|
1930
|
+
/** Whether the host layout currently offers a docked aside. */
|
|
1931
|
+
aside: boolean;
|
|
1932
|
+
/** compact (<600) / regular (≥600). Shell medium/expanded are not distinct here. */
|
|
1933
|
+
sizeClass: 'compact' | 'regular';
|
|
1650
1934
|
/** Actual surface viewport width in logical pixels. */
|
|
1651
1935
|
width: number;
|
|
1652
1936
|
/** Actual surface viewport height in logical pixels. */
|
|
@@ -1777,31 +2061,29 @@ export type TabBarItemPatch = {
|
|
|
1777
2061
|
badge?: string | null;
|
|
1778
2062
|
redDot?: boolean;
|
|
1779
2063
|
};
|
|
2064
|
+
/**
|
|
2065
|
+
* Patch for `lx.tabBar.update()`. Items, badges, red dots, and
|
|
2066
|
+
* visibility only — a `style` field is rejected. Colors stay in
|
|
2067
|
+
* static `lxapp.json` `tabBar.style`. `backgroundColor` is
|
|
2068
|
+
* mobile-only; the desktop sidebar follows the host
|
|
2069
|
+
* `lingxia.yaml` theme.
|
|
2070
|
+
*/
|
|
1780
2071
|
export type TabBarPatch = {
|
|
1781
2072
|
visibility?: TabBarVisibilityPreference;
|
|
1782
|
-
style?: TabBarStylePatch | null;
|
|
1783
2073
|
items?: readonly TabBarItemPatch[];
|
|
1784
2074
|
};
|
|
1785
|
-
export type TabBarStylePatch = {
|
|
1786
|
-
foregroundColor?: string | null;
|
|
1787
|
-
selectedForegroundColor?: string | null;
|
|
1788
|
-
};
|
|
1789
2075
|
export type TabBarVisibilityPreference = 'auto' | 'visible' | 'hidden';
|
|
1790
2076
|
/** External content in the in-app browser. */
|
|
1791
|
-
export type TabSurface = SurfaceBase & {
|
|
2077
|
+
export type TabSurface = (SurfaceBase & {
|
|
1792
2078
|
readonly kind: 'tab';
|
|
1793
2079
|
readonly realized: 'tab' | 'aside';
|
|
1794
|
-
|
|
1795
|
-
* `tab` when this handle owns exactly the tab it opened, and `close()` /
|
|
1796
|
-
* `activate()` act on it. `group` when the browser chrome owns the tab
|
|
1797
|
-
* strip: the content is open, but control belongs to that chrome, so both
|
|
1798
|
-
* methods reject with `unsupported_placement`. Branch on this rather than
|
|
1799
|
-
* on the old platform-dependent `null`.
|
|
1800
|
-
*/
|
|
1801
|
-
readonly scope: 'tab' | 'group';
|
|
1802
|
-
/** Bring this tab to the front of its browser. `scope: 'group'` rejects. */
|
|
2080
|
+
readonly scope: 'tab';
|
|
1803
2081
|
activate(): Promise<void>;
|
|
1804
|
-
}
|
|
2082
|
+
}) | (Omit<SurfaceBase, 'close' | 'onClose'> & {
|
|
2083
|
+
readonly kind: 'tab';
|
|
2084
|
+
readonly realized: 'tab' | 'aside';
|
|
2085
|
+
readonly scope: 'group';
|
|
2086
|
+
});
|
|
1805
2087
|
export type TerminalApi = {
|
|
1806
2088
|
/** Saved terminal settings, revision-checked on write. */
|
|
1807
2089
|
readonly settings: TerminalSettingsApi;
|
|
@@ -1922,15 +2204,20 @@ export type TerminalThemeSettings = {
|
|
|
1922
2204
|
light: string;
|
|
1923
2205
|
dark: string;
|
|
1924
2206
|
};
|
|
2207
|
+
export type ToastHandle = {
|
|
2208
|
+
/** Dismiss this toast only; harmless after a newer toast replaces it. */
|
|
2209
|
+
dismiss(): Promise<void>;
|
|
2210
|
+
};
|
|
1925
2211
|
export type TrayApi = globalThis.TrayApi;
|
|
1926
2212
|
/**
|
|
1927
2213
|
* Runtime control of the menu-bar (macOS) / system-tray (Windows) status item.
|
|
1928
2214
|
* The tray is declared in `lingxia.yaml` (`tray:`); these update its dynamic
|
|
1929
2215
|
* content at runtime.
|
|
1930
2216
|
* **Desktop only.** Mobile platforms have no tray, so every method here is a
|
|
1931
|
-
* no-op there (it never throws) — safe to call from portable code.
|
|
1932
|
-
*
|
|
1933
|
-
*
|
|
2217
|
+
* no-op there (it never throws) — safe to call from portable code.
|
|
2218
|
+
* The tray belongs to the product, not to the lxapp that happens to be
|
|
2219
|
+
* running, so these are Control-app only: a guest lxapp calling one receives
|
|
2220
|
+
* a permission error.
|
|
1934
2221
|
*/
|
|
1935
2222
|
export type TrayMenuItem = {
|
|
1936
2223
|
label: string;
|
|
@@ -1948,7 +2235,10 @@ export type UpdateFailedInfo = UpdateReadyInfo & {
|
|
|
1948
2235
|
/**
|
|
1949
2236
|
* Callback-based updates for this lxapp's bundle. Available to every
|
|
1950
2237
|
* lxapp. To update the native host app, the Control app uses the
|
|
1951
|
-
* task-based `lx.
|
|
2238
|
+
* task-based `lx.host.checkUpdate()` API instead.
|
|
2239
|
+
* Listeners are a set: later subscriptions do not replace earlier ones.
|
|
2240
|
+
* The last pending ready/failed event is replayed to each new
|
|
2241
|
+
* subscriber until a newer event replaces it.
|
|
1952
2242
|
*/
|
|
1953
2243
|
export type UpdateManager = {
|
|
1954
2244
|
applyUpdate(): void;
|
|
@@ -1959,13 +2249,9 @@ export type UpdateManager = {
|
|
|
1959
2249
|
};
|
|
1960
2250
|
export type UpdateReadyInfo = {
|
|
1961
2251
|
version?: string;
|
|
1962
|
-
isForceUpdate?: boolean;
|
|
1963
2252
|
channel?: "release" | "draft" | string;
|
|
1964
2253
|
};
|
|
1965
|
-
export type UploadIteratorResult =
|
|
1966
|
-
done: boolean;
|
|
1967
|
-
value?: UploadProgressEvent;
|
|
1968
|
-
};
|
|
2254
|
+
export type UploadIteratorResult = IteratorResult<UploadProgressEvent, void>;
|
|
1969
2255
|
/**
|
|
1970
2256
|
* Upload options. The file streams from disk, so the size ceiling is
|
|
1971
2257
|
* the remote's, not memory.
|
|
@@ -1974,12 +2260,12 @@ export type UploadIteratorResult = {
|
|
|
1974
2260
|
* - `multipart` (default) wraps the file in a `multipart/form-data`
|
|
1975
2261
|
* envelope beside the `formData` text fields — what an ordinary form
|
|
1976
2262
|
* endpoint parses. `name`, `fileName`, and `formData` describe that
|
|
1977
|
-
* envelope.
|
|
2263
|
+
* envelope. `formData`, when present, must contain at least one field.
|
|
1978
2264
|
* - `raw` sends the file bytes as the entire body. Presigned
|
|
1979
2265
|
* object-storage URLs (S3, OSS, Azure Blob) need this: a multipart
|
|
1980
2266
|
* envelope would be stored verbatim as the object's contents,
|
|
1981
|
-
* boundary lines and all. `name` and `
|
|
1982
|
-
* rather than silently dropped
|
|
2267
|
+
* boundary lines and all. `name`, `formData`, and `fileName` are
|
|
2268
|
+
* then rejected rather than silently dropped.
|
|
1983
2269
|
* @example
|
|
1984
2270
|
* ```ts
|
|
1985
2271
|
* // A presigned URL is signed for one method and one Content-Type,
|
|
@@ -1991,8 +2277,8 @@ export type UploadIteratorResult = {
|
|
|
1991
2277
|
* bodyMode: 'raw',
|
|
1992
2278
|
* mimeType: 'video/mp4',
|
|
1993
2279
|
* });
|
|
1994
|
-
* for await (const event of task) render(event.progress);
|
|
1995
|
-
* const { statusCode } = await task;
|
|
2280
|
+
* for await (const event of task.progress) render(event.progress);
|
|
2281
|
+
* const { statusCode } = await task.result;
|
|
1996
2282
|
* ```
|
|
1997
2283
|
*/
|
|
1998
2284
|
export type UploadOptions = {
|
|
@@ -2005,14 +2291,6 @@ export type UploadOptions = {
|
|
|
2005
2291
|
* A presigned URL is signed for exactly one method, usually `PUT`.
|
|
2006
2292
|
*/
|
|
2007
2293
|
method?: 'POST' | 'PUT' | 'PATCH';
|
|
2008
|
-
/**
|
|
2009
|
-
* How the file bytes are framed. Default: `multipart`.
|
|
2010
|
-
* `raw` sends them as the whole body under a `Content-Length` taken from
|
|
2011
|
-
* the file itself, which is what presigned endpoints require.
|
|
2012
|
-
*/
|
|
2013
|
-
bodyMode?: 'multipart' | 'raw';
|
|
2014
|
-
/** Name of the multipart part carrying the file. Default: `file`. Multipart only. */
|
|
2015
|
-
name?: string;
|
|
2016
2294
|
/**
|
|
2017
2295
|
* Optional request headers.
|
|
2018
2296
|
* Restricted headers such as `Referer` are ignored by the runtime.
|
|
@@ -2021,12 +2299,8 @@ export type UploadOptions = {
|
|
|
2021
2299
|
* carries the part boundary.
|
|
2022
2300
|
*/
|
|
2023
2301
|
headers?: Record<string, string>;
|
|
2024
|
-
/** Text fields sent alongside the file in the envelope. Multipart only. */
|
|
2025
|
-
formData?: Record<string, string>;
|
|
2026
2302
|
/** Request timeout in milliseconds. */
|
|
2027
|
-
|
|
2028
|
-
/** Filename announced for the file part. Defaults to the file's own name. Multipart only. */
|
|
2029
|
-
fileName?: string;
|
|
2303
|
+
timeoutMs?: number;
|
|
2030
2304
|
/**
|
|
2031
2305
|
* File MIME type. Types the file part under `multipart`; becomes the
|
|
2032
2306
|
* request `Content-Type` under `raw`, where it defaults to
|
|
@@ -2035,10 +2309,26 @@ export type UploadOptions = {
|
|
|
2035
2309
|
mimeType?: string;
|
|
2036
2310
|
/** Optional abort signal. */
|
|
2037
2311
|
signal?: AbortSignal;
|
|
2038
|
-
}
|
|
2312
|
+
} & ({
|
|
2313
|
+
/**
|
|
2314
|
+
* How the file bytes are framed. Default: `multipart`.
|
|
2315
|
+
*/
|
|
2316
|
+
bodyMode?: 'multipart';
|
|
2317
|
+
/** Name of the multipart part carrying the file. Default: `file`. */
|
|
2318
|
+
name?: string;
|
|
2319
|
+
/** Text fields sent alongside the file. Must be non-empty when set. */
|
|
2320
|
+
formData?: Record<string, string>;
|
|
2321
|
+
/** Filename announced for the file part. Defaults to the file's own name. */
|
|
2322
|
+
fileName?: string;
|
|
2323
|
+
} | {
|
|
2324
|
+
/** Send the file bytes as the whole body. Multipart fields are rejected. */
|
|
2325
|
+
bodyMode: 'raw';
|
|
2326
|
+
name?: never;
|
|
2327
|
+
formData?: never;
|
|
2328
|
+
fileName?: never;
|
|
2329
|
+
});
|
|
2039
2330
|
export type UploadProgressEvent = {
|
|
2040
|
-
|
|
2041
|
-
kind: 'progress' | 'canceled' | 'completed';
|
|
2331
|
+
kind: 'progress' | 'canceled';
|
|
2042
2332
|
/** Bytes handed to the socket so far, envelope included under `multipart`. */
|
|
2043
2333
|
uploadedBytes?: number;
|
|
2044
2334
|
/**
|
|
@@ -2049,8 +2339,12 @@ export type UploadProgressEvent = {
|
|
|
2049
2339
|
totalBytes?: number;
|
|
2050
2340
|
/** `uploadedBytes / totalBytes`, absent while the total is unknown or zero. */
|
|
2051
2341
|
progress?: number;
|
|
2052
|
-
|
|
2053
|
-
|
|
2342
|
+
} | {
|
|
2343
|
+
kind: 'completed';
|
|
2344
|
+
uploadedBytes?: number;
|
|
2345
|
+
totalBytes?: number;
|
|
2346
|
+
progress?: number;
|
|
2347
|
+
result: UploadResult;
|
|
2054
2348
|
};
|
|
2055
2349
|
export type UploadResult = {
|
|
2056
2350
|
/** HTTP status code returned by the server. */
|
|
@@ -2058,21 +2352,13 @@ export type UploadResult = {
|
|
|
2058
2352
|
/** Response body decoded as UTF-8 text. */
|
|
2059
2353
|
data: string;
|
|
2060
2354
|
};
|
|
2061
|
-
export type UploadTask =
|
|
2062
|
-
next(): Promise<UploadIteratorResult>;
|
|
2063
|
-
/** Stops iteration only. Does not cancel the underlying upload task. */
|
|
2064
|
-
return(): Promise<UploadIteratorResult>;
|
|
2065
|
-
catch<TResult = never>(onrejected?: ((reason: unknown) => TResult | PromiseLike<TResult>) | null): Promise<UploadResult | TResult>;
|
|
2066
|
-
finally(onfinally?: (() => void) | null): Promise<UploadResult>;
|
|
2067
|
-
cancel(): Promise<void>;
|
|
2068
|
-
wait(): Promise<UploadResult>;
|
|
2069
|
-
};
|
|
2355
|
+
export type UploadTask = CancelableTask<UploadResult, UploadProgressEvent>;
|
|
2070
2356
|
export type VideoCompressQuality = 'low' | 'medium' | 'high';
|
|
2071
2357
|
export type VideoContext = {
|
|
2072
2358
|
play(): void;
|
|
2073
2359
|
pause(): void;
|
|
2074
2360
|
stop(): void;
|
|
2075
|
-
seek(
|
|
2361
|
+
seek(positionSeconds: number): void;
|
|
2076
2362
|
requestFullScreen(): void;
|
|
2077
2363
|
exitFullScreen(): void;
|
|
2078
2364
|
setStreamSource(options: StreamSourceOptions): void;
|
|
@@ -2184,7 +2470,7 @@ export type WindowsTerminalInlineImageStatus = {
|
|
|
2184
2470
|
/**
|
|
2185
2471
|
* Host app identity. Everything here is fixed for the life of the process;
|
|
2186
2472
|
* the language the app renders in is not, and lives on
|
|
2187
|
-
* `lx.
|
|
2473
|
+
* `lx.host.displayLanguage`.
|
|
2188
2474
|
*/
|
|
2189
2475
|
export interface AppBaseInfo {
|
|
2190
2476
|
/**
|
|
@@ -2194,7 +2480,7 @@ export interface AppBaseInfo {
|
|
|
2194
2480
|
os: HostOs;
|
|
2195
2481
|
productName: string;
|
|
2196
2482
|
version: string;
|
|
2197
|
-
|
|
2483
|
+
sdkVersion: string;
|
|
2198
2484
|
}
|
|
2199
2485
|
/** Device info APIs. */
|
|
2200
2486
|
export interface DeviceInfo {
|
|
@@ -2256,9 +2542,9 @@ export interface SystemSettingInfo {
|
|
|
2256
2542
|
/** Wi-Fi APIs. */
|
|
2257
2543
|
export interface WifiInfo {
|
|
2258
2544
|
/** Service Set Identifier (network name) */
|
|
2259
|
-
|
|
2545
|
+
ssid: string;
|
|
2260
2546
|
/** Basic Service Set Identifier (MAC address) */
|
|
2261
|
-
|
|
2547
|
+
bssid?: string;
|
|
2262
2548
|
/** Whether the network is secure (requires password) */
|
|
2263
2549
|
secure: boolean;
|
|
2264
2550
|
/** Signal strength (0-100, higher is better) */
|
|
@@ -2266,15 +2552,13 @@ export interface WifiInfo {
|
|
|
2266
2552
|
/** Center frequency in MHz (if available) */
|
|
2267
2553
|
frequency?: number;
|
|
2268
2554
|
}
|
|
2269
|
-
export
|
|
2270
|
-
private constructor();
|
|
2555
|
+
export interface DirEntry {
|
|
2271
2556
|
readonly name: string;
|
|
2272
2557
|
readonly isFile: boolean;
|
|
2273
2558
|
readonly isDirectory: boolean;
|
|
2274
2559
|
readonly isSymlink: boolean;
|
|
2275
2560
|
}
|
|
2276
|
-
export
|
|
2277
|
-
private constructor();
|
|
2561
|
+
export interface LxFile {
|
|
2278
2562
|
/** The path supplied to `lx.fs.file`. */
|
|
2279
2563
|
readonly path: string;
|
|
2280
2564
|
/** Read the complete file as strict UTF-8 text. */
|
|
@@ -2297,6 +2581,56 @@ export declare class LxFile {
|
|
|
2297
2581
|
/** Read metadata for this managed path. */
|
|
2298
2582
|
stat(): Promise<FileStats>;
|
|
2299
2583
|
}
|
|
2584
|
+
declare global {
|
|
2585
|
+
interface ClipboardApi {
|
|
2586
|
+
/**
|
|
2587
|
+
* Replace the clipboard with Unicode text.
|
|
2588
|
+
* Empty string is a valid payload (it is not `clear()`). The runtime does not
|
|
2589
|
+
* present a toast — call `lx.showToast` if the product wants one. Rejects
|
|
2590
|
+
* `E_INVALID_ARG` above 1 MiB.
|
|
2591
|
+
*/
|
|
2592
|
+
writeText(text: string): Promise<void>;
|
|
2593
|
+
/**
|
|
2594
|
+
* Read Unicode text.
|
|
2595
|
+
* Resolves `{ status: 'canceled' }` only when the user dismisses the OS paste
|
|
2596
|
+
* prompt (iOS 16+, macOS 15.4+). No text representation (empty clipboard, or
|
|
2597
|
+
* image-only) resolves `{ status: 'empty' }`. A copied empty
|
|
2598
|
+
* string resolves `{ status: 'ok', text: '' }`.
|
|
2599
|
+
* Rejects `E_PERMISSION_DENIED` when the host denies clipboard access
|
|
2600
|
+
* outright: a macOS "never allow" setting, or HarmonyOS without
|
|
2601
|
+
* `ohos.permission.READ_PASTEBOARD`. Android denies a read while the app has
|
|
2602
|
+
* no window focus and reports it as an empty clipboard, so read in response
|
|
2603
|
+
* to a user action.
|
|
2604
|
+
*/
|
|
2605
|
+
readText(): Promise<ClipboardTextResult>;
|
|
2606
|
+
/**
|
|
2607
|
+
* Replace the clipboard with a typed item.
|
|
2608
|
+
* Rejects `E_INVALID_ARG` for text above 1 MiB or an image file that does not
|
|
2609
|
+
* decode.
|
|
2610
|
+
*/
|
|
2611
|
+
write(item: ClipboardWriteItem): Promise<void>;
|
|
2612
|
+
/**
|
|
2613
|
+
* Read the clipboard.
|
|
2614
|
+
* Omit `type` to receive every representation this host can surface.
|
|
2615
|
+
* Pass `type` to request one; if that representation is absent, the
|
|
2616
|
+
* completed result is `{ status: 'empty' }` rather than a mismatch error.
|
|
2617
|
+
* Images arrive as a temporary PNG under `lx://temp`. Dismissal and
|
|
2618
|
+
* permission behave as in `readText`.
|
|
2619
|
+
*/
|
|
2620
|
+
read(options?: ClipboardReadOptions): Promise<ClipboardReadResult>;
|
|
2621
|
+
/** Remove every representation. */
|
|
2622
|
+
clear(): Promise<void>;
|
|
2623
|
+
/**
|
|
2624
|
+
* Which representations are present, without reading payloads. An empty
|
|
2625
|
+
* array is an empty clipboard; representations this runtime cannot
|
|
2626
|
+
* round-trip (HTML, files) are omitted.
|
|
2627
|
+
* Never shows the OS paste prompt and needs no permission on any host, so it
|
|
2628
|
+
* is the way to decide whether to offer "Paste". The answer is a hint —
|
|
2629
|
+
* content may change before you read it.
|
|
2630
|
+
*/
|
|
2631
|
+
types(): Promise<ClipboardType[]>;
|
|
2632
|
+
}
|
|
2633
|
+
}
|
|
2300
2634
|
declare global {
|
|
2301
2635
|
interface FileSystemApi {
|
|
2302
2636
|
/**
|
|
@@ -2304,44 +2638,53 @@ declare global {
|
|
|
2304
2638
|
* Relative paths resolve under `lx.env.USER_DATA_PATH`. Creating a reference
|
|
2305
2639
|
* does not require the path to exist.
|
|
2306
2640
|
*/
|
|
2307
|
-
file(path:
|
|
2641
|
+
file(path: ManagedPath): LxFile;
|
|
2308
2642
|
/** Test whether a managed path currently exists. */
|
|
2309
|
-
exists(path:
|
|
2643
|
+
exists(path: ManagedPath): Promise<boolean>;
|
|
2310
2644
|
/** Read metadata for a managed path. */
|
|
2311
|
-
stat(path:
|
|
2645
|
+
stat(path: ManagedPath): Promise<FileStats>;
|
|
2312
2646
|
/** The direct children of a managed directory. */
|
|
2313
|
-
readDir(path:
|
|
2647
|
+
readDir(path: ManagedPath): Promise<DirEntry[]>;
|
|
2314
2648
|
/** Create a managed directory. */
|
|
2315
|
-
mkdir(path:
|
|
2649
|
+
mkdir(path: ManagedPath, options?: FsMkdirOptions): Promise<void>;
|
|
2316
2650
|
/** Write UTF-8 text or bytes to a managed file. */
|
|
2317
|
-
write(path:
|
|
2651
|
+
write(path: ManagedPath, data: string, options?: FsWriteOptions): Promise<void>;
|
|
2318
2652
|
/** Copy a managed file. */
|
|
2319
|
-
copy(source:
|
|
2653
|
+
copy(source: ManagedPath, destination: ManagedPath, options?: FsCopyOptions): Promise<void>;
|
|
2320
2654
|
/** Rename or move a managed file or directory. */
|
|
2321
|
-
rename(source:
|
|
2655
|
+
rename(source: ManagedPath, destination: ManagedPath, options?: FsRenameOptions): Promise<void>;
|
|
2322
2656
|
/** Remove a managed file or directory. */
|
|
2323
|
-
remove(path:
|
|
2657
|
+
remove(path: ManagedPath, options?: FsRemoveOptions): Promise<void>;
|
|
2324
2658
|
}
|
|
2325
2659
|
}
|
|
2326
2660
|
declare global {
|
|
2327
2661
|
interface HostAppApi {
|
|
2328
2662
|
/**
|
|
2329
|
-
* `lx.
|
|
2663
|
+
* `lx.host.screenshot(options?)` — capture the host app's window as a PNG.
|
|
2330
2664
|
* App-level semantics, one level above any page/WebView capture: the image
|
|
2331
2665
|
* is what the user sees of the whole app — host-drawn navigation chrome,
|
|
2332
2666
|
* native overlays, and every composited WebView, not just this lxapp's web
|
|
2333
2667
|
* content. Because that view can include other lxapps' UI, the API is
|
|
2334
|
-
* restricted to the Control app, like the other host-level APIs on `lx.
|
|
2668
|
+
* restricted to the Control app, like the other host-level APIs on `lx.host`.
|
|
2335
2669
|
*/
|
|
2336
2670
|
screenshot(options?: AppScreenshotOptions): Promise<AppScreenshotResult>;
|
|
2337
2671
|
/**
|
|
2338
|
-
*
|
|
2339
|
-
* This host-level capability is restricted to the Control app.
|
|
2340
|
-
*
|
|
2341
|
-
* `
|
|
2342
|
-
*
|
|
2672
|
+
* Query whether the host app has an update.
|
|
2673
|
+
* This host-level capability is restricted to the Control app. A successful
|
|
2674
|
+
* check does **not** take over the built-in auto-flow — that is
|
|
2675
|
+
* `claimCustomUpdate()` or `update.apply()`. Permission denial or a failed
|
|
2676
|
+
* check claims nothing. Incompatible updates are hidden as
|
|
2677
|
+
* `hasUpdate: false`. Store-channel hosts still surface a newer feed version;
|
|
2678
|
+
* `apply()` opens the store listing instead of downloading.
|
|
2343
2679
|
*/
|
|
2344
2680
|
checkUpdate(): Promise<HostAppUpdateCheckResult>;
|
|
2681
|
+
/**
|
|
2682
|
+
* Claim the process-lifetime custom host-update flow.
|
|
2683
|
+
* Irreversible: the built-in auto-flow will not prompt or download again,
|
|
2684
|
+
* including after the calling page unloads. Does not cancel an already-started
|
|
2685
|
+
* update task. Later failed checks do not undo a claim already made.
|
|
2686
|
+
*/
|
|
2687
|
+
claimCustomUpdate(): void;
|
|
2345
2688
|
readonly env: HostAppEnv;
|
|
2346
2689
|
/**
|
|
2347
2690
|
* Read the host app's identity: OS, product name, product version, and SDK
|
|
@@ -2357,29 +2700,31 @@ declare global {
|
|
|
2357
2700
|
*/
|
|
2358
2701
|
exit(): void;
|
|
2359
2702
|
/**
|
|
2360
|
-
*
|
|
2361
|
-
*
|
|
2362
|
-
*
|
|
2363
|
-
*
|
|
2364
|
-
*
|
|
2703
|
+
* Mark the product in system chrome, for example with an unread count.
|
|
2704
|
+
* One call, because "where the count goes" is the platform's answer, not the
|
|
2705
|
+
* caller's: `auto` paints every product-owned surface this platform has — the
|
|
2706
|
+
* dock and the menu-bar item on macOS, the taskbar and the notification-area
|
|
2707
|
+
* item on Windows, the home-screen icon on iOS and HarmonyOS. Name a
|
|
2708
|
+
* `surface` only when one of them is the point.
|
|
2709
|
+
* It is the product's chrome, not the calling lxapp's, so it is Control app
|
|
2710
|
+
* only. Null or an empty string clears it.
|
|
2711
|
+
* Returns whether anything was actually painted. A platform with no such
|
|
2712
|
+
* chrome is a no-op that returns `false` rather than an error — portable code
|
|
2713
|
+
* can call this unconditionally.
|
|
2365
2714
|
*/
|
|
2366
|
-
setBadge(value: string | number | null):
|
|
2715
|
+
setBadge(value: string | number | null, options?: SetBadgeOptions): Promise<boolean>;
|
|
2367
2716
|
}
|
|
2368
2717
|
}
|
|
2369
2718
|
declare global {
|
|
2370
2719
|
interface Lx {
|
|
2371
|
-
readonly
|
|
2720
|
+
readonly host: HostAppApi;
|
|
2372
2721
|
/**
|
|
2373
|
-
*
|
|
2374
|
-
*
|
|
2375
|
-
*
|
|
2376
|
-
* deciding what to render, not a replacement for handling a rejection.
|
|
2377
|
-
* `{ capability: 'surface', value: 'aside' }` in particular changes when a
|
|
2378
|
-
* desktop window crosses the compact breakpoint; pair it with
|
|
2379
|
-
* `lx.surface.onContext` instead of polling. The answer is per runtime context:
|
|
2380
|
-
* a context that does not expose an API reports false for it.
|
|
2722
|
+
* Frozen feature support, not permission or current layout. Unknown strings
|
|
2723
|
+
* return false; non-strings throw TypeError. Required features also need an
|
|
2724
|
+
* appropriate lxapp.json minRuntime.
|
|
2381
2725
|
*/
|
|
2382
|
-
supports(
|
|
2726
|
+
supports(feature: LxFeature): boolean;
|
|
2727
|
+
readonly clipboard: ClipboardApi;
|
|
2383
2728
|
/** Vibrate briefly, where the device has a vibrator. */
|
|
2384
2729
|
vibrateShort(): boolean;
|
|
2385
2730
|
/** Vibrate for a longer pulse, where the device has a vibrator. */
|
|
@@ -2426,8 +2771,8 @@ declare global {
|
|
|
2426
2771
|
* `method: 'PUT'` with `bodyMode: 'raw'` to send the file bytes as the whole
|
|
2427
2772
|
* body instead, which is what presigned object-storage URLs expect.
|
|
2428
2773
|
* Returns the task handle synchronously, before the transfer starts, so
|
|
2429
|
-
* progress and cancellation can be wired up without racing it:
|
|
2430
|
-
*
|
|
2774
|
+
* progress and cancellation can be wired up without racing it: `result` settles
|
|
2775
|
+
* once, `progress` streams to one consumer, and `cancel()` aborts.
|
|
2431
2776
|
*/
|
|
2432
2777
|
uploadFile(options: UploadOptions): UploadTask;
|
|
2433
2778
|
/**
|
|
@@ -2436,17 +2781,20 @@ declare global {
|
|
|
2436
2781
|
* `mode: "auto"`.
|
|
2437
2782
|
*/
|
|
2438
2783
|
openFile(options: OpenFileOptions): Promise<void>;
|
|
2784
|
+
/** Pick one file. A successful selection returns one opaque URI. */
|
|
2785
|
+
pickFile(options?: PickFileOptions): Promise<PickFileResult>;
|
|
2786
|
+
/** Pick one or more files. Dismissal is a normal outcome. */
|
|
2787
|
+
pickFiles(options?: PickFileOptions): Promise<ChooseFileResult>;
|
|
2439
2788
|
/**
|
|
2440
|
-
*
|
|
2441
|
-
*
|
|
2442
|
-
* completed selection resolves `{ canceled: false, paths }` with at least one
|
|
2789
|
+
* Resolves `{ status: 'canceled' }` only when the user dismisses the picker. A
|
|
2790
|
+
* completed selection resolves `{ status: 'ok', paths }` with at least one
|
|
2443
2791
|
* path. Rejects when the picker fails or returns an invalid payload.
|
|
2444
2792
|
*/
|
|
2445
|
-
chooseFile(options
|
|
2793
|
+
chooseFile(options: never): Promise<never>;
|
|
2446
2794
|
/**
|
|
2447
2795
|
* Opens a directory picker.
|
|
2448
|
-
* Resolves `{
|
|
2449
|
-
* completed selection resolves `{
|
|
2796
|
+
* Resolves `{ status: 'canceled' }` only when the user dismisses the picker. A
|
|
2797
|
+
* completed selection resolves `{ status: 'ok', path }`. Rejects when the
|
|
2450
2798
|
* picker fails or returns an invalid payload.
|
|
2451
2799
|
*/
|
|
2452
2800
|
chooseDirectory(options?: ChooseDirectoryOptions): Promise<ChooseDirectoryResult>;
|
|
@@ -2465,8 +2813,8 @@ declare global {
|
|
|
2465
2813
|
compressImage(options: CompressImageOptions): Promise<CompressImageResult>;
|
|
2466
2814
|
/**
|
|
2467
2815
|
* Opens the media picker or camera.
|
|
2468
|
-
* Resolves `{
|
|
2469
|
-
* completed selection resolves `{
|
|
2816
|
+
* Resolves `{ status: 'canceled' }` only when the user dismisses the picker. A
|
|
2817
|
+
* completed selection resolves `{ status: 'ok', entries }` with at least one
|
|
2470
2818
|
* entry. Rejects when capture or selection fails, or the host returns an invalid
|
|
2471
2819
|
* payload.
|
|
2472
2820
|
*/
|
|
@@ -2474,10 +2822,8 @@ declare global {
|
|
|
2474
2822
|
/**
|
|
2475
2823
|
* Synchronously returns a JS handle so listeners can be attached before the
|
|
2476
2824
|
* first event fires:
|
|
2477
|
-
* - `presented`:
|
|
2478
|
-
*
|
|
2479
|
-
* once `completed` settles, so consumers can safely ignore it (it never
|
|
2480
|
-
* rejects).
|
|
2825
|
+
* - `presented`: resolves `{ status: 'presented' }` only after the first
|
|
2826
|
+
* frame; otherwise `{ status: 'notPresented', reason }`. Never rejects.
|
|
2481
2827
|
* - `current`: `{ index, source }` snapshot of the item on screen, updated
|
|
2482
2828
|
* live as the user swipes / the session auto-advances.
|
|
2483
2829
|
* - `onChange(listener)`: fires `{ index, source }` for every item change
|
|
@@ -2495,8 +2841,8 @@ declare global {
|
|
|
2495
2841
|
saveVideoToPhotosAlbum(options: SaveMediaOptions): Promise<void>;
|
|
2496
2842
|
/**
|
|
2497
2843
|
* Opens the scanner.
|
|
2498
|
-
* Resolves `{
|
|
2499
|
-
* completed scan resolves `{
|
|
2844
|
+
* Resolves `{ status: 'canceled' }` only when the user dismisses the scanner. A
|
|
2845
|
+
* completed scan resolves `{ status: 'ok', scanResult, scanType }`. Rejects
|
|
2500
2846
|
* when scanning fails or the host returns an invalid payload.
|
|
2501
2847
|
*/
|
|
2502
2848
|
scanCode(options?: ScanCodeOptions): Promise<ScanCodeResult>;
|
|
@@ -2546,15 +2892,18 @@ declare global {
|
|
|
2546
2892
|
getSystemSetting(): SystemSettingInfo;
|
|
2547
2893
|
/**
|
|
2548
2894
|
* Shows a list of actions.
|
|
2549
|
-
* Resolves `{
|
|
2550
|
-
* points into `options.itemList`. Resolves `{ canceled: true }` only when the
|
|
2895
|
+
* Resolves `{ status: 'ok', id }` when the user selects an item; `id` identifies the selected item. Resolves `{ status: 'canceled' }` only when the
|
|
2551
2896
|
* user dismisses the sheet. Rejects when presentation fails or the host returns
|
|
2552
2897
|
* an invalid selection.
|
|
2553
2898
|
*/
|
|
2554
2899
|
showActionSheet(options: ShowActionSheetOptions): Promise<ActionSheetResult>;
|
|
2900
|
+
/** Acknowledgement-only dialog. Resolves when the user dismisses it. */
|
|
2901
|
+
alert(options: AlertOptions): Promise<void>;
|
|
2902
|
+
/** Ask a yes/no question. Dismissal resolves false; presentation failure rejects. */
|
|
2903
|
+
confirm(options: ConfirmOptions): Promise<boolean>;
|
|
2555
2904
|
/**
|
|
2556
2905
|
* Shows a confirmation modal.
|
|
2557
|
-
* Resolves `{
|
|
2906
|
+
* Resolves `{ status: 'ok' }` when the user confirms and `{ status: 'canceled' }`
|
|
2558
2907
|
* only when the user dismisses or cancels the modal. Rejects when presentation
|
|
2559
2908
|
* fails or the host returns an invalid payload.
|
|
2560
2909
|
*/
|
|
@@ -2611,15 +2960,19 @@ declare global {
|
|
|
2611
2960
|
reLaunch(options: ReLaunchOptions): Promise<void>;
|
|
2612
2961
|
readonly shell: ShellApi;
|
|
2613
2962
|
readonly tabBar: TabBarApi;
|
|
2614
|
-
/**
|
|
2615
|
-
|
|
2616
|
-
|
|
2963
|
+
/**
|
|
2964
|
+
* Presents a toast and resolves a handle once the host accepted it. The handle
|
|
2965
|
+
* dismisses only this toast, never a newer one — including a newer one posted
|
|
2966
|
+
* by another lxapp onto a host's shared overlay.
|
|
2967
|
+
*/
|
|
2968
|
+
showToast(options: ShowToastOptions): Promise<ToastHandle>;
|
|
2969
|
+
/** Hides whichever toast is showing. */
|
|
2617
2970
|
hideToast(): Promise<void>;
|
|
2618
2971
|
readonly tray: TrayApi;
|
|
2619
2972
|
/**
|
|
2620
2973
|
* Return the callback-based update manager for this lxapp's bundle. This is
|
|
2621
2974
|
* available to every lxapp and is distinct from the Control-app-only
|
|
2622
|
-
* `lx.
|
|
2975
|
+
* `lx.host.checkUpdate()`, which updates the native host app.
|
|
2623
2976
|
*/
|
|
2624
2977
|
getUpdateManager(): UpdateManager;
|
|
2625
2978
|
}
|
|
@@ -2708,34 +3061,35 @@ declare global {
|
|
|
2708
3061
|
* `lingxia.yaml`, opened with the declaration's own presentation.
|
|
2709
3062
|
*/
|
|
2710
3063
|
openDeclared(id: string): Promise<DeclaredSurface>;
|
|
3064
|
+
/** Find a live surface by its explicit caller-owned key. Runtime ids are not keys. */
|
|
3065
|
+
getByKey(key: string): AnySurface | undefined;
|
|
2711
3066
|
/**
|
|
2712
|
-
* `lx.surface.
|
|
2713
|
-
* **with a `key`**, so no caller has to cache one in order to reuse or close
|
|
2714
|
-
* it. An unkeyed surface is not addressable: nothing registers it, because
|
|
2715
|
-
* holding one for the session costs its closures and its message port and
|
|
2716
|
-
* nobody can look up a uuid they never chose.
|
|
2717
|
-
* A `key` you chose wins over a runtime-assigned `id`, so a key that happens
|
|
2718
|
-
* to spell another surface's id still finds yours.
|
|
2719
|
-
*/
|
|
2720
|
-
get(keyOrId: string): AnySurface | undefined;
|
|
2721
|
-
/**
|
|
2722
|
-
* `lx.surface.onContext(handler)` — register a JS callback (scoped to this
|
|
3067
|
+
* `lx.surface.watchContext(handler)` — register a JS callback (scoped to this
|
|
2723
3068
|
* lxapp's JS context), invoke it immediately, then again whenever that
|
|
2724
|
-
* presentation's
|
|
3069
|
+
* presentation's viewport or host docking availability changes. Returns an unsubscribe fn.
|
|
2725
3070
|
*/
|
|
2726
|
-
|
|
3071
|
+
watchContext(handler: (context: SurfaceContext) => void): () => void;
|
|
2727
3072
|
}
|
|
2728
3073
|
}
|
|
2729
3074
|
declare global {
|
|
2730
3075
|
interface TabBarApi {
|
|
2731
|
-
/**
|
|
3076
|
+
/**
|
|
3077
|
+
* Patch this lxapp's tab bar; unset fields stay as they are.
|
|
3078
|
+
* Items, badges, red dots, and visibility only. A `style` field is
|
|
3079
|
+
* rejected — colors stay in static `lxapp.json` `tabBar.style`.
|
|
3080
|
+
* `tabBar.style.backgroundColor` is mobile-only: it paints the bar on
|
|
3081
|
+
* iOS / Android / Harmony. On macOS / Windows the sidebar follows the
|
|
3082
|
+
* host `lingxia.yaml` theme (`windowBackgroundColor`) instead, so a
|
|
3083
|
+
* `#FFFFFF` fill cannot paint a card on the sidebar. Other style keys
|
|
3084
|
+
* (`foregroundColor`, `selectedForegroundColor`, `dividerColor`) may
|
|
3085
|
+
* tint items while the desktop host is light; a dark host uses the
|
|
3086
|
+
* shell theme for every key.
|
|
3087
|
+
*/
|
|
2732
3088
|
update(patch: TabBarPatch): Promise<void>;
|
|
2733
3089
|
}
|
|
2734
3090
|
}
|
|
2735
3091
|
declare global {
|
|
2736
3092
|
interface TrayApi {
|
|
2737
|
-
/** lx.tray.setBadge(value) — the menu-bar / system-tray badge. Null/empty clears it. */
|
|
2738
|
-
setBadge(value: string | number | null): void;
|
|
2739
3093
|
/** lx.tray.setIcon(icon) — replace the tray icon (a resource path). */
|
|
2740
3094
|
setIcon(icon: string): void;
|
|
2741
3095
|
/** lx.tray.setTitle(text) — text shown beside the icon (macOS). Empty clears it. */
|
|
@@ -2760,4 +3114,6 @@ declare global {
|
|
|
2760
3114
|
}
|
|
2761
3115
|
}
|
|
2762
3116
|
export {};
|
|
3117
|
+
/** Feature contracts generated from the runtime registry. */
|
|
3118
|
+
export type LxFeature = 'app.appUse' | 'app.autostart' | 'app.banner' | 'app.browser' | 'app.browserUse' | 'app.computerUse' | 'app.mediaCapture' | 'app.notification' | 'app.proxy' | 'app.selfUpdate' | 'process' | 'surface.tab' | 'surface.window' | 'surface.window.fullChrome' | 'terminal';
|
|
2763
3119
|
//# sourceMappingURL=logic.d.ts.map
|