-
Notifications
You must be signed in to change notification settings - Fork 9
/
OnDeviceComponent.ts
431 lines (334 loc) · 14.5 KB
/
OnDeviceComponent.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
import type { Socket } from 'net';
export enum RequestType {
callFunc = 'callFunc',
createDirectory = 'createDirectory',
createChild = 'createChild',
deleteFile = 'deleteFile',
deleteNodeReferences = 'deleteNodeReferences',
deleteRegistrySections = 'deleteRegistrySections',
deleteEntireRegistry = 'deleteEntireRegistry',
disableScreenSaver = 'disableScreenSaver',
findNodesAtLocation = 'findNodesAtLocation',
focusNode = 'focusNode',
getAllCount = 'getAllCount',
getApplicationStartTime = 'getApplicationStartTime',
getDirectoryListing = 'getDirectoryListing',
getFocusedNode = 'getFocusedNode',
getNodesInfo = 'getNodesInfo',
getNodesWithProperties = 'getNodesWithProperties',
getRootsCount = 'getRootsCount',
getServerHost = 'getServerHost',
getValue = 'getValue',
getValues = 'getValues',
getVolumeList = 'getVolumeList',
hasFocus = 'hasFocus',
isInFocusChain = 'isInFocusChain',
isSubtype = 'isSubtype',
isShowingOnScreen = 'isShowingOnScreen',
onFieldChangeOnce = 'onFieldChangeOnce',
readFile = 'readFile',
readRegistry = 'readRegistry',
removeNode = 'removeNode',
removeNodeChildren = 'removeNodeChildren',
renameFile = 'renameFile',
setSettings = 'setSettings',
setValue = 'setValue',
startResponsivenessTesting = 'startResponsivenessTesting',
getResponsivenessTestingData = 'getResponsivenessTestingData',
stopResponsivenessTesting = 'stopResponsivenessTesting',
statPath = 'statPath',
storeNodeReferences = 'storeNodeReferences',
writeFile = 'writeFile',
writeRegistry = 'writeRegistry',
}
export type RequestArgs = CallFuncArgs | CreateChildArgs | GetFocusedNodeArgs | GetValueArgs | GetValuesArgs | HasFocusArgs | IsInFocusChainArgs | OnFieldChangeOnceArgs | SetValueArgs | ReadRegistryArgs | WriteRegistryArgs | DeleteRegistrySectionsArgs | DeleteEntireRegistrySectionsArgs | StoreNodeReferencesArgs | GetNodesInfoArgs | FindNodesAtLocationArgs | CreateDirectoryArgs | DeleteEntireRegistrySectionsArgs | DeleteFileArgs | DeleteNodeReferencesArgs | DisableScreensaverArgs | FocusNodeArgs | GetAllCountArgs | GetDirectoryListingArgs | GetNodesWithPropertiesArgs | GetRootsCountArgs | GetServerHostArgs | GetVolumeListArgs | IsShowingOnScreenArgs | IsSubtypeArgs | ReadFileArgs | RenameFileArgs | SetSettingsArgs | StartResponsivenessTestingArgs | StatPathArgs | WriteFileArgs | RemoveNodeArgs |RemoveNodeChildrenArgs | DisableScreensaverArgs;
export enum BaseType {
global = 'global',
scene = 'scene',
nodeRef = 'nodeRef',
focusedNode = 'focusedNode'
}
export declare type LogLevels = 'off' | 'error' | 'warn' | 'info' | 'debug' | 'verbose';
interface NodeRefKey {
/** If base is 'nodeRef' this is the key that we used to store the node references on. If one isn't provided we use the automatically generated one */
nodeRefKey?: string;
}
export interface BaseArgs extends NodeRefKey {
/** Specifies what the entry point is for this key path. Defaults to 'global' if not specified */
base?: BaseType | keyof typeof BaseType;
}
export interface BaseKeyPath extends BaseArgs, MaxChildDepth {
/** Holds the hierarchy value with each level separated by dot for ex: videoNode.title to what you are interested in getting the value from or written to. */
keyPath?: string;
/** We have to convert nodes before converting to json. If this isn't needed then it can be avoided using this param as this causes a fairly significant overhead */
convertResponseToJsonCompatible?: boolean;
}
interface MaxChildDepth {
/** Controls how deep we'll recurse into node's tree structure. Defaults to 0 */
responseMaxChildDepth?: number;
}
export interface RequestOptions {
/** How long to wait (in milliseconds) until the request is considered a failure. If not provided OnDeviceComponent.defaultTimeout is used */
timeout?: number;
/** Allows for passing in a socket to allow sending a request before our socket promise has resolved */
socket?: Socket;
}
export interface Request {
id: string;
args: RequestArgs;
type: RequestType;
callback?: (response: RequestResponse) => void;
}
export interface RequestResponse {
json: any;
stringLength: number;
binaryLength: number;
stringPayload: string;
binaryPayload: Buffer;
}
export interface NodeRepresentation {
// Allow other fields
[key: string]: any;
change: {
Index1: number;
Index2: number;
Operation: string;
};
childRenderOrder?: 'renderFirst' | 'renderLast';
children?: NodeRepresentation[];
clippingRect?: [number, number, number, number];
enableRenderTracking?: boolean;
focusedChild: NodeRepresentation;
focusable: boolean;
id: string;
inheritParentOpacity?: boolean;
inheritParentTransform?: boolean;
muteAudioGuide?: boolean;
opacity?: number;
renderPass?: number;
renderTracking?: 'none' | 'partial' | 'full';
rotation?: number;
scale?: [number, number];
scaleRotateCenter?: [number, number];
subtype: string;
translation?: [number, number];
visible?: boolean;
}
export interface TreeNode {
/** What type of node this as returned by node.subtype() */
subtype: string;
id: string;
visible?: boolean;
opacity?: number;
translation?: number[];
/** This is the reference to the index it was stored at that we can use in later calls. If -1 we don't have one. */
ref: number;
/** Same as ref but for the parent */
parentRef: number;
/** Used to determine the position of this node in its parent if applicable */
position: number;
/** keyPath that can be used to access this node */
keyPath: string;
/** The boundingRect of this node if we needed to get it */
rect?: BoundingRect
/** The sceneBoundingRect of this node if we requested to get it */
sceneRect?: BoundingRect
children: TreeNode[];
}
export interface BoundingRect {
x: number;
y: number;
width: number;
height: number;
}
export interface ReturnTimeTaken {
/** How long this request took to run on the device */
timeTaken: number;
}
export interface CallFuncArgs extends BaseKeyPath {
/** Name of the function that needs to be called. */
funcName: string;
/** List of input arguments that need to be passed to the function. */
funcParams?: any[];
}
export interface GetComponentGlobalAAKeyPath extends BaseKeyPath {
/** Key path for selecting what to pull from the component's `m` associative array */
componentGlobalAAKeyPath: string;
}
export interface SetComponentGlobalAAKeyPath extends BaseKeyPath {
/** Key path for selecting what to set on the component's `m` associative array. */
componentGlobalAAKeyPath: string;
/** Value to set for the supplied `componentGlobalAAKeyPath` */
componentGlobalAAKeyPathValue: any;
}
export interface GetFocusedNodeArgs extends MaxChildDepth, NodeRefKey {
/** returns `ref` field in response that can be matched up with storeNodeReferences response for determining where we are in the node tree */
includeRef?: boolean;
/** If you only need access to the `ref` or `keyPath` in the output then you can speed up the request by choosing not to include the node in the response. Defaults to true */
includeNode?: boolean;
/** If true, will try to return the actual ArrayGrid itemComponent that is currently focused */
returnFocusedArrayGridChild?: boolean;
}
export interface GetValueArgs extends BaseKeyPath {
/** Allows supplying a keypath to a node and the field fpr that node separately to allow for better integration with an elements library */
field?: string;
}
export interface GetValuesArgs {
/** Retrieve multiple values with a single request. A list of the individual getValue args */
requests: {
[key: string]: GetValueArgs;
};
}
export interface GetNodesInfoArgs extends GetValuesArgs {}
export interface HasFocusArgs extends BaseKeyPath {}
export interface IsInFocusChainArgs extends BaseKeyPath {}
export interface StoreNodeReferencesArgs extends NodeRefKey {
/** We can get ArrayGrid(RowList,MarkupGrid,etc) children but this has an extra overhead so is disabled by default */
includeArrayGridChildren?: boolean;
/** We can get total and type based count info but again this has some overhead so is disabled by default */
includeNodeCountInfo?: boolean;
/** We can get the boundingRect info for each stored node. Again this has a performance penalty so is turned off by default */
includeBoundingRectInfo?: boolean;
}
export interface StoreNodeReferencesResponse extends ReturnTimeTaken {
flatTree: TreeNode[];
rootTree: TreeNode[];
totalNodes?: number;
nodeCountByType?: {[key: string]: number}
currentDesignResolution?: {
width: number;
height: number;
resolution: 'FHD' | 'HD';
}
}
export interface DeleteNodeReferencesArgs extends NodeRefKey {}
export interface DisableScreensaverArgs {
/** Set to true to disable screensaver from starting, false to allow screensaver to start at the appropriate time */
disableScreensaver: boolean;
}
export interface StartResponsivenessTestingArgs {
/** Sets how long a 'tick' is. Any render thread unresponsiveness shorter than this tick duration will not be captured. Number is in milliseconds and defaults to 17
*/
tickDuration?: number;
/** Sets the number of ticks we are shooting for in each period and is multiplied by tickDuration to set our timer duration */
periodTickCount?: number;
/** Sets how many periods we will keep in the stored data before we start throwing out older periods. Defaults to 10 */
periodsTrackCount?: number;
}
export interface FocusNodeArgs extends BaseKeyPath {
/** Set to false to take away focus from the node. Defaults to true */
on?: boolean;
}
export interface CreateChildArgs extends BaseKeyPath {
subtype: string;
fields?: Partial<NodeRepresentation>;
}
export interface RemoveNodeArgs extends BaseKeyPath {}
export interface RemoveNodeChildrenArgs extends BaseKeyPath {
/** The first index of the node(s) that we want to remove */
index: number;
/** The total count of nodes we want to remove. -1 for all */
count?: number;
}
export interface GetAllCountArgs {}
export interface GetRootsCountArgs {}
export interface GetVolumeListArgs {}
export interface Path {
path: string;
}
export interface GetDirectoryListingArgs extends Path {}
export interface StatPathArgs extends Path {}
export interface CreateDirectoryArgs extends Path {}
export interface DeleteFileArgs extends Path {}
export interface RenameFileArgs {
fromPath: string;
toPath: string;
}
export interface ReadFileArgs extends Path {}
export interface WriteFileArgs extends Path {
binaryPayload: Buffer
}
// IMPROVEMENT build out to support more complicated types
// rename to ComparableValueType in v3
export type ComparableValueTypes = string | number | boolean;
// rename to ComparisonOperator in v3
export type ComparisonOperators = '=' | '!=' | '>' | '>=' | '<' | '<=' | 'in' | '!in' | 'equal' | 'notEqual' | 'greaterThan' | 'greaterThanEqualTo' | 'lessThan' | 'lessThanEqualTo';
interface NodeComparison {
/* defaults to equal if not provided */
operator?: ComparisonOperators;
/* field acts a shorthand to specify fields. */
field?: string;
/* only fields will be used if both fields and keyPaths are provided */
fields?: string[];
/* keyPath acts a shorthand to specify keyPaths */
keyPath?: string;
/* only fields will be used if both fields and keyPaths are provided */
keyPaths?: string[];
value: ComparableValueTypes;
}
export interface GetNodesWithPropertiesArgs extends MaxChildDepth, NodeRefKey {
properties: NodeComparison[];
}
export interface FindNodesAtLocationArgs extends StoreNodeReferencesArgs {
/** horizontal pixel position you wish to find nodes at. Defaults to a resolution of 1920 but can be changed with OnDeviceComponent.uiResolution **/
x: number;
/** vertical pixel position you wish to find nodes at. Defaults to a resolution of 1080 but can be changed with OnDeviceComponent.uiResolution */
y: number;
/** If doing a single `findNodesAtLocation` request, it's not a big deal to call storeNodeReferences on the Roku to get our rect info. If you wish to call repeatedly you can make it much faster by providing an existing response from `storeNodeReferences` */
nodeTreeResponse?: StoreNodeReferencesResponse;
/** Will always be true no matter what is passed in */
includeBoundingRectInfo?: true;
}
export interface IsShowingOnScreenArgs extends BaseKeyPath {}
export interface IsSubtypeArgs extends BaseKeyPath {
/** The subtype we are checking against */
subtype: string;
/** isSubtype does not normally match the current node's subtype which is usually not the desired behavior.
* Because of this we also will match on the node's own subtype by default.
* Setting this to false will make it match on only a descendant subtype. */
matchOnSelfSubtype?: boolean;
}
interface MatchObject extends GetValueArgs {
/** If the match value is passed in then the observer will be fired when the field value equals to the value in match */
value: ComparableValueTypes;
}
export interface OnFieldChangeOnceArgs extends BaseKeyPath {
/** If the `keyPath` does not exist yet, this specifies how often to recheck to see if it now exists in milliseconds */
retryInterval?: number;
/** If the `keyPath` does not exist yet, this specifies how long to wait before erroring out in milliseconds */
retryTimeout?: number;
/** The field that we want to observe for changes on. If not supplied, the last part of `keyPath` will be used */
field?: string;
/** If provided will only return when this matches (including if it already equals that value) */
match?: MatchObject | ComparableValueTypes;
}
export interface SetValueArgs extends BaseKeyPath {
/** Value that needs to be set to the field. Field path is defined by key path. */
value: any;
/** Used to specify whether we are setting a field on a node or if we're updating the node structure itself. If not defined, we take the last part of the keyPath and use it as the field */
field?: string;
}
export interface ReadRegistryArgs {
/** List of Section keys of which we need data to be read, if empty then it will return entire contents of the registry */
values?: {
[section: string]: string[] | string;
};
}
export interface WriteRegistryArgs {
/** Contains data that will be written to registry. If null is passed for a sectionItemKey that key will be deleted. If null is passed for a section that entire section will be deleted. */
values: {
[section: string]: {[sectionItemKey: string]: string | null}
};
}
export interface DeleteRegistrySectionsArgs {
/** Contains list of section keys that needs to be deleted. */
sections: string[] | string;
/** If true deletes the entry registry. */
allowEntireRegistryDelete?: boolean;
}
export interface DeleteEntireRegistrySectionsArgs {}
export interface GetApplicationStartTimeArgs {}
export interface GetServerHostArgs {}
export interface SetSettingsArgs {
logLevel: LogLevels;
}