@lingxia/types 0.17.0 → 0.19.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 +1039 -128
- package/dist/automation/index.d.ts.map +1 -1
- package/dist/automation/index.js +61 -3
- package/dist/automation/index.js.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/automation/index.js +60 -4
- package/dist/esm/automation/index.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/index.js.map +1 -1
- package/dist/esm/mocks.js +2 -0
- package/dist/esm/mocks.js.map +1 -0
- package/dist/esm/page.js +2 -0
- package/dist/esm/page.js.map +1 -0
- package/dist/esm/testing/public-api.js +133 -48
- 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 +772 -381
- package/dist/generated/logic.d.ts.map +1 -1
- package/dist/index.d.ts +17 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mocks.d.ts +58 -0
- package/dist/mocks.d.ts.map +1 -0
- package/dist/mocks.js +3 -0
- package/dist/mocks.js.map +1 -0
- package/dist/page.d.ts +26 -0
- package/dist/page.d.ts.map +1 -0
- package/dist/page.js +3 -0
- package/dist/page.js.map +1 -0
- package/dist/process.d.ts +15 -4
- package/dist/process.d.ts.map +1 -1
- package/dist/testing/public-api.d.ts +127 -51
- package/dist/testing/public-api.d.ts.map +1 -1
- package/dist/testing/public-api.js +133 -48
- package/dist/testing/public-api.js.map +1 -1
- package/package.json +8 -5
- package/src/automation/index.ts +1066 -128
- 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 +830 -405
- package/src/index.ts +19 -10
- package/src/mocks.ts +62 -0
- package/src/page.ts +26 -0
- package/src/process.ts +14 -4
- package/src/testing/public-api.ts +155 -49
- package/dist/automation-test-globals.d.ts +0 -14
package/src/generated/logic.ts
CHANGED
|
@@ -5,9 +5,21 @@
|
|
|
5
5
|
// by external Rong modules in this generated prelude.
|
|
6
6
|
declare const appDownloadPathBrand: unique symbol;
|
|
7
7
|
declare const systemDownloadsPathBrand: unique symbol;
|
|
8
|
+
/** Managed paths and relative userdata paths; system Downloads references are excluded. */
|
|
9
|
+
export type ManagedPath = string & { readonly [systemDownloadsPathBrand]?: never };
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
/** JSON-shaped state; undefined removes a property in setData. */
|
|
12
|
+
export type PageDataValue<T> = unknown extends T ? T : T extends string | number | boolean | null | undefined ? T
|
|
13
|
+
: T extends (...args: never[]) => unknown ? never
|
|
14
|
+
: T extends object ? { [K in keyof T]: PageDataValue<T[K]> } : never;
|
|
15
|
+
|
|
16
|
+
export type NoReservedPageMembers<T> = {
|
|
17
|
+
[K in keyof T]: K extends 'data' ? T[K]
|
|
18
|
+
: K extends keyof PageInstance | '_setData' | '_cancelPendingSetData' ? never : T[K];
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export interface PageConfig<TData extends object = Record<string, unknown>> {
|
|
22
|
+
data?: TData & PageDataValue<TData>;
|
|
11
23
|
onLoad?: (options?: PageLoadOptions) => void | Promise<void>;
|
|
12
24
|
onShow?: () => void | Promise<void>;
|
|
13
25
|
onReady?: () => void | Promise<void>;
|
|
@@ -46,31 +58,98 @@ export type NoLifecycleTypos<TCustom, TNames extends string> = {
|
|
|
46
58
|
|
|
47
59
|
/**
|
|
48
60
|
* A `setData` key that addresses inside `data` — `'a.b'` or `'rows[0].name'`.
|
|
49
|
-
*
|
|
50
|
-
*
|
|
61
|
+
* Kept for documentation; nested writes go through `setPath` (checked) or
|
|
62
|
+
* `setDataPath` (unchecked). `setData` no longer accepts these keys.
|
|
51
63
|
*/
|
|
52
64
|
export type PageDataPath = `${string}.${string}` | `${string}[${number}]${string}`;
|
|
53
65
|
|
|
54
66
|
/**
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*/
|
|
59
|
-
export type LazyInitField<T> =
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*/
|
|
69
|
-
export type
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
67
|
+
* @deprecated Page `data` is no longer widened for `null` / `[]` initializers.
|
|
68
|
+
* Annotate the field (`null as Profile | null`) when a later fill should be
|
|
69
|
+
* checked.
|
|
70
|
+
*/
|
|
71
|
+
export type LazyInitField<T> = T;
|
|
72
|
+
|
|
73
|
+
type PageReadonlyDepth = [never, 0, 1, 2, 3, 4, 5, 6];
|
|
74
|
+
|
|
75
|
+
type PagePrimitive = string | number | boolean | bigint | symbol | null | undefined;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Deep readonly view of page `data`. Static only — the runtime object is not
|
|
79
|
+
* frozen.
|
|
80
|
+
*/
|
|
81
|
+
export type DeepReadonly<T, D extends number = 6> = [D] extends [never]
|
|
82
|
+
? T
|
|
83
|
+
: T extends PagePrimitive
|
|
84
|
+
? T
|
|
85
|
+
: T extends Function
|
|
86
|
+
? T
|
|
87
|
+
: T extends readonly unknown[]
|
|
88
|
+
? { readonly [K in keyof T]: DeepReadonly<T[K], PageReadonlyDepth[D]> }
|
|
89
|
+
: T extends object
|
|
90
|
+
? { readonly [K in keyof T]: DeepReadonly<T[K], PageReadonlyDepth[D]> }
|
|
91
|
+
: T;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Tuple path into `data`, depth-capped so large page states stay completable.
|
|
95
|
+
*/
|
|
96
|
+
export type DataPath<T, D extends number = 5> = [D] extends [never]
|
|
97
|
+
? never
|
|
98
|
+
: T extends readonly (infer U)[]
|
|
99
|
+
? [number] | [number, ...DataPath<U, PageReadonlyDepth[D]>]
|
|
100
|
+
: T extends object
|
|
101
|
+
? {
|
|
102
|
+
[K in keyof T & (string | number)]:
|
|
103
|
+
| [K]
|
|
104
|
+
| (DataPath<T[K], PageReadonlyDepth[D]> extends infer Rest
|
|
105
|
+
? Rest extends readonly PropertyKey[]
|
|
106
|
+
? [K, ...Rest]
|
|
107
|
+
: never
|
|
108
|
+
: never);
|
|
109
|
+
}[keyof T & (string | number)]
|
|
110
|
+
: never;
|
|
111
|
+
|
|
112
|
+
export type DataPathValue<T, P extends readonly PropertyKey[]> = T extends null | undefined
|
|
113
|
+
? never
|
|
114
|
+
: T extends unknown
|
|
115
|
+
? P extends readonly [
|
|
116
|
+
infer K,
|
|
117
|
+
...infer Rest,
|
|
118
|
+
]
|
|
119
|
+
? Rest extends readonly PropertyKey[]
|
|
120
|
+
? Rest['length'] extends 0
|
|
121
|
+
? K extends keyof T
|
|
122
|
+
? T[K]
|
|
123
|
+
: K extends number
|
|
124
|
+
? T extends readonly (infer U)[]
|
|
125
|
+
? U
|
|
126
|
+
: never
|
|
127
|
+
: never
|
|
128
|
+
: K extends keyof T
|
|
129
|
+
? DataPathValue<T[K], Rest>
|
|
130
|
+
: K extends number
|
|
131
|
+
? T extends readonly (infer U)[]
|
|
132
|
+
? DataPathValue<U, Rest>
|
|
133
|
+
: never
|
|
134
|
+
: never
|
|
135
|
+
: never
|
|
136
|
+
: never
|
|
137
|
+
: never;
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Top-level keys are checked against `data`. Nested writes use `setPath` or
|
|
141
|
+
* the unchecked `setDataPath`.
|
|
142
|
+
*/
|
|
143
|
+
export type SetDataPatch<TData> = { [K in keyof TData]?: TData[K] };
|
|
144
|
+
|
|
145
|
+
type SetDataValue<TData, K> = K extends PageDataPath
|
|
146
|
+
? { "LingXia type error": "use setPath or setDataPath for nested writes" }
|
|
147
|
+
: K extends keyof TData
|
|
148
|
+
? TData[K] | DeepReadonly<TData[K]>
|
|
149
|
+
: { "LingXia type error": "unknown data key" };
|
|
150
|
+
|
|
151
|
+
export interface PageInstance<TData extends object = Record<string, unknown>> {
|
|
152
|
+
readonly data: { readonly [K in keyof TData]: DeepReadonly<TData[K]> };
|
|
74
153
|
route: string;
|
|
75
154
|
/**
|
|
76
155
|
* Available when this page was opened as a surface via
|
|
@@ -81,7 +160,25 @@ export interface PageInstance<TData extends Record<string, unknown> = Record<str
|
|
|
81
160
|
* Available when this page was opened by `lx.navigateTo(...)`.
|
|
82
161
|
*/
|
|
83
162
|
opener?: PageMessagePort;
|
|
84
|
-
setData
|
|
163
|
+
setData<TPatch extends Record<string, unknown>>(
|
|
164
|
+
data: TPatch & { [K in keyof TPatch]: SetDataValue<TData, K> },
|
|
165
|
+
): void;
|
|
166
|
+
setPath<const P extends DataPath<TData>>(
|
|
167
|
+
path: P,
|
|
168
|
+
value: DataPathValue<TData, P>,
|
|
169
|
+
): void;
|
|
170
|
+
/** Nested write by a runtime-resolved string path. JSON shape is checked; the path/value relationship is not. */
|
|
171
|
+
setDataPath(path: string, value: JsonValue | undefined): void;
|
|
172
|
+
/** Drain pending state writes; an attached View acknowledges application, not paint. Rejects on unload. */
|
|
173
|
+
flush(): Promise<void>;
|
|
174
|
+
/**
|
|
175
|
+
* Aborted as the page unloads, before `onUnload` runs, however the page
|
|
176
|
+
* leaves. Pass it to work the page starts — `fetch(url, { signal:
|
|
177
|
+
* this.signal })` — so that work stops with the page, rejecting with an
|
|
178
|
+
* `AbortError`, instead of resolving into a page that is gone. When the
|
|
179
|
+
* whole lxapp shuts down, its Logic ends with it and the signal does not fire.
|
|
180
|
+
*/
|
|
181
|
+
readonly signal: AbortSignal;
|
|
85
182
|
}
|
|
86
183
|
|
|
87
184
|
/**
|
|
@@ -98,6 +195,12 @@ export interface StreamHandle<T = unknown> {
|
|
|
98
195
|
end(result?: unknown): void;
|
|
99
196
|
/** End the stream with an error. */
|
|
100
197
|
error(code: string, message?: string): void;
|
|
198
|
+
/**
|
|
199
|
+
* Called once if View cancels before `end`/`error`. Returns unsubscribe.
|
|
200
|
+
* The generator form still observes cancel in `finally`; use this for the
|
|
201
|
+
* callback-based handle.
|
|
202
|
+
*/
|
|
203
|
+
onCancel(handler: () => void): () => void;
|
|
101
204
|
}
|
|
102
205
|
|
|
103
206
|
/**
|
|
@@ -111,9 +214,9 @@ export interface ChannelHandle<TSend = unknown, TReceive = unknown> {
|
|
|
111
214
|
send(payload: TSend): void;
|
|
112
215
|
/** Close the channel from Logic side. */
|
|
113
216
|
close(code?: string, reason?: string): void;
|
|
114
|
-
/** Register a listener for incoming events. */
|
|
115
|
-
on(event: 'data', handler: (payload: TReceive) => void): void;
|
|
116
|
-
on(event: 'close', handler: (info: { code: string; reason: string }) => void): void;
|
|
217
|
+
/** Register a listener for incoming events. Returns unsubscribe. */
|
|
218
|
+
on(event: 'data', handler: (payload: TReceive) => void): () => void;
|
|
219
|
+
on(event: 'close', handler: (info: { code: string; reason: string }) => void): () => void;
|
|
117
220
|
}
|
|
118
221
|
|
|
119
222
|
/**
|
|
@@ -132,36 +235,54 @@ export type DownloadOptions<TDestination extends DownloadDestination = DownloadD
|
|
|
132
235
|
export type DownloadResultForDestination<TDestination extends DownloadDestination> =
|
|
133
236
|
TDestination extends 'downloads' ? DownloadsDownloadResult : AppDownloadResult;
|
|
134
237
|
|
|
135
|
-
export
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
238
|
+
export type DownloadProgressEvent<TResult extends DownloadResult = DownloadResult> =
|
|
239
|
+
| {
|
|
240
|
+
kind: 'progress' | 'paused' | 'resumed';
|
|
241
|
+
downloadedBytes?: number;
|
|
242
|
+
totalBytes?: number;
|
|
243
|
+
/** Present only when the total size is known. */
|
|
244
|
+
progress?: number;
|
|
245
|
+
}
|
|
246
|
+
| {
|
|
247
|
+
kind: 'canceled';
|
|
248
|
+
downloadedBytes?: number;
|
|
249
|
+
totalBytes?: number;
|
|
250
|
+
progress?: number;
|
|
251
|
+
}
|
|
252
|
+
| {
|
|
253
|
+
kind: 'completed';
|
|
254
|
+
downloadedBytes?: number;
|
|
255
|
+
totalBytes?: number;
|
|
256
|
+
progress?: number;
|
|
257
|
+
result: TResult;
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
export type DownloadIteratorResult<TResult extends DownloadResult = DownloadResult> =
|
|
261
|
+
IteratorResult<DownloadProgressEvent<TResult>, void>;
|
|
262
|
+
|
|
263
|
+
export type AppTempDownloadResult = Extract<AppDownloadResult, { storage: 'temp' }>;
|
|
264
|
+
export type AppPersistedDownloadResult = Extract<AppDownloadResult, { storage: 'userdata' }>;
|
|
265
|
+
|
|
266
|
+
export type ChooseFileSingleResult = {
|
|
267
|
+
status: 'ok';
|
|
268
|
+
paths: [string];
|
|
269
|
+
} | CanceledResult;
|
|
270
|
+
|
|
271
|
+
/** A running operation. Progress has one consumer; stopping observation does not cancel it. */
|
|
272
|
+
export interface Task<TResult, TProgress> {
|
|
273
|
+
readonly result: Promise<TResult>;
|
|
274
|
+
readonly progress: AsyncIterable<TProgress>;
|
|
142
275
|
}
|
|
143
276
|
|
|
144
|
-
export interface
|
|
145
|
-
|
|
146
|
-
|
|
277
|
+
export interface CancelableTask<TResult, TProgress> extends Task<TResult, TProgress> {
|
|
278
|
+
/** Requests cancellation. Await result to observe the terminal outcome. */
|
|
279
|
+
cancel(): Promise<void>;
|
|
147
280
|
}
|
|
148
281
|
|
|
149
|
-
export interface DownloadTask<
|
|
150
|
-
extends
|
|
151
|
-
AsyncIterable<DownloadProgressEvent<TDownloadResult>> {
|
|
152
|
-
next(): Promise<DownloadIteratorResult<TDownloadResult>>;
|
|
153
|
-
/** Stops iteration only. Does not cancel the underlying download task. */
|
|
154
|
-
return(): Promise<DownloadIteratorResult<TDownloadResult>>;
|
|
155
|
-
catch<TRejected = never>(
|
|
156
|
-
onrejected?: ((reason: unknown) => TRejected | PromiseLike<TRejected>) | null,
|
|
157
|
-
): Promise<TDownloadResult | TRejected>;
|
|
158
|
-
finally(onfinally?: (() => void) | null): Promise<TDownloadResult>;
|
|
282
|
+
export interface DownloadTask<TResult extends DownloadResult = DownloadResult>
|
|
283
|
+
extends CancelableTask<TResult, DownloadProgressEvent<TResult>> {
|
|
159
284
|
pause(): Promise<void>;
|
|
160
285
|
resume(): Promise<void>;
|
|
161
|
-
cancel(): Promise<void>;
|
|
162
|
-
/** Alias for cancel(), matching browser/mini-program abort naming. */
|
|
163
|
-
abort(): Promise<void>;
|
|
164
|
-
wait(): Promise<TDownloadResult>;
|
|
165
286
|
}
|
|
166
287
|
|
|
167
288
|
declare global {
|
|
@@ -188,11 +309,24 @@ declare global {
|
|
|
188
309
|
|
|
189
310
|
/**
|
|
190
311
|
* Launch-at-startup control. Absent where the host cannot register a
|
|
191
|
-
* startup item; its presence and `lx.supports(
|
|
192
|
-
* agree, so `lx.
|
|
312
|
+
* startup item; its presence and `lx.supports('app.autostart')` always
|
|
313
|
+
* agree, so `lx.host.autostart?.…` and the query are interchangeable.
|
|
193
314
|
*/
|
|
194
315
|
autostart?: AutostartApi;
|
|
195
316
|
|
|
317
|
+
/**
|
|
318
|
+
* Local notifications. Absent where the host cannot post them; its presence
|
|
319
|
+
* and `lx.supports('app.notification')` always agree.
|
|
320
|
+
*/
|
|
321
|
+
notification?: NotificationApi;
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Product-drawn desktop banner (top-right). Absent off desktop and in
|
|
325
|
+
* guest lxapps; its presence and `lx.supports('app.banner')`
|
|
326
|
+
* always agree.
|
|
327
|
+
*/
|
|
328
|
+
banner?: BannerApi;
|
|
329
|
+
|
|
196
330
|
/** The language this lxapp renders in. Every lxapp follows it. */
|
|
197
331
|
readonly displayLanguage: DisplayLanguageApi;
|
|
198
332
|
|
|
@@ -201,19 +335,25 @@ declare global {
|
|
|
201
335
|
|
|
202
336
|
/**
|
|
203
337
|
* Product-wide settings, and their single writer. Present only in the
|
|
204
|
-
* Control app the host sealed at build time
|
|
205
|
-
* `lx.
|
|
206
|
-
* `lx.app.control?.…` and the query are interchangeable.
|
|
338
|
+
* Control app the host sealed at build time. Use
|
|
339
|
+
* `lx.host.control !== undefined` to inspect that identity.
|
|
207
340
|
*/
|
|
208
341
|
readonly control?: ControlApi;
|
|
209
342
|
|
|
210
343
|
/**
|
|
211
344
|
* Product-wide cache reporting and clearing for a settings screen.
|
|
212
|
-
* Present only in the Control app;
|
|
213
|
-
* `lx.
|
|
214
|
-
* `lx.app.cache?.…` and the query are interchangeable.
|
|
345
|
+
* Present only in the Control app; presence agrees with
|
|
346
|
+
* `lx.host.control !== undefined`.
|
|
215
347
|
*/
|
|
216
348
|
cache?: AppCacheApi;
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Take over host updates for the rest of this process. Irreversible: the
|
|
352
|
+
* built-in auto-flow will not prompt or download again, including after
|
|
353
|
+
* the calling page unloads. Does not cancel an already-started update task.
|
|
354
|
+
* `update.apply()` claims as well. `checkUpdate()` does not.
|
|
355
|
+
*/
|
|
356
|
+
claimCustomUpdate(): void;
|
|
217
357
|
}
|
|
218
358
|
|
|
219
359
|
/** Runtime environment constants backed by abstract `lx://` paths. */
|
|
@@ -223,18 +363,36 @@ declare global {
|
|
|
223
363
|
/**
|
|
224
364
|
* Terminal product settings. Present only in the host-bundled Terminal
|
|
225
365
|
* Settings lxapp when the host declares `capabilities.terminal`; its
|
|
226
|
-
* presence and `lx.supports(
|
|
366
|
+
* presence and `lx.supports('terminal')` always agree.
|
|
227
367
|
*/
|
|
228
368
|
readonly terminal?: TerminalApi;
|
|
229
369
|
|
|
230
370
|
/** Download to the downloads directory. */
|
|
231
371
|
downloadFile(options: DownloadsDownloadOptions): DownloadTask<DownloadsDownloadResult>;
|
|
372
|
+
/** Download to a durable app-owned path. */
|
|
373
|
+
downloadFile(
|
|
374
|
+
options: AppDownloadOptions & { filePath: string },
|
|
375
|
+
): DownloadTask<AppPersistedDownloadResult>;
|
|
376
|
+
/** Download to a temporary app-owned path. */
|
|
377
|
+
downloadFile(
|
|
378
|
+
options: AppDownloadOptions & { filePath?: undefined },
|
|
379
|
+
): DownloadTask<AppTempDownloadResult>;
|
|
232
380
|
/** Download to the lxapp-managed app directory. */
|
|
233
381
|
downloadFile(options: AppDownloadOptions): DownloadTask<AppDownloadResult>;
|
|
234
382
|
/** Download with a destination-correlated result type. */
|
|
235
383
|
downloadFile<TDestination extends DownloadDestination = "app">(
|
|
236
384
|
options: DownloadOptions<TDestination>,
|
|
237
385
|
): DownloadTask<DownloadResultForDestination<TDestination>>;
|
|
386
|
+
/** Single-file picker: a completed selection is exactly one path. */
|
|
387
|
+
chooseFile(options: ChooseFileOptions & { multiple: false }): Promise<ChooseFileSingleResult>;
|
|
388
|
+
chooseFile(options: ChooseFileOptions & { multiple: true }): Promise<ChooseFileResult>;
|
|
389
|
+
/**
|
|
390
|
+
* Opens a file picker.
|
|
391
|
+
* Resolves `{ status: 'canceled' }` only when the user dismisses the picker. A
|
|
392
|
+
* completed selection resolves `{ status: 'ok', paths }` with at least one
|
|
393
|
+
* path. Rejects when the picker fails or returns an invalid payload.
|
|
394
|
+
*/
|
|
395
|
+
chooseFile(options?: ChooseFileOptions): Promise<ChooseFileResult>;
|
|
238
396
|
|
|
239
397
|
/**
|
|
240
398
|
* Open this lxapp's store with every key's shape pinned on the handle.
|
|
@@ -255,7 +413,7 @@ export type StorageSchema = object;
|
|
|
255
413
|
|
|
256
414
|
type StorageKey<S extends object> = Extract<keyof S, string>;
|
|
257
415
|
type StorageEntry<S extends object> = {
|
|
258
|
-
[K in StorageKey<S>]: [key: K, value: S[K]];
|
|
416
|
+
[K in StorageKey<S>]: [key: K, value: S[K] | DeepReadonly<S[K]>];
|
|
259
417
|
}[StorageKey<S>];
|
|
260
418
|
|
|
261
419
|
/**
|
|
@@ -269,7 +427,7 @@ type StorageEntry<S extends object> = {
|
|
|
269
427
|
* unchecked assertion this type exists to remove from `get<T>()`.
|
|
270
428
|
*/
|
|
271
429
|
export type TypedStorage<S extends object> = {
|
|
272
|
-
get<K extends StorageKey<S>>(key: K): Promise<S[K] | undefined>;
|
|
430
|
+
get<K extends StorageKey<S>>(key: K, decode?: (value: unknown) => S[K]): Promise<S[K] | undefined>;
|
|
273
431
|
set(...entry: StorageEntry<S>): Promise<void>;
|
|
274
432
|
has(key: StorageKey<S>): Promise<boolean>;
|
|
275
433
|
delete(key: StorageKey<S>): Promise<void>;
|
|
@@ -279,15 +437,18 @@ export type TypedStorage<S extends object> = {
|
|
|
279
437
|
};
|
|
280
438
|
|
|
281
439
|
/**
|
|
282
|
-
* Result of `lx.showActionSheet`. Branch on `
|
|
283
|
-
* the selected item
|
|
440
|
+
* Result of `lx.showActionSheet`. Branch on `status` before reading
|
|
441
|
+
* the selected item id.
|
|
284
442
|
*/
|
|
285
443
|
export type ActionSheetResult = {
|
|
286
|
-
|
|
287
|
-
/**
|
|
288
|
-
|
|
444
|
+
status: 'ok';
|
|
445
|
+
/** Stable id of the selected action. */
|
|
446
|
+
id: string;
|
|
289
447
|
} | CanceledResult;
|
|
290
448
|
|
|
449
|
+
/** An acknowledgement dialog has no cancel button. */
|
|
450
|
+
export type AlertOptions = Omit<ShowModalOptions, 'showCancel' | 'cancelText' | 'cancelColor'>;
|
|
451
|
+
|
|
291
452
|
/** Every surface handle, narrowable by `kind`. */
|
|
292
453
|
export type AnySurface = PageSurface | DeclaredSurface | AppSurface | TabSurface | BuiltinSurface;
|
|
293
454
|
|
|
@@ -295,7 +456,7 @@ export type AnySurface = PageSurface | DeclaredSurface | AppSurface | TabSurface
|
|
|
295
456
|
* The product-wide cache a settings screen reports and clears.
|
|
296
457
|
* App-scoped, not lxapp-scoped: the figure covers every lxapp the host
|
|
297
458
|
* has run. Injected only into the Control app, same gate as
|
|
298
|
-
* `lx.
|
|
459
|
+
* `lx.host.control` — guests do not have the member.
|
|
299
460
|
*/
|
|
300
461
|
export type AppCacheApi = {
|
|
301
462
|
/** Estimated reclaimable managed bytes; excludes live session storage and WebView cache. */
|
|
@@ -333,7 +494,7 @@ export type AppDownloadOptions = DownloadOptionsBase & {
|
|
|
333
494
|
/**
|
|
334
495
|
* Optional app-owned durable output path.
|
|
335
496
|
*
|
|
336
|
-
* Omit `filePath` to receive a temporary result in `
|
|
497
|
+
* Omit `filePath` to receive a temporary result in `uri`. Relative
|
|
337
498
|
* paths resolve under user data. `lx://` paths must target `lx://userdata`;
|
|
338
499
|
* `lx://usercache` is not accepted here.
|
|
339
500
|
*/
|
|
@@ -345,24 +506,15 @@ export type AppDownloadOptions = DownloadOptionsBase & {
|
|
|
345
506
|
};
|
|
346
507
|
|
|
347
508
|
export type AppDownloadResult = {
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
*
|
|
351
|
-
* Not durable; move or copy it to `lx://userdata` if you need to keep it.
|
|
352
|
-
*
|
|
353
|
-
* When `filePath` is omitted, the runtime must be able to infer a file
|
|
354
|
-
* type from the URL or the server's `Content-Type` header.
|
|
355
|
-
*/
|
|
356
|
-
tempFilePath: string;
|
|
357
|
-
filePath?: never;
|
|
509
|
+
uri: AppDownloadFilePath;
|
|
510
|
+
storage: 'temp';
|
|
358
511
|
mimeType?: string;
|
|
359
|
-
|
|
512
|
+
sizeBytes: number;
|
|
360
513
|
} | {
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
tempFilePath?: never;
|
|
514
|
+
uri: AppDownloadFilePath;
|
|
515
|
+
storage: 'userdata';
|
|
364
516
|
mimeType?: string;
|
|
365
|
-
|
|
517
|
+
sizeBytes: number;
|
|
366
518
|
};
|
|
367
519
|
|
|
368
520
|
export type AppInstance = AppConfig & {
|
|
@@ -412,7 +564,7 @@ export type AppScreenshotOptions = {
|
|
|
412
564
|
|
|
413
565
|
export type AppScreenshotResult = {
|
|
414
566
|
/** `lx://` URI of the captured PNG in the lxapp temp directory. */
|
|
415
|
-
|
|
567
|
+
uri: string;
|
|
416
568
|
/** Image width in pixels, when the runtime could read it from the PNG. */
|
|
417
569
|
width?: number;
|
|
418
570
|
/** Image height in pixels, when the runtime could read it from the PNG. */
|
|
@@ -425,7 +577,7 @@ export type AppSurface = SurfaceBase & SurfaceShowable & {
|
|
|
425
577
|
readonly realized: 'main' | 'aside';
|
|
426
578
|
};
|
|
427
579
|
|
|
428
|
-
/** `lx.
|
|
580
|
+
/** `lx.host.appearance` — the scheme this lxapp renders in. */
|
|
429
581
|
export type AppearanceApi = {
|
|
430
582
|
/**
|
|
431
583
|
* The scheme this lxapp is rendering in. An lxapp that pinned one in its
|
|
@@ -447,25 +599,6 @@ export type AppearanceApi = {
|
|
|
447
599
|
*/
|
|
448
600
|
export type AppearancePreference = 'auto' | 'light' | 'dark';
|
|
449
601
|
|
|
450
|
-
/**
|
|
451
|
-
* Launch-at-startup control for the host app.
|
|
452
|
-
* Absent (`undefined`) wherever the host cannot register a startup item.
|
|
453
|
-
* `lx.supports({ capability: 'autostart' })` and the member's presence always
|
|
454
|
-
* agree, so either gate works:
|
|
455
|
-
* ```ts
|
|
456
|
-
* if (lx.supports({ capability: 'autostart' })) {
|
|
457
|
-
* // render the "Launch at startup" toggle
|
|
458
|
-
* }
|
|
459
|
-
* ```
|
|
460
|
-
* Requires `capabilities.autostart: true` in `lingxia.yaml`; without it the
|
|
461
|
-
* member is absent on all platforms. Declaring the capability never enables
|
|
462
|
-
* autostart by itself — the SDK registers the app only when `setEnabled(true)`
|
|
463
|
-
* is called, so the decision stays with the user (typically a settings-page
|
|
464
|
-
* toggle, default off).
|
|
465
|
-
* Host-app-level capability: like `checkUpdate` and `screenshot`, the methods
|
|
466
|
-
* are available only to the native-assigned Control app; other lxapps receive
|
|
467
|
-
* a permission error.
|
|
468
|
-
*/
|
|
469
602
|
export type AutostartApi = {
|
|
470
603
|
/**
|
|
471
604
|
* Whether the app is currently registered to launch at startup, read from
|
|
@@ -483,6 +616,36 @@ export type AutostartApi = {
|
|
|
483
616
|
setEnabled(on: boolean): Promise<void>;
|
|
484
617
|
};
|
|
485
618
|
|
|
619
|
+
/**
|
|
620
|
+
* Product-drawn desktop banner, top-right. Not an OS notification and
|
|
621
|
+
* not bound to App Link. Present only in the desktop Control app;
|
|
622
|
+
* presence and `lx.supports('app.banner')` always agree.
|
|
623
|
+
* No buttons: an informational card that auto-dismisses (5s unless
|
|
624
|
+
* `timeoutMs` is set). With buttons: a gate that waits for a choice,
|
|
625
|
+
* dismiss, timeout, or replace. User outcomes resolve; presentation
|
|
626
|
+
* failures reject.
|
|
627
|
+
*/
|
|
628
|
+
export type BannerApi = {
|
|
629
|
+
show(options: {
|
|
630
|
+
id?: string;
|
|
631
|
+
title: string;
|
|
632
|
+
body?: string;
|
|
633
|
+
actions?: Array<{
|
|
634
|
+
id: string;
|
|
635
|
+
label: string;
|
|
636
|
+
style?: 'default' | 'primary' | 'destructive';
|
|
637
|
+
}>;
|
|
638
|
+
timeoutMs?: number;
|
|
639
|
+
/** Omit/`system` follows the OS. `light`/`dark` force chrome. `#RGB`/`#RRGGBB`/`#RRGGBBAA` is a solid fill. */
|
|
640
|
+
background?: 'system' | 'light' | 'dark' | string;
|
|
641
|
+
}): Promise<
|
|
642
|
+
| { status: 'ok'; id: string; action: string }
|
|
643
|
+
| { status: 'canceled'; id: string; reason: 'dismissed' | 'timeout' | 'replaced' }
|
|
644
|
+
>;
|
|
645
|
+
/** Unknown ids are fine. */
|
|
646
|
+
dismiss(id: string): Promise<void>;
|
|
647
|
+
};
|
|
648
|
+
|
|
486
649
|
export type BinaryFileData = ArrayBuffer | ArrayBufferView;
|
|
487
650
|
|
|
488
651
|
/**
|
|
@@ -494,16 +657,15 @@ export type BuiltinShellPage = 'downloads';
|
|
|
494
657
|
/**
|
|
495
658
|
* A host builtin page such as downloads. The shell owns
|
|
496
659
|
* its lifetime and its visibility, so this handle reports identity:
|
|
497
|
-
* there is no `show
|
|
498
|
-
* with `unsupported_placement`.
|
|
660
|
+
* there is no `show`, `hide`, `close`, or `onClose`.
|
|
499
661
|
*/
|
|
500
|
-
export type BuiltinSurface = SurfaceBase & {
|
|
662
|
+
export type BuiltinSurface = Omit<SurfaceBase, 'close' | 'onClose'> & {
|
|
501
663
|
readonly kind: 'builtin';
|
|
502
664
|
};
|
|
503
665
|
|
|
504
666
|
/** The user dismissed the operation. Never an error. */
|
|
505
667
|
export type CanceledResult = {
|
|
506
|
-
|
|
668
|
+
status: 'canceled';
|
|
507
669
|
};
|
|
508
670
|
|
|
509
671
|
export type ChooseDirectoryOptions = {
|
|
@@ -512,11 +674,11 @@ export type ChooseDirectoryOptions = {
|
|
|
512
674
|
};
|
|
513
675
|
|
|
514
676
|
/**
|
|
515
|
-
* Result of `lx.chooseDirectory`. Branch on `
|
|
677
|
+
* Result of `lx.chooseDirectory`. Branch on `status` before reading
|
|
516
678
|
* the selected directory.
|
|
517
679
|
*/
|
|
518
680
|
export type ChooseDirectoryResult = {
|
|
519
|
-
|
|
681
|
+
status: 'ok';
|
|
520
682
|
/** Native-consumable directory reference (path or URI). */
|
|
521
683
|
path: string;
|
|
522
684
|
} | CanceledResult;
|
|
@@ -536,11 +698,11 @@ export type ChooseFileOptions = {
|
|
|
536
698
|
};
|
|
537
699
|
|
|
538
700
|
/**
|
|
539
|
-
* Result of `lx.chooseFile`. Branch on `
|
|
701
|
+
* Result of `lx.chooseFile`. Branch on `status` before reading the
|
|
540
702
|
* selected paths.
|
|
541
703
|
*/
|
|
542
704
|
export type ChooseFileResult = {
|
|
543
|
-
|
|
705
|
+
status: 'ok';
|
|
544
706
|
/**
|
|
545
707
|
* File paths returned by LingXia; always at least one. Values may be
|
|
546
708
|
* app-local paths, `lx://...` paths, or platform system-picker references.
|
|
@@ -555,25 +717,89 @@ export type ChooseMediaOptions = {
|
|
|
555
717
|
mediaType?: ('image' | 'video')[];
|
|
556
718
|
sourceType?: ('album' | 'camera')[];
|
|
557
719
|
camera?: 'back' | 'front';
|
|
558
|
-
|
|
720
|
+
maxDurationSeconds?: number;
|
|
559
721
|
};
|
|
560
722
|
|
|
561
723
|
/**
|
|
562
|
-
* Result of `lx.chooseMedia`. Branch on `
|
|
724
|
+
* Result of `lx.chooseMedia`. Branch on `status` before reading the
|
|
563
725
|
* selected entries.
|
|
564
726
|
*/
|
|
565
727
|
export type ChooseMediaResult = {
|
|
566
|
-
|
|
728
|
+
status: 'ok';
|
|
567
729
|
/** Picked media; always at least one entry. */
|
|
568
730
|
entries: [ChosenMediaEntry, ...ChosenMediaEntry[]];
|
|
569
731
|
} | CanceledResult;
|
|
570
732
|
|
|
571
733
|
export type ChosenMediaEntry = {
|
|
572
|
-
|
|
734
|
+
uri: string;
|
|
573
735
|
fileType: 'image' | 'video';
|
|
574
736
|
isOriginal: boolean;
|
|
575
737
|
};
|
|
576
738
|
|
|
739
|
+
export type ClipboardApi = globalThis.ClipboardApi;
|
|
740
|
+
|
|
741
|
+
export type ClipboardItem = {
|
|
742
|
+
type: 'text';
|
|
743
|
+
text: string;
|
|
744
|
+
} | {
|
|
745
|
+
type: 'image';
|
|
746
|
+
/**
|
|
747
|
+
* Temporary `lx://temp` PNG, session-scoped and auto-cleaned. Move or
|
|
748
|
+
* copy it with `lx.fs` if you need to keep it.
|
|
749
|
+
*/
|
|
750
|
+
filePath: string;
|
|
751
|
+
};
|
|
752
|
+
|
|
753
|
+
export type ClipboardReadOptions = {
|
|
754
|
+
/** Omit to receive every representation the host can surface. */
|
|
755
|
+
type?: ClipboardType;
|
|
756
|
+
};
|
|
757
|
+
|
|
758
|
+
/**
|
|
759
|
+
* Result of `lx.clipboard.read`. Omit `type` to receive every
|
|
760
|
+
* representation this host can surface. A requested type that is
|
|
761
|
+
* absent is `{ status: 'empty' }`, not an error.
|
|
762
|
+
*/
|
|
763
|
+
export type ClipboardReadResult = {
|
|
764
|
+
status: 'empty';
|
|
765
|
+
} | {
|
|
766
|
+
status: 'ok';
|
|
767
|
+
items: ClipboardItem[];
|
|
768
|
+
} | CanceledResult;
|
|
769
|
+
|
|
770
|
+
/**
|
|
771
|
+
* Result of `lx.clipboard.readText`. Branch on `status`.
|
|
772
|
+
* A copied empty string is `{ status: 'ok', text: '' }`;
|
|
773
|
+
* an image-only clipboard is `{ status: 'empty' }`.
|
|
774
|
+
*/
|
|
775
|
+
export type ClipboardTextResult = {
|
|
776
|
+
status: 'empty';
|
|
777
|
+
} | {
|
|
778
|
+
status: 'ok';
|
|
779
|
+
text: string;
|
|
780
|
+
} | CanceledResult;
|
|
781
|
+
|
|
782
|
+
/** Representations the runtime can round-trip. Closed union. */
|
|
783
|
+
export type ClipboardType = 'text' | 'image';
|
|
784
|
+
|
|
785
|
+
/**
|
|
786
|
+
* One clipboard write. Every host accepts both: `image` takes a PNG or
|
|
787
|
+
* JPEG file and re-encodes it as the platform's native image format.
|
|
788
|
+
*/
|
|
789
|
+
export type ClipboardWriteItem = {
|
|
790
|
+
type: 'text';
|
|
791
|
+
/** Unicode text. Rejects `E_INVALID_ARG` when larger than 1 MiB. */
|
|
792
|
+
text: string;
|
|
793
|
+
} | {
|
|
794
|
+
type: 'image';
|
|
795
|
+
/**
|
|
796
|
+
* Managed `lx://` path, or a picker result from `lx.chooseFile` /
|
|
797
|
+
* `lx.chooseMedia` — the same file rules as `lx.share`. Rejects
|
|
798
|
+
* `E_INVALID_ARG` when the file is not a decodable image.
|
|
799
|
+
*/
|
|
800
|
+
filePath: string;
|
|
801
|
+
};
|
|
802
|
+
|
|
577
803
|
export type CompressImageOptions = {
|
|
578
804
|
path: string;
|
|
579
805
|
quality?: number;
|
|
@@ -582,27 +808,34 @@ export type CompressImageOptions = {
|
|
|
582
808
|
};
|
|
583
809
|
|
|
584
810
|
export type CompressImageResult = {
|
|
585
|
-
|
|
811
|
+
uri: string;
|
|
586
812
|
};
|
|
587
813
|
|
|
588
|
-
export type CompressVideoIteratorResult =
|
|
589
|
-
done: boolean;
|
|
590
|
-
value?: CompressVideoProgressEvent;
|
|
591
|
-
};
|
|
814
|
+
export type CompressVideoIteratorResult = IteratorResult<CompressVideoProgressEvent, void>;
|
|
592
815
|
|
|
593
816
|
export type CompressVideoOptions = {
|
|
817
|
+
signal?: AbortSignal;
|
|
594
818
|
/**
|
|
595
819
|
* Source video path or `lx://` URI.
|
|
596
820
|
*/
|
|
597
821
|
path: string;
|
|
598
822
|
/**
|
|
599
|
-
*
|
|
600
|
-
|
|
601
|
-
|
|
823
|
+
* Optional output path for compressed file.
|
|
824
|
+
*/
|
|
825
|
+
outputPath?: string;
|
|
826
|
+
} & (
|
|
827
|
+
| {
|
|
828
|
+
/**
|
|
602
829
|
* Compression quality preset.
|
|
603
|
-
*
|
|
830
|
+
* Mutually exclusive with `bitrate`, `fps`, and `resolution`.
|
|
604
831
|
*/
|
|
605
|
-
quality
|
|
832
|
+
quality: VideoCompressQuality;
|
|
833
|
+
bitrate?: never;
|
|
834
|
+
fps?: never;
|
|
835
|
+
resolution?: never;
|
|
836
|
+
}
|
|
837
|
+
| {
|
|
838
|
+
quality?: never;
|
|
606
839
|
/**
|
|
607
840
|
* Preferred target video bitrate in kbps.
|
|
608
841
|
* May be adjusted or ignored by platform codec/runtime limitations.
|
|
@@ -618,11 +851,8 @@ export type CompressVideoOptions = {
|
|
|
618
851
|
* May be approximated or ignored by platform transcoder capabilities.
|
|
619
852
|
*/
|
|
620
853
|
resolution?: number;
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
*/
|
|
624
|
-
outputPath?: string;
|
|
625
|
-
};
|
|
854
|
+
}
|
|
855
|
+
);
|
|
626
856
|
|
|
627
857
|
export type CompressVideoProgressEvent = {
|
|
628
858
|
/** Transcode progress in percent, `0`-`100`. */
|
|
@@ -630,7 +860,7 @@ export type CompressVideoProgressEvent = {
|
|
|
630
860
|
};
|
|
631
861
|
|
|
632
862
|
export type CompressVideoResult = {
|
|
633
|
-
|
|
863
|
+
uri: string;
|
|
634
864
|
width: number;
|
|
635
865
|
height: number;
|
|
636
866
|
durationMs: number;
|
|
@@ -644,23 +874,11 @@ export type CompressVideoResult = {
|
|
|
644
874
|
|
|
645
875
|
/**
|
|
646
876
|
* Handle returned by `lx.compressVideo`.
|
|
647
|
-
* Awaiting
|
|
648
|
-
* Iterating
|
|
877
|
+
* Awaiting `task.result` resolves with the final {@link CompressVideoResult}.
|
|
878
|
+
* Iterating `task.progress` with `for await` yields {@link CompressVideoProgressEvent}s
|
|
649
879
|
* while the transcode runs.
|
|
650
880
|
*/
|
|
651
|
-
export type CompressVideoTask =
|
|
652
|
-
next(): Promise<CompressVideoIteratorResult>;
|
|
653
|
-
/** Stops iteration only. Does not cancel the compression. */
|
|
654
|
-
return(): Promise<CompressVideoIteratorResult>;
|
|
655
|
-
catch<TResult = never>(onrejected?: ((reason: unknown) => TResult | PromiseLike<TResult>) | null): Promise<CompressVideoResult | TResult>;
|
|
656
|
-
finally(onfinally?: (() => void) | null): Promise<CompressVideoResult>;
|
|
657
|
-
/**
|
|
658
|
-
* Cancels the transcode and deletes any partial output.
|
|
659
|
-
* The task promise rejects with an `AbortError` (`code: 'E_ABORT'`).
|
|
660
|
-
*/
|
|
661
|
-
cancel(): void;
|
|
662
|
-
wait(): Promise<CompressVideoResult>;
|
|
663
|
-
};
|
|
881
|
+
export type CompressVideoTask = CancelableTask<CompressVideoResult, CompressVideoProgressEvent>;
|
|
664
882
|
|
|
665
883
|
/**
|
|
666
884
|
* Configured page name from `lxapp.json` / `lingxia.yaml`. JavaScript
|
|
@@ -673,17 +891,20 @@ export type CompressVideoTask = PromiseLike<CompressVideoResult> & AsyncIterable
|
|
|
673
891
|
*/
|
|
674
892
|
export type ConfiguredPageName = keyof LxAppPages extends never ? string : keyof LxAppPages;
|
|
675
893
|
|
|
894
|
+
/** A confirmation dialog always permits declining. */
|
|
895
|
+
export type ConfirmOptions = Omit<ShowModalOptions, 'showCancel'>;
|
|
896
|
+
|
|
676
897
|
export type ConnectWifiOptions = {
|
|
677
|
-
|
|
898
|
+
ssid: string;
|
|
678
899
|
password?: string;
|
|
679
900
|
};
|
|
680
901
|
|
|
681
902
|
/**
|
|
682
|
-
* `lx.
|
|
903
|
+
* `lx.host.control` — product-wide settings, and their single writer.
|
|
683
904
|
* Present only in the Control app. Bind it once rather than repeating
|
|
684
|
-
* `lx.
|
|
905
|
+
* `lx.host.control!`:
|
|
685
906
|
* ```js
|
|
686
|
-
* const control = lx.
|
|
907
|
+
* const control = lx.host.control;
|
|
687
908
|
* if (!control) return; // not the Control app
|
|
688
909
|
* await control.appearance.setPreference('dark');
|
|
689
910
|
* ```
|
|
@@ -693,7 +914,7 @@ export type ControlApi = {
|
|
|
693
914
|
readonly appearance: ControlAppearanceApi;
|
|
694
915
|
};
|
|
695
916
|
|
|
696
|
-
/** `lx.
|
|
917
|
+
/** `lx.host.control.appearance` — the product's own light/dark setting. */
|
|
697
918
|
export type ControlAppearanceApi = {
|
|
698
919
|
/** What the user chose for the whole product. */
|
|
699
920
|
getPreference(): AppearancePreference;
|
|
@@ -704,7 +925,7 @@ export type ControlAppearanceApi = {
|
|
|
704
925
|
setPreference(preference: AppearancePreference): Promise<void>;
|
|
705
926
|
/**
|
|
706
927
|
* Follow the choice, not what it resolves to: a system flip under `'auto'`
|
|
707
|
-
* moves `lx.
|
|
928
|
+
* moves `lx.host.appearance.watch` and leaves this quiet. Starts with the
|
|
708
929
|
* current value; that first callback runs synchronously, before
|
|
709
930
|
* `watchPreference` returns.
|
|
710
931
|
*/
|
|
@@ -712,7 +933,7 @@ export type ControlAppearanceApi = {
|
|
|
712
933
|
};
|
|
713
934
|
|
|
714
935
|
/**
|
|
715
|
-
* `lx.
|
|
936
|
+
* `lx.host.control.displayLanguage` — the preference behind that
|
|
716
937
|
* language, for the one surface that edits it.
|
|
717
938
|
*/
|
|
718
939
|
export type ControlDisplayLanguageApi = {
|
|
@@ -741,7 +962,7 @@ export type DeviceOrientationChangeEvent = {
|
|
|
741
962
|
value: DeviceOrientation;
|
|
742
963
|
};
|
|
743
964
|
|
|
744
|
-
/** `lx.
|
|
965
|
+
/** `lx.host.displayLanguage` — the language this lxapp renders in. */
|
|
745
966
|
export type DisplayLanguageApi = {
|
|
746
967
|
/**
|
|
747
968
|
* The language in effect right now, as a canonical BCP-47 tag. Map it to
|
|
@@ -781,7 +1002,7 @@ export type DownloadOptionsBase = {
|
|
|
781
1002
|
*/
|
|
782
1003
|
headers?: Record<string, string>;
|
|
783
1004
|
/** Request timeout in milliseconds. */
|
|
784
|
-
|
|
1005
|
+
timeoutMs?: number;
|
|
785
1006
|
/** Optional abort signal. */
|
|
786
1007
|
signal?: AbortSignal;
|
|
787
1008
|
};
|
|
@@ -793,17 +1014,17 @@ export type DownloadsDownloadOptions = DownloadOptionsBase & {
|
|
|
793
1014
|
* Optional filename hint for the system Downloads destination.
|
|
794
1015
|
* This is not an app-owned `lx.fs` path.
|
|
795
1016
|
*/
|
|
796
|
-
|
|
1017
|
+
suggestedName?: string;
|
|
1018
|
+
filePath?: never;
|
|
797
1019
|
/** Save into the user's system Downloads directory. */
|
|
798
1020
|
destination: 'downloads';
|
|
799
1021
|
};
|
|
800
1022
|
|
|
801
1023
|
export type DownloadsDownloadResult = {
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
tempFilePath?: never;
|
|
1024
|
+
uri: SystemDownloadsPath;
|
|
1025
|
+
storage: 'downloads';
|
|
805
1026
|
mimeType?: string;
|
|
806
|
-
|
|
1027
|
+
sizeBytes: number;
|
|
807
1028
|
};
|
|
808
1029
|
|
|
809
1030
|
/**
|
|
@@ -847,7 +1068,7 @@ export type ExtractVideoThumbnailResult = {
|
|
|
847
1068
|
/**
|
|
848
1069
|
* Generated thumbnail file path.
|
|
849
1070
|
*/
|
|
850
|
-
|
|
1071
|
+
uri: string;
|
|
851
1072
|
/**
|
|
852
1073
|
* Output image width in pixels.
|
|
853
1074
|
*/
|
|
@@ -906,10 +1127,10 @@ export type GetImageInfoOptions = {
|
|
|
906
1127
|
|
|
907
1128
|
/** Location APIs. */
|
|
908
1129
|
export type GetLocationOptions = {
|
|
909
|
-
|
|
1130
|
+
coordinateSystem?: 'wgs84' | 'gcj02';
|
|
910
1131
|
altitude?: boolean;
|
|
911
1132
|
isHighAccuracy?: boolean;
|
|
912
|
-
|
|
1133
|
+
timeoutMs?: number;
|
|
913
1134
|
};
|
|
914
1135
|
|
|
915
1136
|
export type GetVideoInfoOptions = {
|
|
@@ -925,8 +1146,11 @@ export type HostAppApi = globalThis.HostAppApi;
|
|
|
925
1146
|
* Build-time deployment environment of the host app (`dev` | `prod`).
|
|
926
1147
|
* Surfaced via {@link HostAppApi.env}. Taken from the `env` field in
|
|
927
1148
|
* the generated `app.json`. Missing `env` is treated as `'prod'`.
|
|
928
|
-
* This is the host build axis:
|
|
929
|
-
* token, and self-update
|
|
1149
|
+
* This is the immutable host build axis: package-id suffix, publish
|
|
1150
|
+
* token, signed App Link entitlements, and self-update channel.
|
|
1151
|
+
* In-app App Link hosts follow {@link HostAppApi.getServiceEnv} on
|
|
1152
|
+
* the next launch. The mutable service environment is
|
|
1153
|
+
* {@link HostAppApi.toggleServiceEnv}. It is **not** the
|
|
930
1154
|
* lxapp publish channel (`LxAppEnvVersion` / `LxAppReleaseType`:
|
|
931
1155
|
* `'release' | 'draft'`). Default channel is derived
|
|
932
1156
|
* from env (`dev` → `draft`, `prod` → `release`) and can be
|
|
@@ -949,7 +1173,7 @@ export type HostAppUpdateEvent = {
|
|
|
949
1173
|
downloadedBytes?: number;
|
|
950
1174
|
progress?: number;
|
|
951
1175
|
} | {
|
|
952
|
-
state: 'downloaded' | 'installRequested';
|
|
1176
|
+
state: 'downloaded' | 'installRequested' | 'storeOpened';
|
|
953
1177
|
} | {
|
|
954
1178
|
state: 'failed';
|
|
955
1179
|
stage: HostAppUpdateApplyStage;
|
|
@@ -960,42 +1184,40 @@ export type HostAppUpdateInfo = {
|
|
|
960
1184
|
version: string;
|
|
961
1185
|
size?: number;
|
|
962
1186
|
releaseNotes?: string[];
|
|
963
|
-
isForceUpdate: boolean;
|
|
964
1187
|
/**
|
|
965
|
-
*
|
|
1188
|
+
* How this update is applied. `store` opens the platform marketplace;
|
|
1189
|
+
* `direct` downloads and self-installs. `lx.supports('app.selfUpdate')`
|
|
1190
|
+
* is true only for `direct`.
|
|
1191
|
+
*/
|
|
1192
|
+
channel: 'direct' | 'store';
|
|
1193
|
+
/**
|
|
1194
|
+
* Apply this checked update.
|
|
966
1195
|
*
|
|
967
|
-
* `apply()` is single-use for this update object.
|
|
1196
|
+
* `apply()` is single-use for this update object. It also claims custom
|
|
1197
|
+
* host updates for the rest of this process, same as
|
|
1198
|
+
* {@link HostAppApi.claimCustomUpdate}.
|
|
968
1199
|
*
|
|
969
|
-
*
|
|
970
|
-
*
|
|
1200
|
+
* Await `task.result` when progress is not needed, or iterate
|
|
1201
|
+
* `task.progress` to render it.
|
|
971
1202
|
*
|
|
972
|
-
*
|
|
973
|
-
*
|
|
974
|
-
*
|
|
1203
|
+
* On `direct`, downloads and hands off install. On `store`, opens the
|
|
1204
|
+
* platform store listing (no package is downloaded) and resolves
|
|
1205
|
+
* `storeOpened`; whether the user then updates is not reported.
|
|
975
1206
|
*/
|
|
976
1207
|
apply(): HostAppUpdateTask;
|
|
977
1208
|
};
|
|
978
1209
|
|
|
979
|
-
export type HostAppUpdateIteratorResult =
|
|
980
|
-
done: boolean;
|
|
981
|
-
value?: HostAppUpdateEvent;
|
|
982
|
-
};
|
|
1210
|
+
export type HostAppUpdateIteratorResult = IteratorResult<HostAppUpdateEvent, void>;
|
|
983
1211
|
|
|
984
1212
|
export type HostAppUpdateResult = {
|
|
985
|
-
|
|
1213
|
+
/** `storeOpened` on a `store` channel: the listing opened, nothing was installed. */
|
|
1214
|
+
state: 'installRequested' | 'storeOpened';
|
|
986
1215
|
};
|
|
987
1216
|
|
|
988
|
-
export type HostAppUpdateTask =
|
|
989
|
-
next(): Promise<HostAppUpdateIteratorResult>;
|
|
990
|
-
/** Stops iteration only. It does not cancel an app update already handed to the platform. */
|
|
991
|
-
return(): Promise<HostAppUpdateIteratorResult>;
|
|
992
|
-
catch<TResult = never>(onrejected?: ((reason: unknown) => TResult | PromiseLike<TResult>) | null): Promise<HostAppUpdateResult | TResult>;
|
|
993
|
-
finally(onfinally?: (() => void) | null): Promise<HostAppUpdateResult>;
|
|
994
|
-
wait(): Promise<HostAppUpdateResult>;
|
|
995
|
-
};
|
|
1217
|
+
export type HostAppUpdateTask = Task<HostAppUpdateResult, HostAppUpdateEvent>;
|
|
996
1218
|
|
|
997
1219
|
/**
|
|
998
|
-
* Canonical platform-family label shared by `lx.
|
|
1220
|
+
* Canonical platform-family label shared by `lx.host.getBaseInfo().os`
|
|
999
1221
|
* and `lx.getDeviceInfo().osName`. `"unknown"` is a non-product build.
|
|
1000
1222
|
*/
|
|
1001
1223
|
export type HostOs = 'iOS' | 'macOS' | 'Android' | 'Windows' | 'Harmony' | 'unknown';
|
|
@@ -1007,6 +1229,43 @@ export type InstalledTerminalFont = {
|
|
|
1007
1229
|
nerdIcons: boolean;
|
|
1008
1230
|
};
|
|
1009
1231
|
|
|
1232
|
+
/**
|
|
1233
|
+
* Launch-at-startup control for the host app.
|
|
1234
|
+
* Absent (`undefined`) wherever the host cannot register a startup item.
|
|
1235
|
+
* `lx.supports('app.autostart')` and the member's presence always
|
|
1236
|
+
* agree, so either gate works:
|
|
1237
|
+
* ```ts
|
|
1238
|
+
* if (lx.supports('app.autostart')) {
|
|
1239
|
+
* // render the "Launch at startup" toggle
|
|
1240
|
+
* }
|
|
1241
|
+
* ```
|
|
1242
|
+
* Requires `capabilities.autostart: true` in `lingxia.yaml`; without it the
|
|
1243
|
+
* member is absent on all platforms. Declaring the capability never enables
|
|
1244
|
+
* autostart by itself — the SDK registers the app only when `setEnabled(true)`
|
|
1245
|
+
* is called, so the decision stays with the user (typically a settings-page
|
|
1246
|
+
* toggle, default off).
|
|
1247
|
+
* Host-app-level capability: like `checkUpdate` and `screenshot`, the methods
|
|
1248
|
+
* are available only to the native-assigned Control app; other lxapps receive
|
|
1249
|
+
* a permission error.
|
|
1250
|
+
* Local notifications as a Control-app resume affordance.
|
|
1251
|
+
* Absent unless the host declared `capabilities.notifications` and the
|
|
1252
|
+
* platform implements the local API. Presence and
|
|
1253
|
+
* `lx.supports('app.notification')` always agree.
|
|
1254
|
+
* Declaring the capability never prompts; permission runs on
|
|
1255
|
+
* `requestPermission()` or the first `show()` that reaches the OS.
|
|
1256
|
+
* Control app only. Guest lxapps receive a permission error.
|
|
1257
|
+
* A JSON value: what a navigation route parameter may hold. Not a way
|
|
1258
|
+
* to smuggle a payload — every route declares its own parameter
|
|
1259
|
+
* schema, and the framework caps size, count, and nesting.
|
|
1260
|
+
*/
|
|
1261
|
+
export type JsonValue =
|
|
1262
|
+
| null
|
|
1263
|
+
| boolean
|
|
1264
|
+
| number
|
|
1265
|
+
| string
|
|
1266
|
+
| JsonValue[]
|
|
1267
|
+
| { [key: string]: JsonValue };
|
|
1268
|
+
|
|
1010
1269
|
/**
|
|
1011
1270
|
* Input event APIs.
|
|
1012
1271
|
* Platform support: Android only
|
|
@@ -1030,38 +1289,8 @@ export type LxAppEnvVersion = 'release' | 'draft';
|
|
|
1030
1289
|
/** LxApp metadata APIs. */
|
|
1031
1290
|
export type LxAppReleaseType = 'release' | 'draft';
|
|
1032
1291
|
|
|
1033
|
-
/** Boolean capability names accepted by `lx.supports`. */
|
|
1034
|
-
export type LxCapabilityFlag = 'control' | 'terminal' | 'autostart' | 'notifications' | 'browser' | 'proxy' | 'selfUpdate' | 'process' | 'appUse' | 'computerUse' | 'browserUse' | 'mediaCapture';
|
|
1035
|
-
|
|
1036
|
-
/**
|
|
1037
|
-
* One capability question per call. The catalog is closed, so
|
|
1038
|
-
* completion enumerates it and a typo is a type error. `capability`
|
|
1039
|
-
* is the discriminant; only the `surface` branch accepts a `value`.
|
|
1040
|
-
* Two surface answers describe an *affordance*, not whether the call
|
|
1041
|
-
* succeeds: `tab` is "the host has an in-app browser" — without it a
|
|
1042
|
-
* url still opens, in the OS browser instead — and `aside` is "a
|
|
1043
|
-
* docked region exists right now", while a compact layout still opens
|
|
1044
|
-
* the url through the in-app browser's own chrome. Ask them to decide
|
|
1045
|
-
* what to render, not whether to call.
|
|
1046
|
-
* `chrome` qualifies a window and only a window: it asks whether this
|
|
1047
|
-
* host can produce that decoration, not merely a window.
|
|
1048
|
-
*/
|
|
1049
|
-
export type LxCapabilityQuery = {
|
|
1050
|
-
capability: 'surface';
|
|
1051
|
-
value: 'window';
|
|
1052
|
-
chrome?: WindowChrome;
|
|
1053
|
-
} | {
|
|
1054
|
-
capability: 'surface';
|
|
1055
|
-
value: Exclude<LxSurfaceCapability, 'window'>;
|
|
1056
|
-
} | {
|
|
1057
|
-
capability: LxCapabilityFlag;
|
|
1058
|
-
};
|
|
1059
|
-
|
|
1060
1292
|
export type LxEnv = globalThis.LxEnv;
|
|
1061
1293
|
|
|
1062
|
-
/** Surface placements accepted by `lx.supports`. */
|
|
1063
|
-
export type LxSurfaceCapability = 'main' | 'aside' | 'float' | 'window' | 'tab';
|
|
1064
|
-
|
|
1065
1294
|
/** Device action APIs. */
|
|
1066
1295
|
export type MakePhoneCallOptions = {
|
|
1067
1296
|
phoneNumber: string;
|
|
@@ -1072,11 +1301,11 @@ export type MediaObjectFit = 'cover' | 'contain' | 'fill' | 'fit';
|
|
|
1072
1301
|
export type MediaRotation = 0 | 90 | 180 | 270;
|
|
1073
1302
|
|
|
1074
1303
|
/**
|
|
1075
|
-
* Result of `lx.showModal`. `
|
|
1304
|
+
* Result of `lx.showModal`. `status: 'ok'` means the user confirmed;
|
|
1076
1305
|
* there is no third resolved outcome. Presentation failures reject.
|
|
1077
1306
|
*/
|
|
1078
1307
|
export type ModalResult = {
|
|
1079
|
-
|
|
1308
|
+
status: 'ok';
|
|
1080
1309
|
} | CanceledResult;
|
|
1081
1310
|
|
|
1082
1311
|
/**
|
|
@@ -1140,6 +1369,24 @@ export type NavigationBarStylePatch = {
|
|
|
1140
1369
|
dividerColor?: string | null;
|
|
1141
1370
|
};
|
|
1142
1371
|
|
|
1372
|
+
/**
|
|
1373
|
+
* Where a notification tap, a menu item, or the tray goes.
|
|
1374
|
+
* `page` and `app` are the same contract as `lx.navigateTo` /
|
|
1375
|
+
* `lx.navigateToApp`: a configured page name and a query, ordinary
|
|
1376
|
+
* scene. `route` is a host-registered location that is not a page.
|
|
1377
|
+
* `appLink` is an `https://` product URL that is also a real inbound
|
|
1378
|
+
* App Link (`scene === 8003`). `activate` just brings the product
|
|
1379
|
+
* forward.
|
|
1380
|
+
* A branch carries its own fields and no others: a mixed target is a
|
|
1381
|
+
* parameter error, not a best guess.
|
|
1382
|
+
*/
|
|
1383
|
+
export type NavigationTarget =
|
|
1384
|
+
| { kind: 'activate' }
|
|
1385
|
+
| { kind: 'page'; page: ConfiguredPageName; query?: PageQuery }
|
|
1386
|
+
| { kind: 'app'; appId: string; page?: ExternalPageName; query?: PageQuery }
|
|
1387
|
+
| { kind: 'route'; name: string; params?: Record<string, JsonValue> }
|
|
1388
|
+
| { kind: 'appLink'; url: string };
|
|
1389
|
+
|
|
1143
1390
|
export type NetworkChangeCallback = (info: NetworkInfo) => void;
|
|
1144
1391
|
|
|
1145
1392
|
export type NetworkInfo = {
|
|
@@ -1152,6 +1399,66 @@ export type NetworkInfo = {
|
|
|
1152
1399
|
/** Network status APIs. */
|
|
1153
1400
|
export type NetworkType = 'none' | 'unknown' | 'wifi' | '2g' | '3g' | '4g' | '5g' | 'ethernet';
|
|
1154
1401
|
|
|
1402
|
+
export type NotificationApi = {
|
|
1403
|
+
/**
|
|
1404
|
+
* Read the current permission without prompting. `'default'` means the
|
|
1405
|
+
* user has not been asked yet.
|
|
1406
|
+
*/
|
|
1407
|
+
getPermission(): Promise<'granted' | 'denied' | 'default'>;
|
|
1408
|
+
/**
|
|
1409
|
+
* Ask for notification permission. Prompts where the OS has a prompt and
|
|
1410
|
+
* the user has not answered; otherwise reports the current setting.
|
|
1411
|
+
* Rejects when the prompt is left unanswered.
|
|
1412
|
+
*/
|
|
1413
|
+
requestPermission(): Promise<'granted' | 'denied'>;
|
|
1414
|
+
/**
|
|
1415
|
+
* Post or replace a local notification. `id` is the replace key: anything
|
|
1416
|
+
* pending or delivered under it is replaced, whatever `status` comes back,
|
|
1417
|
+
* and its old tap target stops resolving. Omit `id` to get a generated
|
|
1418
|
+
* one. Omit `schedule`, or pass a time that is not in the future, to post
|
|
1419
|
+
* now.
|
|
1420
|
+
*
|
|
1421
|
+
* `target` is where the tap goes, and an omitted one means
|
|
1422
|
+
* `{ kind: 'activate' }` — bring the product forward, nothing else.
|
|
1423
|
+
* `{ kind: 'page' }` opens a page of this Control app the way
|
|
1424
|
+
* `lx.navigateTo` does. `{ kind: 'app' }` opens another lxapp the way
|
|
1425
|
+
* `lx.navigateToApp` does. `{ kind: 'route' }` names a location the host
|
|
1426
|
+
* registered at startup that is not a page. `{ kind: 'appLink' }` takes
|
|
1427
|
+
* an `https://` URL that is also a real inbound App Link
|
|
1428
|
+
* (`scene === 8003`). An unknown page or route, a parameter the route
|
|
1429
|
+
* did not declare, or a host that is not configured rejects here, before
|
|
1430
|
+
* anything is posted.
|
|
1431
|
+
*
|
|
1432
|
+
* `status` says what happened: `'posted'` — the OS accepted it for
|
|
1433
|
+
* display now, which is not a receipt that anyone saw or read it;
|
|
1434
|
+
* `'scheduled'` — queued with the OS for `schedule`; `'suppressed'` — an
|
|
1435
|
+
* immediate post while the product is already frontmost, where nothing is
|
|
1436
|
+
* posted and no permission is needed. A scheduled notification is
|
|
1437
|
+
* presented even if the product is frontmost when it fires.
|
|
1438
|
+
*
|
|
1439
|
+
* A tap resolves through the host, so a target that is gone by then — a
|
|
1440
|
+
* route the build no longer registers, a cancelled or replaced
|
|
1441
|
+
* notification, cleared app data — brings the product forward and says it
|
|
1442
|
+
* is unavailable rather than opening something else.
|
|
1443
|
+
*/
|
|
1444
|
+
show(options: {
|
|
1445
|
+
id?: string;
|
|
1446
|
+
title: string;
|
|
1447
|
+
body?: string;
|
|
1448
|
+
target?: NavigationTarget;
|
|
1449
|
+
schedule?: { at: number } | { delayMs: number };
|
|
1450
|
+
/** No sound. The banner still appears. */
|
|
1451
|
+
silent?: boolean;
|
|
1452
|
+
}): Promise<{ id: string; status: 'posted' | 'scheduled' | 'suppressed' }>;
|
|
1453
|
+
/**
|
|
1454
|
+
* Remove what is pending or delivered under `id`, and retire its tap
|
|
1455
|
+
* target. Unknown ids are fine.
|
|
1456
|
+
*/
|
|
1457
|
+
cancel(id: string): Promise<void>;
|
|
1458
|
+
/** Remove every local notification this API posted or scheduled. */
|
|
1459
|
+
cancelAll(): Promise<void>;
|
|
1460
|
+
};
|
|
1461
|
+
|
|
1155
1462
|
/** File system APIs. */
|
|
1156
1463
|
export type OpenFileOptions = {
|
|
1157
1464
|
/** Local file path or runtime-managed temp path. */
|
|
@@ -1206,7 +1513,7 @@ export type OpenPageShared = {
|
|
|
1206
1513
|
size?: OverlaySurfaceSize;
|
|
1207
1514
|
interaction?: SurfaceInteraction;
|
|
1208
1515
|
query?: PageQuery;
|
|
1209
|
-
/** Caller-owned identity, for `lx.surface.
|
|
1516
|
+
/** Caller-owned identity, for `lx.surface.getByKey(key)` later. */
|
|
1210
1517
|
key?: string;
|
|
1211
1518
|
};
|
|
1212
1519
|
|
|
@@ -1219,7 +1526,7 @@ export type OpenUrlOptions = {
|
|
|
1219
1526
|
/** Preferred docking side when the realized placement is an aside. */
|
|
1220
1527
|
edge?: SurfaceEdge;
|
|
1221
1528
|
size?: OverlaySurfaceSize;
|
|
1222
|
-
/** Stable identity for `lx.surface.
|
|
1529
|
+
/** Stable identity for `lx.surface.getByKey(key)`. */
|
|
1223
1530
|
key?: string;
|
|
1224
1531
|
};
|
|
1225
1532
|
|
|
@@ -1267,6 +1574,10 @@ export type PageTargetOptions = {
|
|
|
1267
1574
|
query?: PageQuery;
|
|
1268
1575
|
};
|
|
1269
1576
|
|
|
1577
|
+
export type PickFileOptions = Omit<ChooseFileOptions, 'multiple'>;
|
|
1578
|
+
|
|
1579
|
+
export type PickFileResult = { status: 'ok'; uri: string } | CanceledResult;
|
|
1580
|
+
|
|
1270
1581
|
export type PreviewMediaAdvance = 'manual' | 'next' | 'loop';
|
|
1271
1582
|
|
|
1272
1583
|
/** One change-stream event / the `current` snapshot. */
|
|
@@ -1278,28 +1589,12 @@ export type PreviewMediaChange = {
|
|
|
1278
1589
|
export type PreviewMediaCloseReason = 'manual' | 'completed' | 'interrupted' | 'error';
|
|
1279
1590
|
|
|
1280
1591
|
/**
|
|
1281
|
-
*
|
|
1282
|
-
*
|
|
1283
|
-
*
|
|
1284
|
-
* been composited to screen. Use this to time the hide of an overlay
|
|
1285
|
-
* surface above the preview so the swap is seamless. Never rejects;
|
|
1286
|
-
* resolves with no value when the first frame is up. Safe to ignore.
|
|
1287
|
-
* - `current` is a live `{ index, source }` snapshot of the item on screen,
|
|
1288
|
-
* updated as the user swipes and as the session auto-advances.
|
|
1289
|
-
* - `onChange(listener)` fires for every item change. Returns an
|
|
1290
|
-
* unsubscribe function.
|
|
1291
|
-
* - `completed` resolves `{ reason, index, source }` when the preview
|
|
1292
|
-
* session ends (manual / auto / interrupted / error), or rejects on abort.
|
|
1293
|
-
* If the call was aborted before any frame was presented, `presented` still
|
|
1294
|
-
* resolves (with no value) once the abort takes effect — it never rejects,
|
|
1295
|
-
* to keep fire-and-forget usage safe.
|
|
1296
|
-
* @example
|
|
1297
|
-
* const preview = lx.previewMedia({ sources, startIndex: 2 });
|
|
1298
|
-
* preview.onChange(({ source }) => markAsViewed(source.path));
|
|
1299
|
-
* const { reason, source } = await preview.completed;
|
|
1592
|
+
* A media session. `presented` distinguishes a rendered first frame from
|
|
1593
|
+
* an early close, cancellation, or failure. `completed` reports closure;
|
|
1594
|
+
* native playback errors may report reason `error`, while request failures reject.
|
|
1300
1595
|
*/
|
|
1301
1596
|
export type PreviewMediaHandle = {
|
|
1302
|
-
readonly presented: Promise<
|
|
1597
|
+
readonly presented: Promise<{ status: 'presented' } | { status: 'notPresented'; reason: 'canceled' | 'failed' | 'closed' }>;
|
|
1303
1598
|
readonly current: PreviewMediaChange;
|
|
1304
1599
|
onChange(listener: (change: PreviewMediaChange) => void): () => void;
|
|
1305
1600
|
readonly completed: Promise<PreviewMediaResult>;
|
|
@@ -1443,15 +1738,42 @@ export type ScanCodeOptions = {
|
|
|
1443
1738
|
};
|
|
1444
1739
|
|
|
1445
1740
|
/**
|
|
1446
|
-
* Result of `lx.scanCode`. Branch on `
|
|
1741
|
+
* Result of `lx.scanCode`. Branch on `status` before reading the scan
|
|
1447
1742
|
* payload.
|
|
1448
1743
|
*/
|
|
1449
1744
|
export type ScanCodeResult = {
|
|
1450
|
-
|
|
1745
|
+
status: 'ok';
|
|
1451
1746
|
scanResult: string;
|
|
1452
1747
|
scanType: string;
|
|
1453
1748
|
} | CanceledResult;
|
|
1454
1749
|
|
|
1750
|
+
/**
|
|
1751
|
+
* Where `lx.host.setBadge` paints.
|
|
1752
|
+
* `auto` (the default) marks every product-owned surface this platform
|
|
1753
|
+
* has: the dock and the menu-bar item on macOS, the taskbar and the
|
|
1754
|
+
* notification-area item on Windows, the home-screen icon on iOS and
|
|
1755
|
+
* HarmonyOS. Name one only when that surface is the point.
|
|
1756
|
+
* Asynchronous because it reports what actually happened: a platform that
|
|
1757
|
+
* answers through its own callback has to be waited for to be believed.
|
|
1758
|
+
* A surface with nothing to paint on is reported, not raised: a macOS
|
|
1759
|
+
* status item exists from the moment a tray is declared but stays hidden
|
|
1760
|
+
* until `lx.tray.show()`, and a badge on a hidden item is not a badge
|
|
1761
|
+
* anyone can see. That resolves `false` whether you named the surface or
|
|
1762
|
+
* took `auto`; only a malfunction rejects.
|
|
1763
|
+
* Apple ties the badge to notification permission. On macOS the label
|
|
1764
|
+
* always reaches the system, but the Dock declines to draw it for an app
|
|
1765
|
+
* that is registered with Notification Center and not allowed — so a host
|
|
1766
|
+
* that declares `capabilities.notifications` and never got a yes resolves
|
|
1767
|
+
* `false` here. A host that never asks is unaffected.
|
|
1768
|
+
* On iOS the home-screen badge is drawn by the notification system, so
|
|
1769
|
+
* it needs notification permission and only accepts a number — that is
|
|
1770
|
+
* the OS's rule, not an API coupling. Android has no cross-vendor
|
|
1771
|
+
* launcher badge at all, so `setBadge` returns `false` there.
|
|
1772
|
+
*/
|
|
1773
|
+
export type SetBadgeOptions = {
|
|
1774
|
+
surface?: 'auto' | 'appIcon' | 'tray';
|
|
1775
|
+
};
|
|
1776
|
+
|
|
1455
1777
|
/** Share images, PDFs, or other files. */
|
|
1456
1778
|
export type ShareFilesOptions = ShareTitleOptions & {
|
|
1457
1779
|
/**
|
|
@@ -1586,7 +1908,7 @@ export type ShellOpenAppOptions = {
|
|
|
1586
1908
|
*/
|
|
1587
1909
|
channel?: LxAppEnvVersion;
|
|
1588
1910
|
targetVersion?: string;
|
|
1589
|
-
/** Stable identity for `lx.surface.
|
|
1911
|
+
/** Stable identity for `lx.surface.getByKey(key)`. */
|
|
1590
1912
|
key?: string;
|
|
1591
1913
|
};
|
|
1592
1914
|
|
|
@@ -1599,7 +1921,7 @@ export type ShellOpenAppOptions = {
|
|
|
1599
1921
|
*/
|
|
1600
1922
|
export type ShellOpenDeclaredOptions = {
|
|
1601
1923
|
/**
|
|
1602
|
-
* Caller-owned identity, for `lx.surface.
|
|
1924
|
+
* Caller-owned identity, for `lx.surface.getByKey(key)` later — the same key
|
|
1603
1925
|
* every opener takes. It carries one extra power here: a declaration can
|
|
1604
1926
|
* be opened more than once, and the key is which instance you mean, so a
|
|
1605
1927
|
* new key creates one. 1 to 128 UTF-8 bytes. Declarations without
|
|
@@ -1699,7 +2021,7 @@ export type ShellSurfacePatch = {
|
|
|
1699
2021
|
};
|
|
1700
2022
|
|
|
1701
2023
|
export type ShowActionSheetOptions = {
|
|
1702
|
-
|
|
2024
|
+
items: readonly { id: string; label: string }[];
|
|
1703
2025
|
itemColor?: string;
|
|
1704
2026
|
};
|
|
1705
2027
|
|
|
@@ -1718,7 +2040,7 @@ export type ShowToastOptions = {
|
|
|
1718
2040
|
title: string;
|
|
1719
2041
|
icon?: 'success' | 'error' | 'loading' | 'none';
|
|
1720
2042
|
image?: string;
|
|
1721
|
-
|
|
2043
|
+
durationMs?: number;
|
|
1722
2044
|
mask?: boolean;
|
|
1723
2045
|
position?: 'top' | 'center' | 'bottom';
|
|
1724
2046
|
};
|
|
@@ -1736,7 +2058,7 @@ export type Storage = {
|
|
|
1736
2058
|
* shape, exactly like a `JSON.parse` boundary; a missing key resolves
|
|
1737
2059
|
* `undefined`, which a stored `null` never does.
|
|
1738
2060
|
*/
|
|
1739
|
-
get<T = unknown>(key: string): Promise<T | undefined>;
|
|
2061
|
+
get<T = unknown>(key: string, decode?: (value: unknown) => T): Promise<T | undefined>;
|
|
1740
2062
|
set(key: string, value: unknown): Promise<void>;
|
|
1741
2063
|
/**
|
|
1742
2064
|
* Resolves whether an exact key exists, without reading its value. Prefer
|
|
@@ -1761,7 +2083,7 @@ export type StorageInfo = {
|
|
|
1761
2083
|
export type StreamSourceOptions = {
|
|
1762
2084
|
provider: string;
|
|
1763
2085
|
isLive: boolean;
|
|
1764
|
-
|
|
2086
|
+
durationSeconds?: number;
|
|
1765
2087
|
params?: Record<string, unknown>;
|
|
1766
2088
|
};
|
|
1767
2089
|
|
|
@@ -1781,19 +2103,16 @@ export type SurfaceApi = {
|
|
|
1781
2103
|
*/
|
|
1782
2104
|
openDeclared(id: string): Promise<DeclaredSurface>;
|
|
1783
2105
|
/**
|
|
1784
|
-
*
|
|
1785
|
-
*
|
|
1786
|
-
* to reuse or close them. A surface opened without a `key` is not
|
|
1787
|
-
* addressable — nothing else refers to a runtime-assigned id, so nothing
|
|
1788
|
-
* registers it. A key you chose wins over an id it happens to spell.
|
|
2106
|
+
* Find a live surface by the explicit key passed when opening it.
|
|
2107
|
+
* Runtime-assigned ids are not lookup keys.
|
|
1789
2108
|
*/
|
|
1790
|
-
|
|
2109
|
+
getByKey(key: string): AnySurface | undefined;
|
|
1791
2110
|
/**
|
|
1792
2111
|
* Observe this presentation's viewport. Invoked immediately with the
|
|
1793
2112
|
* current context, then again whenever it changes. Returns an unsubscribe
|
|
1794
2113
|
* function.
|
|
1795
2114
|
*/
|
|
1796
|
-
|
|
2115
|
+
watchContext(handler: (context: SurfaceContext) => void): () => void;
|
|
1797
2116
|
};
|
|
1798
2117
|
|
|
1799
2118
|
/** What every surface handle carries, whatever opened it. */
|
|
@@ -1842,12 +2161,15 @@ export type SurfaceClosedEvent = {
|
|
|
1842
2161
|
};
|
|
1843
2162
|
|
|
1844
2163
|
/**
|
|
1845
|
-
* The current surface viewport context, delivered to `lx.surface.
|
|
1846
|
-
* so an lxapp can
|
|
2164
|
+
* The current surface viewport context, delivered to `lx.surface.watchContext()`
|
|
2165
|
+
* so an lxapp can choose a compact or workspace View. Column count and
|
|
2166
|
+
* spacing inside `regular` use CSS or the raw `width` / `height`.
|
|
1847
2167
|
*/
|
|
1848
2168
|
export type SurfaceContext = {
|
|
1849
|
-
/**
|
|
1850
|
-
|
|
2169
|
+
/** Whether the host layout currently offers a docked aside. */
|
|
2170
|
+
aside: boolean;
|
|
2171
|
+
/** compact (<600) / regular (≥600). Shell medium/expanded are not distinct here. */
|
|
2172
|
+
sizeClass: 'compact' | 'regular';
|
|
1851
2173
|
/** Actual surface viewport width in logical pixels. */
|
|
1852
2174
|
width: number;
|
|
1853
2175
|
/** Actual surface viewport height in logical pixels. */
|
|
@@ -1994,34 +2316,31 @@ export type TabBarItemPatch = {
|
|
|
1994
2316
|
redDot?: boolean;
|
|
1995
2317
|
};
|
|
1996
2318
|
|
|
2319
|
+
/**
|
|
2320
|
+
* Patch for `lx.tabBar.update()`. Items, badges, red dots, and
|
|
2321
|
+
* visibility only — a `style` field is rejected. Colors stay in
|
|
2322
|
+
* static `lxapp.json` `tabBar.style`. `backgroundColor` is
|
|
2323
|
+
* mobile-only; the desktop sidebar follows the host
|
|
2324
|
+
* `lingxia.yaml` theme.
|
|
2325
|
+
*/
|
|
1997
2326
|
export type TabBarPatch = {
|
|
1998
2327
|
visibility?: TabBarVisibilityPreference;
|
|
1999
|
-
style?: TabBarStylePatch | null;
|
|
2000
2328
|
items?: readonly TabBarItemPatch[];
|
|
2001
2329
|
};
|
|
2002
2330
|
|
|
2003
|
-
export type TabBarStylePatch = {
|
|
2004
|
-
foregroundColor?: string | null;
|
|
2005
|
-
selectedForegroundColor?: string | null;
|
|
2006
|
-
};
|
|
2007
|
-
|
|
2008
2331
|
export type TabBarVisibilityPreference = 'auto' | 'visible' | 'hidden';
|
|
2009
2332
|
|
|
2010
2333
|
/** External content in the in-app browser. */
|
|
2011
|
-
export type TabSurface = SurfaceBase & {
|
|
2334
|
+
export type TabSurface = (SurfaceBase & {
|
|
2012
2335
|
readonly kind: 'tab';
|
|
2013
2336
|
readonly realized: 'tab' | 'aside';
|
|
2014
|
-
|
|
2015
|
-
* `tab` when this handle owns exactly the tab it opened, and `close()` /
|
|
2016
|
-
* `activate()` act on it. `group` when the browser chrome owns the tab
|
|
2017
|
-
* strip: the content is open, but control belongs to that chrome, so both
|
|
2018
|
-
* methods reject with `unsupported_placement`. Branch on this rather than
|
|
2019
|
-
* on the old platform-dependent `null`.
|
|
2020
|
-
*/
|
|
2021
|
-
readonly scope: 'tab' | 'group';
|
|
2022
|
-
/** Bring this tab to the front of its browser. `scope: 'group'` rejects. */
|
|
2337
|
+
readonly scope: 'tab';
|
|
2023
2338
|
activate(): Promise<void>;
|
|
2024
|
-
}
|
|
2339
|
+
}) | (Omit<SurfaceBase, 'close' | 'onClose'> & {
|
|
2340
|
+
readonly kind: 'tab';
|
|
2341
|
+
readonly realized: 'tab' | 'aside';
|
|
2342
|
+
readonly scope: 'group';
|
|
2343
|
+
});
|
|
2025
2344
|
|
|
2026
2345
|
export type TerminalApi = {
|
|
2027
2346
|
/** Saved terminal settings, revision-checked on write. */
|
|
@@ -2157,6 +2476,11 @@ export type TerminalThemeSettings = {
|
|
|
2157
2476
|
dark: string;
|
|
2158
2477
|
};
|
|
2159
2478
|
|
|
2479
|
+
export type ToastHandle = {
|
|
2480
|
+
/** Dismiss this toast only; harmless after a newer toast replaces it. */
|
|
2481
|
+
dismiss(): Promise<void>;
|
|
2482
|
+
};
|
|
2483
|
+
|
|
2160
2484
|
export type TrayApi = globalThis.TrayApi;
|
|
2161
2485
|
|
|
2162
2486
|
/**
|
|
@@ -2164,9 +2488,10 @@ export type TrayApi = globalThis.TrayApi;
|
|
|
2164
2488
|
* The tray is declared in `lingxia.yaml` (`tray:`); these update its dynamic
|
|
2165
2489
|
* content at runtime.
|
|
2166
2490
|
* **Desktop only.** Mobile platforms have no tray, so every method here is a
|
|
2167
|
-
* no-op there (it never throws) — safe to call from portable code.
|
|
2168
|
-
*
|
|
2169
|
-
*
|
|
2491
|
+
* no-op there (it never throws) — safe to call from portable code.
|
|
2492
|
+
* The tray belongs to the product, not to the lxapp that happens to be
|
|
2493
|
+
* running, so these are Control-app only: a guest lxapp calling one receives
|
|
2494
|
+
* a permission error.
|
|
2170
2495
|
*/
|
|
2171
2496
|
export type TrayMenuItem = {
|
|
2172
2497
|
label: string;
|
|
@@ -2187,7 +2512,10 @@ export type UpdateFailedInfo = UpdateReadyInfo & {
|
|
|
2187
2512
|
/**
|
|
2188
2513
|
* Callback-based updates for this lxapp's bundle. Available to every
|
|
2189
2514
|
* lxapp. To update the native host app, the Control app uses the
|
|
2190
|
-
* task-based `lx.
|
|
2515
|
+
* task-based `lx.host.checkUpdate()` API instead.
|
|
2516
|
+
* Listeners are a set: later subscriptions do not replace earlier ones.
|
|
2517
|
+
* The last pending ready/failed event is replayed to each new
|
|
2518
|
+
* subscriber until a newer event replaces it.
|
|
2191
2519
|
*/
|
|
2192
2520
|
export type UpdateManager = {
|
|
2193
2521
|
applyUpdate(): void;
|
|
@@ -2199,14 +2527,10 @@ export type UpdateManager = {
|
|
|
2199
2527
|
|
|
2200
2528
|
export type UpdateReadyInfo = {
|
|
2201
2529
|
version?: string;
|
|
2202
|
-
isForceUpdate?: boolean;
|
|
2203
2530
|
channel?: "release" | "draft" | string;
|
|
2204
2531
|
};
|
|
2205
2532
|
|
|
2206
|
-
export type UploadIteratorResult =
|
|
2207
|
-
done: boolean;
|
|
2208
|
-
value?: UploadProgressEvent;
|
|
2209
|
-
};
|
|
2533
|
+
export type UploadIteratorResult = IteratorResult<UploadProgressEvent, void>;
|
|
2210
2534
|
|
|
2211
2535
|
/**
|
|
2212
2536
|
* Upload options. The file streams from disk, so the size ceiling is
|
|
@@ -2216,12 +2540,12 @@ export type UploadIteratorResult = {
|
|
|
2216
2540
|
* - `multipart` (default) wraps the file in a `multipart/form-data`
|
|
2217
2541
|
* envelope beside the `formData` text fields — what an ordinary form
|
|
2218
2542
|
* endpoint parses. `name`, `fileName`, and `formData` describe that
|
|
2219
|
-
* envelope.
|
|
2543
|
+
* envelope. `formData`, when present, must contain at least one field.
|
|
2220
2544
|
* - `raw` sends the file bytes as the entire body. Presigned
|
|
2221
2545
|
* object-storage URLs (S3, OSS, Azure Blob) need this: a multipart
|
|
2222
2546
|
* envelope would be stored verbatim as the object's contents,
|
|
2223
|
-
* boundary lines and all. `name` and `
|
|
2224
|
-
* rather than silently dropped
|
|
2547
|
+
* boundary lines and all. `name`, `formData`, and `fileName` are
|
|
2548
|
+
* then rejected rather than silently dropped.
|
|
2225
2549
|
* @example
|
|
2226
2550
|
* ```ts
|
|
2227
2551
|
* // A presigned URL is signed for one method and one Content-Type,
|
|
@@ -2233,8 +2557,8 @@ export type UploadIteratorResult = {
|
|
|
2233
2557
|
* bodyMode: 'raw',
|
|
2234
2558
|
* mimeType: 'video/mp4',
|
|
2235
2559
|
* });
|
|
2236
|
-
* for await (const event of task) render(event.progress);
|
|
2237
|
-
* const { statusCode } = await task;
|
|
2560
|
+
* for await (const event of task.progress) render(event.progress);
|
|
2561
|
+
* const { statusCode } = await task.result;
|
|
2238
2562
|
* ```
|
|
2239
2563
|
*/
|
|
2240
2564
|
export type UploadOptions = {
|
|
@@ -2247,14 +2571,6 @@ export type UploadOptions = {
|
|
|
2247
2571
|
* A presigned URL is signed for exactly one method, usually `PUT`.
|
|
2248
2572
|
*/
|
|
2249
2573
|
method?: 'POST' | 'PUT' | 'PATCH';
|
|
2250
|
-
/**
|
|
2251
|
-
* How the file bytes are framed. Default: `multipart`.
|
|
2252
|
-
* `raw` sends them as the whole body under a `Content-Length` taken from
|
|
2253
|
-
* the file itself, which is what presigned endpoints require.
|
|
2254
|
-
*/
|
|
2255
|
-
bodyMode?: 'multipart' | 'raw';
|
|
2256
|
-
/** Name of the multipart part carrying the file. Default: `file`. Multipart only. */
|
|
2257
|
-
name?: string;
|
|
2258
2574
|
/**
|
|
2259
2575
|
* Optional request headers.
|
|
2260
2576
|
* Restricted headers such as `Referer` are ignored by the runtime.
|
|
@@ -2263,12 +2579,8 @@ export type UploadOptions = {
|
|
|
2263
2579
|
* carries the part boundary.
|
|
2264
2580
|
*/
|
|
2265
2581
|
headers?: Record<string, string>;
|
|
2266
|
-
/** Text fields sent alongside the file in the envelope. Multipart only. */
|
|
2267
|
-
formData?: Record<string, string>;
|
|
2268
2582
|
/** Request timeout in milliseconds. */
|
|
2269
|
-
|
|
2270
|
-
/** Filename announced for the file part. Defaults to the file's own name. Multipart only. */
|
|
2271
|
-
fileName?: string;
|
|
2583
|
+
timeoutMs?: number;
|
|
2272
2584
|
/**
|
|
2273
2585
|
* File MIME type. Types the file part under `multipart`; becomes the
|
|
2274
2586
|
* request `Content-Type` under `raw`, where it defaults to
|
|
@@ -2277,11 +2589,30 @@ export type UploadOptions = {
|
|
|
2277
2589
|
mimeType?: string;
|
|
2278
2590
|
/** Optional abort signal. */
|
|
2279
2591
|
signal?: AbortSignal;
|
|
2280
|
-
}
|
|
2592
|
+
} & (
|
|
2593
|
+
| {
|
|
2594
|
+
/**
|
|
2595
|
+
* How the file bytes are framed. Default: `multipart`.
|
|
2596
|
+
*/
|
|
2597
|
+
bodyMode?: 'multipart';
|
|
2598
|
+
/** Name of the multipart part carrying the file. Default: `file`. */
|
|
2599
|
+
name?: string;
|
|
2600
|
+
/** Text fields sent alongside the file. Must be non-empty when set. */
|
|
2601
|
+
formData?: Record<string, string>;
|
|
2602
|
+
/** Filename announced for the file part. Defaults to the file's own name. */
|
|
2603
|
+
fileName?: string;
|
|
2604
|
+
}
|
|
2605
|
+
| {
|
|
2606
|
+
/** Send the file bytes as the whole body. Multipart fields are rejected. */
|
|
2607
|
+
bodyMode: 'raw';
|
|
2608
|
+
name?: never;
|
|
2609
|
+
formData?: never;
|
|
2610
|
+
fileName?: never;
|
|
2611
|
+
}
|
|
2612
|
+
);
|
|
2281
2613
|
|
|
2282
2614
|
export type UploadProgressEvent = {
|
|
2283
|
-
|
|
2284
|
-
kind: 'progress' | 'canceled' | 'completed';
|
|
2615
|
+
kind: 'progress' | 'canceled';
|
|
2285
2616
|
/** Bytes handed to the socket so far, envelope included under `multipart`. */
|
|
2286
2617
|
uploadedBytes?: number;
|
|
2287
2618
|
/**
|
|
@@ -2292,8 +2623,12 @@ export type UploadProgressEvent = {
|
|
|
2292
2623
|
totalBytes?: number;
|
|
2293
2624
|
/** `uploadedBytes / totalBytes`, absent while the total is unknown or zero. */
|
|
2294
2625
|
progress?: number;
|
|
2295
|
-
|
|
2296
|
-
|
|
2626
|
+
} | {
|
|
2627
|
+
kind: 'completed';
|
|
2628
|
+
uploadedBytes?: number;
|
|
2629
|
+
totalBytes?: number;
|
|
2630
|
+
progress?: number;
|
|
2631
|
+
result: UploadResult;
|
|
2297
2632
|
};
|
|
2298
2633
|
|
|
2299
2634
|
export type UploadResult = {
|
|
@@ -2303,15 +2638,7 @@ export type UploadResult = {
|
|
|
2303
2638
|
data: string;
|
|
2304
2639
|
};
|
|
2305
2640
|
|
|
2306
|
-
export type UploadTask =
|
|
2307
|
-
next(): Promise<UploadIteratorResult>;
|
|
2308
|
-
/** Stops iteration only. Does not cancel the underlying upload task. */
|
|
2309
|
-
return(): Promise<UploadIteratorResult>;
|
|
2310
|
-
catch<TResult = never>(onrejected?: ((reason: unknown) => TResult | PromiseLike<TResult>) | null): Promise<UploadResult | TResult>;
|
|
2311
|
-
finally(onfinally?: (() => void) | null): Promise<UploadResult>;
|
|
2312
|
-
cancel(): Promise<void>;
|
|
2313
|
-
wait(): Promise<UploadResult>;
|
|
2314
|
-
};
|
|
2641
|
+
export type UploadTask = CancelableTask<UploadResult, UploadProgressEvent>;
|
|
2315
2642
|
|
|
2316
2643
|
export type VideoCompressQuality = 'low' | 'medium' | 'high';
|
|
2317
2644
|
|
|
@@ -2319,7 +2646,7 @@ export type VideoContext = {
|
|
|
2319
2646
|
play(): void;
|
|
2320
2647
|
pause(): void;
|
|
2321
2648
|
stop(): void;
|
|
2322
|
-
seek(
|
|
2649
|
+
seek(positionSeconds: number): void;
|
|
2323
2650
|
requestFullScreen(): void;
|
|
2324
2651
|
exitFullScreen(): void;
|
|
2325
2652
|
setStreamSource(options: StreamSourceOptions): void;
|
|
@@ -2436,17 +2763,17 @@ export type WindowsTerminalInlineImageStatus = {
|
|
|
2436
2763
|
/**
|
|
2437
2764
|
* Host app identity. Everything here is fixed for the life of the process;
|
|
2438
2765
|
* the language the app renders in is not, and lives on
|
|
2439
|
-
* `lx.
|
|
2766
|
+
* `lx.host.displayLanguage`.
|
|
2440
2767
|
*/
|
|
2441
2768
|
export interface AppBaseInfo {
|
|
2442
2769
|
/**
|
|
2443
2770
|
* Platform family: `"iOS"` / `"macOS"` / `"Android"` / `"Windows"` /
|
|
2444
|
-
* `"Harmony"`. Matches the View-side `
|
|
2771
|
+
* `"Harmony"`. Matches the View-side `useLxHost().os` value.
|
|
2445
2772
|
*/
|
|
2446
2773
|
os: HostOs;
|
|
2447
2774
|
productName: string;
|
|
2448
2775
|
version: string;
|
|
2449
|
-
|
|
2776
|
+
sdkVersion: string;
|
|
2450
2777
|
}
|
|
2451
2778
|
|
|
2452
2779
|
/** Device info APIs. */
|
|
@@ -2468,6 +2795,23 @@ export interface FileStats {
|
|
|
2468
2795
|
createTime?: number;
|
|
2469
2796
|
}
|
|
2470
2797
|
|
|
2798
|
+
export interface HostServiceEnvState {
|
|
2799
|
+
buildEnv: HostAppEnv;
|
|
2800
|
+
/** Environment this process is running; unchanged until the app restarts. */
|
|
2801
|
+
serviceEnv: HostAppEnv;
|
|
2802
|
+
/** Environment that will be used after closing and reopening the app. */
|
|
2803
|
+
nextLaunchEnv: HostAppEnv;
|
|
2804
|
+
available: HostAppEnv[];
|
|
2805
|
+
canToggle: boolean;
|
|
2806
|
+
}
|
|
2807
|
+
|
|
2808
|
+
export interface HostServiceEnvSwitchResult {
|
|
2809
|
+
state: HostServiceEnvState;
|
|
2810
|
+
exitRequested: boolean;
|
|
2811
|
+
/** If present, the environment was saved; close and reopen the app manually. */
|
|
2812
|
+
exitError?: string;
|
|
2813
|
+
}
|
|
2814
|
+
|
|
2471
2815
|
export interface ImageInfo {
|
|
2472
2816
|
width: number;
|
|
2473
2817
|
height: number;
|
|
@@ -2516,9 +2860,9 @@ export interface SystemSettingInfo {
|
|
|
2516
2860
|
/** Wi-Fi APIs. */
|
|
2517
2861
|
export interface WifiInfo {
|
|
2518
2862
|
/** Service Set Identifier (network name) */
|
|
2519
|
-
|
|
2863
|
+
ssid: string;
|
|
2520
2864
|
/** Basic Service Set Identifier (MAC address) */
|
|
2521
|
-
|
|
2865
|
+
bssid?: string;
|
|
2522
2866
|
/** Whether the network is secure (requires password) */
|
|
2523
2867
|
secure: boolean;
|
|
2524
2868
|
/** Signal strength (0-100, higher is better) */
|
|
@@ -2527,16 +2871,14 @@ export interface WifiInfo {
|
|
|
2527
2871
|
frequency?: number;
|
|
2528
2872
|
}
|
|
2529
2873
|
|
|
2530
|
-
export
|
|
2531
|
-
private constructor();
|
|
2874
|
+
export interface DirEntry {
|
|
2532
2875
|
readonly name: string;
|
|
2533
2876
|
readonly isFile: boolean;
|
|
2534
2877
|
readonly isDirectory: boolean;
|
|
2535
2878
|
readonly isSymlink: boolean;
|
|
2536
2879
|
}
|
|
2537
2880
|
|
|
2538
|
-
export
|
|
2539
|
-
private constructor();
|
|
2881
|
+
export interface LxFile {
|
|
2540
2882
|
/** The path supplied to `lx.fs.file`. */
|
|
2541
2883
|
readonly path: string;
|
|
2542
2884
|
/** Read the complete file as strict UTF-8 text. */
|
|
@@ -2560,6 +2902,57 @@ export declare class LxFile {
|
|
|
2560
2902
|
stat(): Promise<FileStats>;
|
|
2561
2903
|
}
|
|
2562
2904
|
|
|
2905
|
+
declare global {
|
|
2906
|
+
interface ClipboardApi {
|
|
2907
|
+
/**
|
|
2908
|
+
* Replace the clipboard with Unicode text.
|
|
2909
|
+
* Empty string is a valid payload (it is not `clear()`). The runtime does not
|
|
2910
|
+
* present a toast — call `lx.showToast` if the product wants one. Rejects
|
|
2911
|
+
* `E_INVALID_ARG` above 1 MiB.
|
|
2912
|
+
*/
|
|
2913
|
+
writeText(text: string): Promise<void>;
|
|
2914
|
+
/**
|
|
2915
|
+
* Read Unicode text.
|
|
2916
|
+
* Resolves `{ status: 'canceled' }` only when the user dismisses the OS paste
|
|
2917
|
+
* prompt (iOS 16+, macOS 15.4+). No text representation (empty clipboard, or
|
|
2918
|
+
* image-only) resolves `{ status: 'empty' }`. A copied empty
|
|
2919
|
+
* string resolves `{ status: 'ok', text: '' }`.
|
|
2920
|
+
* Rejects `E_PERMISSION_DENIED` when the host denies clipboard access
|
|
2921
|
+
* outright: a macOS "never allow" setting, or HarmonyOS without
|
|
2922
|
+
* `ohos.permission.READ_PASTEBOARD`. Android denies a read while the app has
|
|
2923
|
+
* no window focus and reports it as an empty clipboard, so read in response
|
|
2924
|
+
* to a user action.
|
|
2925
|
+
*/
|
|
2926
|
+
readText(): Promise<ClipboardTextResult>;
|
|
2927
|
+
/**
|
|
2928
|
+
* Replace the clipboard with a typed item.
|
|
2929
|
+
* Rejects `E_INVALID_ARG` for text above 1 MiB or an image file that does not
|
|
2930
|
+
* decode.
|
|
2931
|
+
*/
|
|
2932
|
+
write(item: ClipboardWriteItem): Promise<void>;
|
|
2933
|
+
/**
|
|
2934
|
+
* Read the clipboard.
|
|
2935
|
+
* Omit `type` to receive every representation this host can surface.
|
|
2936
|
+
* Pass `type` to request one; if that representation is absent, the
|
|
2937
|
+
* completed result is `{ status: 'empty' }` rather than a mismatch error.
|
|
2938
|
+
* Images arrive as a temporary PNG under `lx://temp`. Dismissal and
|
|
2939
|
+
* permission behave as in `readText`.
|
|
2940
|
+
*/
|
|
2941
|
+
read(options?: ClipboardReadOptions): Promise<ClipboardReadResult>;
|
|
2942
|
+
/** Remove every representation. */
|
|
2943
|
+
clear(): Promise<void>;
|
|
2944
|
+
/**
|
|
2945
|
+
* Which representations are present, without reading payloads. An empty
|
|
2946
|
+
* array is an empty clipboard; representations this runtime cannot
|
|
2947
|
+
* round-trip (HTML, files) are omitted.
|
|
2948
|
+
* Never shows the OS paste prompt and needs no permission on any host, so it
|
|
2949
|
+
* is the way to decide whether to offer "Paste". The answer is a hint —
|
|
2950
|
+
* content may change before you read it.
|
|
2951
|
+
*/
|
|
2952
|
+
types(): Promise<ClipboardType[]>;
|
|
2953
|
+
}
|
|
2954
|
+
}
|
|
2955
|
+
|
|
2563
2956
|
declare global {
|
|
2564
2957
|
interface FileSystemApi {
|
|
2565
2958
|
/**
|
|
@@ -2567,45 +2960,63 @@ declare global {
|
|
|
2567
2960
|
* Relative paths resolve under `lx.env.USER_DATA_PATH`. Creating a reference
|
|
2568
2961
|
* does not require the path to exist.
|
|
2569
2962
|
*/
|
|
2570
|
-
file(path:
|
|
2963
|
+
file(path: ManagedPath): LxFile;
|
|
2571
2964
|
/** Test whether a managed path currently exists. */
|
|
2572
|
-
exists(path:
|
|
2965
|
+
exists(path: ManagedPath): Promise<boolean>;
|
|
2573
2966
|
/** Read metadata for a managed path. */
|
|
2574
|
-
stat(path:
|
|
2967
|
+
stat(path: ManagedPath): Promise<FileStats>;
|
|
2575
2968
|
/** The direct children of a managed directory. */
|
|
2576
|
-
readDir(path:
|
|
2969
|
+
readDir(path: ManagedPath): Promise<DirEntry[]>;
|
|
2577
2970
|
/** Create a managed directory. */
|
|
2578
|
-
mkdir(path:
|
|
2971
|
+
mkdir(path: ManagedPath, options?: FsMkdirOptions): Promise<void>;
|
|
2579
2972
|
/** Write UTF-8 text or bytes to a managed file. */
|
|
2580
|
-
write(path:
|
|
2973
|
+
write(path: ManagedPath, data: string, options?: FsWriteOptions): Promise<void>;
|
|
2581
2974
|
/** Copy a managed file. */
|
|
2582
|
-
copy(source:
|
|
2975
|
+
copy(source: ManagedPath, destination: ManagedPath, options?: FsCopyOptions): Promise<void>;
|
|
2583
2976
|
/** Rename or move a managed file or directory. */
|
|
2584
|
-
rename(source:
|
|
2977
|
+
rename(source: ManagedPath, destination: ManagedPath, options?: FsRenameOptions): Promise<void>;
|
|
2585
2978
|
/** Remove a managed file or directory. */
|
|
2586
|
-
remove(path:
|
|
2979
|
+
remove(path: ManagedPath, options?: FsRemoveOptions): Promise<void>;
|
|
2587
2980
|
}
|
|
2588
2981
|
}
|
|
2589
2982
|
|
|
2590
2983
|
declare global {
|
|
2591
2984
|
interface HostAppApi {
|
|
2592
2985
|
/**
|
|
2593
|
-
* `lx.
|
|
2986
|
+
* `lx.host.screenshot(options?)` — capture the host app's window as a PNG.
|
|
2594
2987
|
* App-level semantics, one level above any page/WebView capture: the image
|
|
2595
2988
|
* is what the user sees of the whole app — host-drawn navigation chrome,
|
|
2596
2989
|
* native overlays, and every composited WebView, not just this lxapp's web
|
|
2597
2990
|
* content. Because that view can include other lxapps' UI, the API is
|
|
2598
|
-
* restricted to the Control app, like the other host-level APIs on `lx.
|
|
2991
|
+
* restricted to the Control app, like the other host-level APIs on `lx.host`.
|
|
2599
2992
|
*/
|
|
2600
2993
|
screenshot(options?: AppScreenshotOptions): Promise<AppScreenshotResult>;
|
|
2994
|
+
/** Query the running and next-launch service environments. Control app only. */
|
|
2995
|
+
getServiceEnv(): HostServiceEnvState;
|
|
2996
|
+
/**
|
|
2997
|
+
* Save the other service environment for next launch and request exit.
|
|
2998
|
+
* A dev build cannot switch. Control app only. Save failures throw before exit.
|
|
2999
|
+
* If exitRequested is false, ask the user to close and reopen the app manually.
|
|
3000
|
+
* Retrying before restart keeps the same target environment.
|
|
3001
|
+
*/
|
|
3002
|
+
toggleServiceEnv(): HostServiceEnvSwitchResult;
|
|
2601
3003
|
/**
|
|
2602
|
-
*
|
|
2603
|
-
* This host-level capability is restricted to the Control app.
|
|
2604
|
-
*
|
|
2605
|
-
* `
|
|
2606
|
-
*
|
|
3004
|
+
* Query whether the host app has an update.
|
|
3005
|
+
* This host-level capability is restricted to the Control app. A successful
|
|
3006
|
+
* check does **not** take over the built-in auto-flow — that is
|
|
3007
|
+
* `claimCustomUpdate()` or `update.apply()`. Permission denial or a failed
|
|
3008
|
+
* check claims nothing. Incompatible updates are hidden as
|
|
3009
|
+
* `hasUpdate: false`. Store-channel hosts still surface a newer feed version;
|
|
3010
|
+
* `apply()` opens the store listing instead of downloading.
|
|
2607
3011
|
*/
|
|
2608
3012
|
checkUpdate(): Promise<HostAppUpdateCheckResult>;
|
|
3013
|
+
/**
|
|
3014
|
+
* Claim the process-lifetime custom host-update flow.
|
|
3015
|
+
* Irreversible: the built-in auto-flow will not prompt or download again,
|
|
3016
|
+
* including after the calling page unloads. Does not cancel an already-started
|
|
3017
|
+
* update task. Later failed checks do not undo a claim already made.
|
|
3018
|
+
*/
|
|
3019
|
+
claimCustomUpdate(): void;
|
|
2609
3020
|
readonly env: HostAppEnv;
|
|
2610
3021
|
/**
|
|
2611
3022
|
* Read the host app's identity: OS, product name, product version, and SDK
|
|
@@ -2621,30 +3032,32 @@ declare global {
|
|
|
2621
3032
|
*/
|
|
2622
3033
|
exit(): void;
|
|
2623
3034
|
/**
|
|
2624
|
-
*
|
|
2625
|
-
*
|
|
2626
|
-
*
|
|
2627
|
-
*
|
|
2628
|
-
*
|
|
2629
|
-
|
|
2630
|
-
|
|
3035
|
+
* Mark the product in system chrome, for example with an unread count.
|
|
3036
|
+
* One call, because "where the count goes" is the platform's answer, not the
|
|
3037
|
+
* caller's: `auto` paints every product-owned surface this platform has — the
|
|
3038
|
+
* dock and the menu-bar item on macOS, the taskbar and the notification-area
|
|
3039
|
+
* item on Windows, the home-screen icon on iOS and HarmonyOS. Name a
|
|
3040
|
+
* `surface` only when one of them is the point.
|
|
3041
|
+
* It is the product's chrome, not the calling lxapp's, so it is Control app
|
|
3042
|
+
* only. Null or an empty string clears it.
|
|
3043
|
+
* Returns whether anything was actually painted. A platform with no such
|
|
3044
|
+
* chrome is a no-op that returns `false` rather than an error — portable code
|
|
3045
|
+
* can call this unconditionally.
|
|
3046
|
+
*/
|
|
3047
|
+
setBadge(value: string | number | null, options?: SetBadgeOptions): Promise<boolean>;
|
|
2631
3048
|
}
|
|
2632
3049
|
}
|
|
2633
3050
|
|
|
2634
3051
|
declare global {
|
|
2635
3052
|
interface Lx {
|
|
2636
|
-
readonly
|
|
2637
|
-
/**
|
|
2638
|
-
*
|
|
2639
|
-
*
|
|
2640
|
-
*
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
* `lx.surface.onContext` instead of polling. The answer is per runtime context:
|
|
2645
|
-
* a context that does not expose an API reports false for it.
|
|
2646
|
-
*/
|
|
2647
|
-
supports(query: LxCapabilityQuery): boolean;
|
|
3053
|
+
readonly host: HostAppApi;
|
|
3054
|
+
/**
|
|
3055
|
+
* Frozen feature support, not permission or current layout. Unknown strings
|
|
3056
|
+
* return false; non-strings throw TypeError. Required features also need an
|
|
3057
|
+
* appropriate lxapp.json minRuntime.
|
|
3058
|
+
*/
|
|
3059
|
+
supports(feature: LxFeature): boolean;
|
|
3060
|
+
readonly clipboard: ClipboardApi;
|
|
2648
3061
|
/** Vibrate briefly, where the device has a vibrator. */
|
|
2649
3062
|
vibrateShort(): boolean;
|
|
2650
3063
|
/** Vibrate for a longer pulse, where the device has a vibrator. */
|
|
@@ -2691,8 +3104,8 @@ declare global {
|
|
|
2691
3104
|
* `method: 'PUT'` with `bodyMode: 'raw'` to send the file bytes as the whole
|
|
2692
3105
|
* body instead, which is what presigned object-storage URLs expect.
|
|
2693
3106
|
* Returns the task handle synchronously, before the transfer starts, so
|
|
2694
|
-
* progress and cancellation can be wired up without racing it:
|
|
2695
|
-
*
|
|
3107
|
+
* progress and cancellation can be wired up without racing it: `result` settles
|
|
3108
|
+
* once, `progress` streams to one consumer, and `cancel()` aborts.
|
|
2696
3109
|
*/
|
|
2697
3110
|
uploadFile(options: UploadOptions): UploadTask;
|
|
2698
3111
|
/**
|
|
@@ -2701,17 +3114,20 @@ declare global {
|
|
|
2701
3114
|
* `mode: "auto"`.
|
|
2702
3115
|
*/
|
|
2703
3116
|
openFile(options: OpenFileOptions): Promise<void>;
|
|
3117
|
+
/** Pick one file. A successful selection returns one opaque URI. */
|
|
3118
|
+
pickFile(options?: PickFileOptions): Promise<PickFileResult>;
|
|
3119
|
+
/** Pick one or more files. Dismissal is a normal outcome. */
|
|
3120
|
+
pickFiles(options?: PickFileOptions): Promise<ChooseFileResult>;
|
|
2704
3121
|
/**
|
|
2705
|
-
*
|
|
2706
|
-
*
|
|
2707
|
-
* completed selection resolves `{ canceled: false, paths }` with at least one
|
|
3122
|
+
* Resolves `{ status: 'canceled' }` only when the user dismisses the picker. A
|
|
3123
|
+
* completed selection resolves `{ status: 'ok', paths }` with at least one
|
|
2708
3124
|
* path. Rejects when the picker fails or returns an invalid payload.
|
|
2709
3125
|
*/
|
|
2710
|
-
chooseFile(options
|
|
3126
|
+
chooseFile(options: never): Promise<never>;
|
|
2711
3127
|
/**
|
|
2712
3128
|
* Opens a directory picker.
|
|
2713
|
-
* Resolves `{
|
|
2714
|
-
* completed selection resolves `{
|
|
3129
|
+
* Resolves `{ status: 'canceled' }` only when the user dismisses the picker. A
|
|
3130
|
+
* completed selection resolves `{ status: 'ok', path }`. Rejects when the
|
|
2715
3131
|
* picker fails or returns an invalid payload.
|
|
2716
3132
|
*/
|
|
2717
3133
|
chooseDirectory(options?: ChooseDirectoryOptions): Promise<ChooseDirectoryResult>;
|
|
@@ -2730,8 +3146,8 @@ declare global {
|
|
|
2730
3146
|
compressImage(options: CompressImageOptions): Promise<CompressImageResult>;
|
|
2731
3147
|
/**
|
|
2732
3148
|
* Opens the media picker or camera.
|
|
2733
|
-
* Resolves `{
|
|
2734
|
-
* completed selection resolves `{
|
|
3149
|
+
* Resolves `{ status: 'canceled' }` only when the user dismisses the picker. A
|
|
3150
|
+
* completed selection resolves `{ status: 'ok', entries }` with at least one
|
|
2735
3151
|
* entry. Rejects when capture or selection fails, or the host returns an invalid
|
|
2736
3152
|
* payload.
|
|
2737
3153
|
*/
|
|
@@ -2739,10 +3155,8 @@ declare global {
|
|
|
2739
3155
|
/**
|
|
2740
3156
|
* Synchronously returns a JS handle so listeners can be attached before the
|
|
2741
3157
|
* first event fires:
|
|
2742
|
-
* - `presented`:
|
|
2743
|
-
*
|
|
2744
|
-
* once `completed` settles, so consumers can safely ignore it (it never
|
|
2745
|
-
* rejects).
|
|
3158
|
+
* - `presented`: resolves `{ status: 'presented' }` only after the first
|
|
3159
|
+
* frame; otherwise `{ status: 'notPresented', reason }`. Never rejects.
|
|
2746
3160
|
* - `current`: `{ index, source }` snapshot of the item on screen, updated
|
|
2747
3161
|
* live as the user swipes / the session auto-advances.
|
|
2748
3162
|
* - `onChange(listener)`: fires `{ index, source }` for every item change
|
|
@@ -2760,8 +3174,8 @@ declare global {
|
|
|
2760
3174
|
saveVideoToPhotosAlbum(options: SaveMediaOptions): Promise<void>;
|
|
2761
3175
|
/**
|
|
2762
3176
|
* Opens the scanner.
|
|
2763
|
-
* Resolves `{
|
|
2764
|
-
* completed scan resolves `{
|
|
3177
|
+
* Resolves `{ status: 'canceled' }` only when the user dismisses the scanner. A
|
|
3178
|
+
* completed scan resolves `{ status: 'ok', scanResult, scanType }`. Rejects
|
|
2765
3179
|
* when scanning fails or the host returns an invalid payload.
|
|
2766
3180
|
*/
|
|
2767
3181
|
scanCode(options?: ScanCodeOptions): Promise<ScanCodeResult>;
|
|
@@ -2811,15 +3225,18 @@ declare global {
|
|
|
2811
3225
|
getSystemSetting(): SystemSettingInfo;
|
|
2812
3226
|
/**
|
|
2813
3227
|
* Shows a list of actions.
|
|
2814
|
-
* Resolves `{
|
|
2815
|
-
* points into `options.itemList`. Resolves `{ canceled: true }` only when the
|
|
3228
|
+
* Resolves `{ status: 'ok', id }` when the user selects an item; `id` identifies the selected item. Resolves `{ status: 'canceled' }` only when the
|
|
2816
3229
|
* user dismisses the sheet. Rejects when presentation fails or the host returns
|
|
2817
3230
|
* an invalid selection.
|
|
2818
3231
|
*/
|
|
2819
3232
|
showActionSheet(options: ShowActionSheetOptions): Promise<ActionSheetResult>;
|
|
3233
|
+
/** Acknowledgement-only dialog. Resolves when the user dismisses it. */
|
|
3234
|
+
alert(options: AlertOptions): Promise<void>;
|
|
3235
|
+
/** Ask a yes/no question. Dismissal resolves false; presentation failure rejects. */
|
|
3236
|
+
confirm(options: ConfirmOptions): Promise<boolean>;
|
|
2820
3237
|
/**
|
|
2821
3238
|
* Shows a confirmation modal.
|
|
2822
|
-
* Resolves `{
|
|
3239
|
+
* Resolves `{ status: 'ok' }` when the user confirms and `{ status: 'canceled' }`
|
|
2823
3240
|
* only when the user dismisses or cancels the modal. Rejects when presentation
|
|
2824
3241
|
* fails or the host returns an invalid payload.
|
|
2825
3242
|
*/
|
|
@@ -2876,15 +3293,19 @@ declare global {
|
|
|
2876
3293
|
reLaunch(options: ReLaunchOptions): Promise<void>;
|
|
2877
3294
|
readonly shell: ShellApi;
|
|
2878
3295
|
readonly tabBar: TabBarApi;
|
|
2879
|
-
/**
|
|
2880
|
-
|
|
2881
|
-
|
|
3296
|
+
/**
|
|
3297
|
+
* Presents a toast and resolves a handle once the host accepted it. The handle
|
|
3298
|
+
* dismisses only this toast, never a newer one — including a newer one posted
|
|
3299
|
+
* by another lxapp onto a host's shared overlay.
|
|
3300
|
+
*/
|
|
3301
|
+
showToast(options: ShowToastOptions): Promise<ToastHandle>;
|
|
3302
|
+
/** Hides whichever toast is showing. */
|
|
2882
3303
|
hideToast(): Promise<void>;
|
|
2883
3304
|
readonly tray: TrayApi;
|
|
2884
3305
|
/**
|
|
2885
3306
|
* Return the callback-based update manager for this lxapp's bundle. This is
|
|
2886
3307
|
* available to every lxapp and is distinct from the Control-app-only
|
|
2887
|
-
* `lx.
|
|
3308
|
+
* `lx.host.checkUpdate()`, which updates the native host app.
|
|
2888
3309
|
*/
|
|
2889
3310
|
getUpdateManager(): UpdateManager;
|
|
2890
3311
|
}
|
|
@@ -2978,36 +3399,37 @@ declare global {
|
|
|
2978
3399
|
* `lingxia.yaml`, opened with the declaration's own presentation.
|
|
2979
3400
|
*/
|
|
2980
3401
|
openDeclared(id: string): Promise<DeclaredSurface>;
|
|
3402
|
+
/** Find a live surface by its explicit caller-owned key. Runtime ids are not keys. */
|
|
3403
|
+
getByKey(key: string): AnySurface | undefined;
|
|
2981
3404
|
/**
|
|
2982
|
-
* `lx.surface.
|
|
2983
|
-
* **with a `key`**, so no caller has to cache one in order to reuse or close
|
|
2984
|
-
* it. An unkeyed surface is not addressable: nothing registers it, because
|
|
2985
|
-
* holding one for the session costs its closures and its message port and
|
|
2986
|
-
* nobody can look up a uuid they never chose.
|
|
2987
|
-
* A `key` you chose wins over a runtime-assigned `id`, so a key that happens
|
|
2988
|
-
* to spell another surface's id still finds yours.
|
|
2989
|
-
*/
|
|
2990
|
-
get(keyOrId: string): AnySurface | undefined;
|
|
2991
|
-
/**
|
|
2992
|
-
* `lx.surface.onContext(handler)` — register a JS callback (scoped to this
|
|
3405
|
+
* `lx.surface.watchContext(handler)` — register a JS callback (scoped to this
|
|
2993
3406
|
* lxapp's JS context), invoke it immediately, then again whenever that
|
|
2994
|
-
* presentation's
|
|
3407
|
+
* presentation's viewport or host docking availability changes. Returns an unsubscribe fn.
|
|
2995
3408
|
*/
|
|
2996
|
-
|
|
3409
|
+
watchContext(handler: (context: SurfaceContext) => void): () => void;
|
|
2997
3410
|
}
|
|
2998
3411
|
}
|
|
2999
3412
|
|
|
3000
3413
|
declare global {
|
|
3001
3414
|
interface TabBarApi {
|
|
3002
|
-
/**
|
|
3415
|
+
/**
|
|
3416
|
+
* Patch this lxapp's tab bar; unset fields stay as they are.
|
|
3417
|
+
* Items, badges, red dots, and visibility only. A `style` field is
|
|
3418
|
+
* rejected — colors stay in static `lxapp.json` `tabBar.style`.
|
|
3419
|
+
* `tabBar.style.backgroundColor` is mobile-only: it paints the bar on
|
|
3420
|
+
* iOS / Android / Harmony. On macOS / Windows the sidebar follows the
|
|
3421
|
+
* host `lingxia.yaml` theme (`windowBackgroundColor`) instead, so a
|
|
3422
|
+
* `#FFFFFF` fill cannot paint a card on the sidebar. Other style keys
|
|
3423
|
+
* (`foregroundColor`, `selectedForegroundColor`, `dividerColor`) may
|
|
3424
|
+
* tint items while the desktop host is light; a dark host uses the
|
|
3425
|
+
* shell theme for every key.
|
|
3426
|
+
*/
|
|
3003
3427
|
update(patch: TabBarPatch): Promise<void>;
|
|
3004
3428
|
}
|
|
3005
3429
|
}
|
|
3006
3430
|
|
|
3007
3431
|
declare global {
|
|
3008
3432
|
interface TrayApi {
|
|
3009
|
-
/** lx.tray.setBadge(value) — the menu-bar / system-tray badge. Null/empty clears it. */
|
|
3010
|
-
setBadge(value: string | number | null): void;
|
|
3011
3433
|
/** lx.tray.setIcon(icon) — replace the tray icon (a resource path). */
|
|
3012
3434
|
setIcon(icon: string): void;
|
|
3013
3435
|
/** lx.tray.setTitle(text) — text shown beside the icon (macOS). Empty clears it. */
|
|
@@ -3033,3 +3455,6 @@ declare global {
|
|
|
3033
3455
|
}
|
|
3034
3456
|
|
|
3035
3457
|
export {};
|
|
3458
|
+
|
|
3459
|
+
/** Feature contracts generated from the runtime registry. */
|
|
3460
|
+
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';
|