@ham2k/extension-sdk 0.12.14 → 0.12.15
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/index.d.ts +90 -4
- package/dist/index.js +11 -0
- package/docs/distribution.md +7 -0
- package/docs/hooks.md +59 -9
- package/package.json +1 -1
- package/samples/k2hrc-panafall/README.md +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// @ham2k/extension-sdk 0.12.
|
|
1
|
+
// @ham2k/extension-sdk 0.12.15
|
|
2
2
|
/** Experimental v1 panel scene contract. All coordinates are in the scene's viewBox. */
|
|
3
3
|
export interface PanelScene {
|
|
4
4
|
version: 1;
|
|
@@ -21,6 +21,20 @@ export interface PanelScene {
|
|
|
21
21
|
radio?: {
|
|
22
22
|
node?: string;
|
|
23
23
|
};
|
|
24
|
+
/**
|
|
25
|
+
* A scene longer than its pane along `axis` (default `y`), scrolled by the app itself — wheel,
|
|
26
|
+
* trackpad and drag, a drag begun on a button included — with no call to the extension. Scaled
|
|
27
|
+
* to fill the pane across, it runs on past it along the axis. The position, in scene units from
|
|
28
|
+
* the start, is written to the scene value `value` as it scrolls; a render that changes that
|
|
29
|
+
* value moves the view there, and one that leaves it alone leaves the operator's scroll alone.
|
|
30
|
+
* `event`, when given, is sent as a `commit` with the position as `value` once scrolling comes
|
|
31
|
+
* to rest. Layers and controls marked `fixed` stay put over the pane. No `layout`. Extension API 12.
|
|
32
|
+
*/
|
|
33
|
+
scroll?: {
|
|
34
|
+
axis?: "x" | "y";
|
|
35
|
+
value: string;
|
|
36
|
+
event?: string;
|
|
37
|
+
};
|
|
24
38
|
}
|
|
25
39
|
/** Host-fed values of a scene with `radio`: its meters, and `radio.transmitting` as 1 or 0. Reserved: a scene may not declare them. */
|
|
26
40
|
export type PanelSceneRadioValue = "radio.signalDbm" | "radio.powerOut" | "radio.swr" | "radio.alc" | "radio.supplyVolts" | "radio.transmitting"
|
|
@@ -52,13 +66,28 @@ export interface PanelSceneLayer {
|
|
|
52
66
|
y: number;
|
|
53
67
|
width: number;
|
|
54
68
|
height: number;
|
|
55
|
-
/** Supply exactly one of svg or
|
|
69
|
+
/** Supply exactly one of svg, text or icon. SVG must be self-contained. */
|
|
56
70
|
svg?: string;
|
|
71
|
+
/**
|
|
72
|
+
* A named icon — MDI, or FontAwesome with `fa-` — drawn by the app to fit the layer, in `color`
|
|
73
|
+
* (`#RRGGBB`) or the theme's. Extension API 12.
|
|
74
|
+
*/
|
|
75
|
+
icon?: {
|
|
76
|
+
name: string;
|
|
77
|
+
color?: string;
|
|
78
|
+
};
|
|
57
79
|
/**
|
|
58
80
|
* Take the clicks that land on this layer. Off by default: layers are click-through, so
|
|
59
81
|
* artwork painted over a control does not stop it working. On, it covers the controls under it.
|
|
60
82
|
*/
|
|
61
83
|
blocksPointer?: boolean;
|
|
84
|
+
/** In a scene with `scroll`: drawn over the pane where it is, in pane coordinates, not scrolled. Extension API 12. */
|
|
85
|
+
fixed?: boolean;
|
|
86
|
+
/**
|
|
87
|
+
* While a `zoom` strip is dragged, scaled along the scroll about the pane's middle, rather than
|
|
88
|
+
* moved there at its own size: for a background, or a line that runs the whole way. Extension API 12.
|
|
89
|
+
*/
|
|
90
|
+
stretch?: boolean;
|
|
62
91
|
/** Exactly one of literal/value. A value naming a string shows it as-is. Use text layers, not SVG <text>, for font support.
|
|
63
92
|
* Size is unscaled; the host applies OS text scaling once. */
|
|
64
93
|
text?: {
|
|
@@ -121,10 +150,16 @@ export interface PanelSceneLayer {
|
|
|
121
150
|
* reach the extension. Needs `requiresRadioRead`; a host without the feature, or a radio
|
|
122
151
|
* without a scope, shows why instead. A click sends `commit` with the frequency as `value`.
|
|
123
152
|
* Takes no `value`; see `PanelSceneSpectrum` for the rest. Extension API 6: declare `"api": 6`.
|
|
153
|
+
* - `zoom`: a strip of a scene with `scroll`, drawn by nothing, where a drag along the scroll zooms
|
|
154
|
+
* about the pane's middle — away from it in, toward it out, by the ratio of the distances. While
|
|
155
|
+
* the drag lasts the app moves each layer and control to where the zoom puts its middle, at its
|
|
156
|
+
* own size (a `stretch` layer scales instead), and on release sends `commit` with the factor as
|
|
157
|
+
* `value`; `min` and `max` are the factors allowed. A tap on it still reaches what lies there,
|
|
158
|
+
* and a drag elsewhere still scrolls. Needs `event`. Extension API 12.
|
|
124
159
|
*
|
|
125
160
|
* `label` is every control's accessible name. There are no tooltips.
|
|
126
161
|
*/
|
|
127
|
-
export type PanelSceneControlKind = "button" | "slider" | "knob" | "nativeButton" | "nativeSlider" | "nativeTextField" | "nativeDropdown" | "nativeSwitch" | "nativeCheckbox" | "nativeRadio" | "nativeSegmented" | "nativeChip" | "nativeText" | "spectrum";
|
|
162
|
+
export type PanelSceneControlKind = "button" | "slider" | "knob" | "nativeButton" | "nativeSlider" | "nativeTextField" | "nativeDropdown" | "nativeSwitch" | "nativeCheckbox" | "nativeRadio" | "nativeSegmented" | "nativeChip" | "nativeText" | "spectrum" | "zoom";
|
|
128
163
|
/** A literal, or the name of a scene value — which a slider with no `event` retunes with no bridge call. */
|
|
129
164
|
export type PanelSceneSpectrumNumber = number | string;
|
|
130
165
|
/**
|
|
@@ -361,6 +396,18 @@ export interface PanelSceneControl extends PanelSceneSpectrum {
|
|
|
361
396
|
multi?: boolean;
|
|
362
397
|
/** Shown but inert: no clicks, drags, keys or screen-reader adjustments act on it. */
|
|
363
398
|
disabled?: boolean;
|
|
399
|
+
/** In a scene with `scroll`: placed over the pane, in pane coordinates, not scrolled. Needs a rect. Extension API 12. */
|
|
400
|
+
fixed?: boolean;
|
|
401
|
+
/**
|
|
402
|
+
* A drawn control only (`button`, `slider`, `knob`): while the pointer is over it, the scene value
|
|
403
|
+
* `value` reads `to`, set by the host with no call to the extension; leaving puts back the scene's
|
|
404
|
+
* own value. Artwork bound to it lights up under the pointer — a spot's line with its call.
|
|
405
|
+
* Survives renders while the pointer stays. Extension API 12.
|
|
406
|
+
*/
|
|
407
|
+
hoverSet?: {
|
|
408
|
+
value: string;
|
|
409
|
+
to: number;
|
|
410
|
+
};
|
|
364
411
|
/**
|
|
365
412
|
* 0 to 1, fixed or bound like a layer's. At 0 the control is gone: it takes no clicks,
|
|
366
413
|
* keyboard focus or screen-reader node. Anything between is only drawn fainter.
|
|
@@ -387,6 +434,17 @@ export interface PanelSceneControl extends PanelSceneSpectrum {
|
|
|
387
434
|
valueLabels?: string[];
|
|
388
435
|
/** Knobs use relative horizontal/upward dragging. Value per scene unit; default 1. */
|
|
389
436
|
sensitivity?: number;
|
|
437
|
+
/**
|
|
438
|
+
* A knob only: a drag moves the value the other way — content held under the finger, scrolled
|
|
439
|
+
* by dragging, rather than a dial turned. Scrolling is unchanged. Extension API 12.
|
|
440
|
+
*/
|
|
441
|
+
invertDrag?: boolean;
|
|
442
|
+
/**
|
|
443
|
+
* A slider or knob only: it also takes the scrolls that land on drawn buttons over it — labels
|
|
444
|
+
* drawn over a knob that scrolls the artwork. A native control, a `blocksPointer` layer or another
|
|
445
|
+
* slider or knob in between keeps the scroll. Extension API 12.
|
|
446
|
+
*/
|
|
447
|
+
scrollThrough?: boolean;
|
|
390
448
|
/**
|
|
391
449
|
* A knob's second axis: with `valueY`, horizontal scrolling, dragging and the left/right keys set
|
|
392
450
|
* `value`, and vertical ones (and up/down) set `valueY` — sent as its own event, `eventY`, which a
|
|
@@ -687,8 +745,22 @@ export interface GetSpotsOptions {
|
|
|
687
745
|
annotate?: boolean;
|
|
688
746
|
operationUuid?: string;
|
|
689
747
|
}
|
|
748
|
+
export interface SuggestedQso {
|
|
749
|
+
their: {
|
|
750
|
+
call: string;
|
|
751
|
+
};
|
|
752
|
+
freq?: number;
|
|
753
|
+
band?: string;
|
|
754
|
+
mode?: string;
|
|
755
|
+
refs?: SpotRef[];
|
|
756
|
+
}
|
|
690
757
|
export interface BoardSpot extends Spot {
|
|
691
758
|
hookKey?: string;
|
|
759
|
+
display?: {
|
|
760
|
+
icon: string;
|
|
761
|
+
iconColor?: string;
|
|
762
|
+
emoji?: string;
|
|
763
|
+
};
|
|
692
764
|
annotations?: SpotAnnotations;
|
|
693
765
|
}
|
|
694
766
|
export interface SpotAnnotations {
|
|
@@ -1994,7 +2066,7 @@ export interface PanelRadioState {
|
|
|
1994
2066
|
endedAtMillis: number;
|
|
1995
2067
|
} | null;
|
|
1996
2068
|
/**
|
|
1997
|
-
* The radio's scope
|
|
2069
|
+
* The radio's scope: absent on an app without a panadapter, and null
|
|
1998
2070
|
* for a radio without one. The sweeps are never sent — a `spectrum` scene control draws them.
|
|
1999
2071
|
*/
|
|
2000
2072
|
spectrum?: PanelRadioSpectrum | null;
|
|
@@ -2614,6 +2686,20 @@ export declare const host: {
|
|
|
2614
2686
|
clusterPostSpot(args: ClusterPostSpotRequest): Promise<ClusterReply>;
|
|
2615
2687
|
/** Sends any one command line, in the operator's name. Needs `requiresClusterCommand` and extension API 10. */
|
|
2616
2688
|
clusterSend(command: string): Promise<ClusterReply>;
|
|
2689
|
+
/**
|
|
2690
|
+
* Puts a station into the logging fields of the operation in front, as tapping its spot in the
|
|
2691
|
+
* Spots Panel does — call, frequency, band, mode and references; nothing else of `qso` is used.
|
|
2692
|
+
* With `operationUuid` (a panel's `operation.uuid`), only that operation's: `accepted` is false
|
|
2693
|
+
* when it is not the one in front, or none is open. It tunes the radio as a tap does, so it needs
|
|
2694
|
+
* `requiresRadioWrite`, and it is refused outside the extension's own panel `onEvent`. Extension
|
|
2695
|
+
* API 12.
|
|
2696
|
+
*/
|
|
2697
|
+
suggestQso(args: {
|
|
2698
|
+
qso: SuggestedQso;
|
|
2699
|
+
operationUuid?: string;
|
|
2700
|
+
}): Promise<{
|
|
2701
|
+
accepted: boolean;
|
|
2702
|
+
}>;
|
|
2617
2703
|
fetch(url: string, options?: FetchOptions): Promise<FetchResponse>;
|
|
2618
2704
|
webSocket(url: string, options?: WebSocketOptions): ExtensionWebSocket;
|
|
2619
2705
|
kvGet(key: string): Promise<JSONValue | null>;
|
package/dist/index.js
CHANGED
|
@@ -227,6 +227,17 @@ const host = {
|
|
|
227
227
|
async clusterSend(command) {
|
|
228
228
|
return await hostCallFn()("clusterSend", { command });
|
|
229
229
|
},
|
|
230
|
+
/**
|
|
231
|
+
* Puts a station into the logging fields of the operation in front, as tapping its spot in the
|
|
232
|
+
* Spots Panel does — call, frequency, band, mode and references; nothing else of `qso` is used.
|
|
233
|
+
* With `operationUuid` (a panel's `operation.uuid`), only that operation's: `accepted` is false
|
|
234
|
+
* when it is not the one in front, or none is open. It tunes the radio as a tap does, so it needs
|
|
235
|
+
* `requiresRadioWrite`, and it is refused outside the extension's own panel `onEvent`. Extension
|
|
236
|
+
* API 12.
|
|
237
|
+
*/
|
|
238
|
+
async suggestQso(args) {
|
|
239
|
+
return await hostCallFn()("suggestQso", { ...args });
|
|
240
|
+
},
|
|
230
241
|
async fetch(url, options) {
|
|
231
242
|
return await hostCallFn()("fetch", { url, ...options });
|
|
232
243
|
},
|
package/docs/distribution.md
CHANGED
|
@@ -540,6 +540,13 @@ catalog's own bundle links (`…/api/v1/extensions/<key>/versions/<version>/bund
|
|
|
540
540
|
take this verified path when they arrive as a deep link; every other host
|
|
541
541
|
takes the plain one above.
|
|
542
542
|
|
|
543
|
+
An extension's screenshots — published beside its bundles, never inside them
|
|
544
|
+
(the tools README says how) — show as a strip of thumbnails on its row in the
|
|
545
|
+
operation sheet's activity search, on the consent screen of a catalog install,
|
|
546
|
+
and in an installed extension's details; a tap opens them full size. The app
|
|
547
|
+
loads them only from the catalog's own host: a listing naming any other is
|
|
548
|
+
shown without them.
|
|
549
|
+
|
|
543
550
|
### Release tracks
|
|
544
551
|
|
|
545
552
|
A catalog channel — `stable`, `unstable` or `bleeding` — says how finished a
|
package/docs/hooks.md
CHANGED
|
@@ -73,6 +73,17 @@ hook method receives `(args, ctx)` where `ctx: HookContext` is:
|
|
|
73
73
|
reads above it is cheap enough for the lookup path; it resolves `[]`
|
|
74
74
|
whenever the cache is cold or the host keeps no spots. Used by
|
|
75
75
|
`spot-history` to pull a hunted park or summit into the QSO being logged.
|
|
76
|
+
* `host.suggestQso({qso, operationUuid?})` (extension API 12) — puts a
|
|
77
|
+
station into the logging fields of the operation in front, as tapping its
|
|
78
|
+
spot in the Spots Panel does: `qso.their.call`, and `freq`, `band`, `mode`
|
|
79
|
+
and `refs` where given; nothing else of `qso` reaches the fields. With
|
|
80
|
+
`operationUuid` — a panel's own `operation.uuid` — only that operation's
|
|
81
|
+
fields, so a panel never fills a log the operator is not looking at.
|
|
82
|
+
Answers `{accepted}`, false when no such operation is open. It tunes the
|
|
83
|
+
radio as a tap does, so it needs `requiresRadioWrite`, and it is refused
|
|
84
|
+
except from inside the extension's own panel `onEvent`: it answers the
|
|
85
|
+
operator clicking something, never a timer or a render, which would
|
|
86
|
+
overwrite what they are typing.
|
|
76
87
|
* `getSpots?(options?)` — the whole spots board the host already holds,
|
|
77
88
|
for a panel showing spots its own way. Like `getSpotsForCall` it reads the
|
|
78
89
|
cache and never fetches, and resolves `[]` while the cache is cold. By
|
|
@@ -92,7 +103,12 @@ hook method receives `(args, ctx)` where `ctx: HookContext` is:
|
|
|
92
103
|
ones the app already holds for the operation open on screen, so the call
|
|
93
104
|
never waits on a scorer; another operation's spots, and that one's until
|
|
94
105
|
its first verdicts land, come back unannotated rather than guessed.
|
|
95
|
-
|
|
106
|
+
From extension API 12 each also carries `display` — `icon` (an MDI or
|
|
107
|
+
`fa-` name), `iconColor` (`#RRGGBB`, where the activity declares one) and
|
|
108
|
+
`emoji` (the call's note emoji, where it has one): what the Spots Panel's row
|
|
109
|
+
shows beside the call, the activity's icon and tint for the spot's first
|
|
110
|
+
reference, else the source's own icon. `annotate: false` returns the spots
|
|
111
|
+
as their sources gave them.
|
|
96
112
|
A panel's `'spots'` trigger fires whenever this answer may have moved: a
|
|
97
113
|
refresh, new verdicts, the operator's spot filters or bands, or the radio's
|
|
98
114
|
band or mode. A malformed or unknown option rejects the call. The CLI host
|
|
@@ -287,6 +303,14 @@ interface LookupServiceHook {
|
|
|
287
303
|
unset or name itself; tagging one `'prefix'` gets its coordinate
|
|
288
304
|
discarded.
|
|
289
305
|
|
|
306
|
+
- **A guess field of the wrong type is dropped.** The bridge enforces none of
|
|
307
|
+
`CallInfo`'s declared types, so the app normalizes the answer
|
|
308
|
+
(`normalizeLookupResult`, halo_core) before anything reads it: a field its
|
|
309
|
+
readers cannot use — a numeric `continent`, a boolean `emoji` — is dropped
|
|
310
|
+
and reported once by name, and the rest of the guess is still used. A
|
|
311
|
+
numeric string where a number is read (`cqZone: '05'`) is taken as that
|
|
312
|
+
number.
|
|
313
|
+
|
|
290
314
|
Implemented by: `lookups` (key `core`). The merge algorithm itself
|
|
291
315
|
(`mergeLookupIntoGuess`/`runLookupPipeline` in
|
|
292
316
|
`extensions/core/lookups/src/mergeLookup.ts`) is a pure, host-independent
|
|
@@ -1876,9 +1900,10 @@ drawing part of it.
|
|
|
1876
1900
|
| `width`, `height` | The artwork's viewBox, in scene units. Size it to `environment.width`/`height` and a scene unit is a logical pixel. |
|
|
1877
1901
|
| `values` | `{name: number}`: what bindings, numeric text and numeric controls read. At most 256. |
|
|
1878
1902
|
| `strings` | `{name: string}`: what text fields and choices hold. At most 256, each up to 4096 characters. A name is in `values` or `strings`, never both. |
|
|
1879
|
-
| `layers` | Painted in order, each over the ones before: `svg` artwork or `
|
|
1880
|
-
| `controls` | At most 64. Drawn or native; see below. |
|
|
1903
|
+
| `layers` | Painted in order, each over the ones before: `svg` artwork, `text`, or an `icon`. At most 512 (128 before extension API 12), and 1 MiB of artwork and text in all. |
|
|
1904
|
+
| `controls` | At most 256 (64 before extension API 12). Drawn or native; see below. |
|
|
1881
1905
|
| `layout` | Optional. Where rect-less native controls and the artwork go; omitted, the artwork fills the pane. |
|
|
1906
|
+
| `scroll` | Optional, `{axis?, value, event?}` (extension API 12): a scene longer than its pane along `axis` (`y` by default), scrolled natively by the app — wheel, trackpad and drag, a drag begun on a button included — with no call to the extension. It fills the pane across and runs on past it. The position, in scene units, is written to the scene value `value`; a render that changes that value moves the view there, one that leaves it alone leaves the operator's scroll alone. `event` is sent as a `commit`, the position as `value`, once a scroll comes to rest. Layers and controls with `fixed: true` stay put over the pane, in pane coordinates. A drag along the scroll on a slider or knob that scrolls with the content is the scroll's: make one that must be dragged `fixed`. Not with `layout`. |
|
|
1882
1907
|
| `radio` | Optional, `{node?}`: the host feeds that radio's live readings into the reserved `radio.*` values. `node` is an id from `listRadios`; omitted, the logging radio. See *Radio values*. |
|
|
1883
1908
|
|
|
1884
1909
|
**Controls.** Every control has an `id` and a `label`, which is its accessible
|
|
@@ -1889,8 +1914,8 @@ the extension. `value` names what it shows and sets.
|
|
|
1889
1914
|
| Kind | Binds to | Sends | Also takes |
|
|
1890
1915
|
|---|---|---|---|
|
|
1891
1916
|
| `button` | — | `activate` | `menu` |
|
|
1892
|
-
| `slider` | number | `commit` | `min`, `max`, `step`, `discrete`, `hover`, `valueLabels`, `continuous` |
|
|
1893
|
-
| `knob` | number | `commit` | `min`, `max`, `step`, `sensitivity`, `valueLabels`, `continuous`, `menu`, a second axis (`valueY`, `eventY`, `minY`, `maxY`, `stepY`, `sensitivityY`) |
|
|
1917
|
+
| `slider` | number | `commit` | `min`, `max`, `step`, `discrete`, `hover`, `valueLabels`, `continuous`, `scrollThrough` |
|
|
1918
|
+
| `knob` | number | `commit` | `min`, `max`, `step`, `sensitivity`, `invertDrag`, `scrollThrough`, `valueLabels`, `continuous`, `menu`, a second axis (`valueY`, `eventY`, `minY`, `maxY`, `stepY`, `sensitivityY`) |
|
|
1894
1919
|
| `nativeButton` | — | `activate` | `variant` (`filled`, `tonal`, `outlined`, `text`), `icon`, `menu`; needs `event` or `menu` |
|
|
1895
1920
|
| `nativeSlider` | number | `commit` | `min`, `max`, `step`, `valueLabels`, `continuous` |
|
|
1896
1921
|
| `nativeTextField` | string | `commit` on Enter, or on leaving it after typing | `placeholder`, `continuous` |
|
|
@@ -1901,6 +1926,7 @@ the extension. `value` names what it shows and sets.
|
|
|
1901
1926
|
| `nativeChip` | number, 1 or 0; or none | `commit`; `activate` without a value | `icon`; needs `event` without a value |
|
|
1902
1927
|
| `nativeText` | number, string, or none | nothing | `style` (a typography role), `align` (`start`, `center`, `end`) |
|
|
1903
1928
|
| `spectrum` | — | `commit` with the frequency clicked; `activate` from an annotation | see *Spectrum* below |
|
|
1929
|
+
| `zoom` | — | `commit` with the factor, on release | `min`, `max` (the factors allowed); only in a scene with `scroll`; extension API 12 |
|
|
1904
1930
|
|
|
1905
1931
|
The three drawn kinds are invisible hit areas over artwork the extension paints;
|
|
1906
1932
|
the native kinds are Material widgets the app paints and themes. Every control
|
|
@@ -1912,12 +1938,37 @@ may also take:
|
|
|
1912
1938
|
- `after`: with a rect, the layer it paints directly after.
|
|
1913
1939
|
- `opacity`: 0 to 1, fixed or bound like a layer's. At 0 the control is gone.
|
|
1914
1940
|
- `disabled`: shown, but no click, drag, key or screen-reader adjustment acts on it.
|
|
1941
|
+
- `hoverSet` (drawn kinds only; extension API 12): `{value, to}`. While the
|
|
1942
|
+
pointer is over the control, the scene value `value` reads `to` — set by the
|
|
1943
|
+
host, with no call to the extension — and leaving puts back the scene's own
|
|
1944
|
+
value. A layer bound to it lights up under the pointer, and several controls
|
|
1945
|
+
naming one value with different `to`s light up one thing each. It survives
|
|
1946
|
+
renders while the pointer stays.
|
|
1915
1947
|
|
|
1916
1948
|
`options` is `[{label, value}]`, up to 64, with each `value` unique. A choice's
|
|
1917
1949
|
string is `""` or one of them; a `multi` choice holds its values joined with
|
|
1918
1950
|
commas in option order, so no option may contain one. `menu` is
|
|
1919
1951
|
`[{label, event}]`, up to 32: picking an item sends its `event` as the action.
|
|
1920
1952
|
|
|
1953
|
+
A `zoom` strip is drawn by nothing: it claims a drag that begins on it along a scrolling
|
|
1954
|
+
scene's axis. Away from the pane's middle zooms in and toward it zooms out, by the ratio of
|
|
1955
|
+
the two distances from the middle, clamped to `min`…`max`. While the drag lasts the app moves
|
|
1956
|
+
each layer and control to where the zoom puts its middle, keeping its size, so text and dots
|
|
1957
|
+
stay as drawn and only spread apart or close in; a layer with `stretch: true` — a background,
|
|
1958
|
+
a line the length of the scene — scales along the scroll instead. That preview holds until
|
|
1959
|
+
the render that answers the `commit` arrives, so a scene meant to zoom draws its pieces as
|
|
1960
|
+
layers of their own rather than as one picture. A tap on the strip still reaches the button there, and a drag that starts off it
|
|
1961
|
+
still scrolls.
|
|
1962
|
+
|
|
1963
|
+
A scroll steps a slider or knob by its `step`, down and left lowering it; a one-axis
|
|
1964
|
+
control takes a sideways scroll by its own direction. A slider or knob with
|
|
1965
|
+
`scrollThrough` (API 12) also takes the scrolls landing on drawn buttons over it, so labels
|
|
1966
|
+
drawn over a knob that scrolls the artwork do not stop the scroll; anything else in the
|
|
1967
|
+
way — a native control, a `blocksPointer` layer, another slider or knob — keeps the scroll
|
|
1968
|
+
from it.
|
|
1969
|
+
A knob with `invertDrag` (API 12) moves the other way to a drag, as content held under
|
|
1970
|
+
the finger does — what a knob that scrolls the artwork wants — while its scroll is unchanged.
|
|
1971
|
+
|
|
1921
1972
|
A knob with `valueY` sets two numbers from one patch of artwork — a passband's
|
|
1922
1973
|
shift across and its width up, say. Horizontal dragging, horizontal scrolling
|
|
1923
1974
|
and the left/right keys set `value`; vertical ones and the up/down keys set
|
|
@@ -2029,9 +2080,8 @@ control faded in over the artwork, and a click-through layer painted over it.
|
|
|
2029
2080
|
#### Spectrum
|
|
2030
2081
|
|
|
2031
2082
|
A `spectrum` control is a radio's panadapter and waterfall, drawn by the host
|
|
2032
|
-
from sweeps that never reach the extension
|
|
2033
|
-
|
|
2034
|
-
using either declares `"api": 6`, and an app speaking less refuses it at install
|
|
2083
|
+
from sweeps that never reach the extension. It is **extension API 6**, as is
|
|
2084
|
+
`host.setRadioSpectrum`: a bundle using either declares `"api": 6`, and an app speaking less refuses it at install
|
|
2035
2085
|
rather than failing to render the scene. It needs `requiresRadioRead`; without it, or on a host or radio
|
|
2036
2086
|
without a spectrum, the control says why instead. It is placed like a native
|
|
2037
2087
|
control and takes the fields of `PanelSceneSpectrum` in the SDK:
|
|
@@ -2288,7 +2338,7 @@ protocol's (CI-V bytes that are not whole frames), `invalid`. A refusal heard
|
|
|
2288
2338
|
within a second of a raw command on a protocol whose refusals name no command
|
|
2289
2339
|
(`?;`, rigctld's `RPRT`) is taken as the raw command's, not counted against the
|
|
2290
2340
|
app's own reads.
|
|
2291
|
-
|
|
2341
|
+
`readRadio()` carries `spectrum` (absent on an app without a panadapter): null
|
|
2292
2342
|
for a radio without a scope, otherwise its settings as the radio reports them
|
|
2293
2343
|
(`mode`, `spanHz`, `lowHz`/`highHz`, `refLevelDb`, `speed`), what it accepts
|
|
2294
2344
|
(`spansHz`, `refMinDb`…`refStepDb`, `modes`, `speeds`) and `problem`, why it
|
package/package.json
CHANGED
|
@@ -4,9 +4,9 @@ The radio's panadapter and waterfall in a scene panel, with its span, reference
|
|
|
4
4
|
level and sweep speed, a local contrast control, and click-to-tune. The host
|
|
5
5
|
draws the sweeps in the `spectrum` control; they never reach the extension.
|
|
6
6
|
|
|
7
|
-
Needs a
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
Needs a radio whose CAT protocol carries its scope: an Icom IC-705/7300/7610 (at
|
|
8
|
+
115200 bps on a serial line), or a FlexRadio, which is mirrored through a DAX IQ
|
|
9
|
+
channel.
|
|
10
10
|
|
|
11
11
|
In this repository:
|
|
12
12
|
|