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