@ham2k/extension-sdk 1.12.0 → 1.12.1
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 +8 -1
- package/docs/distribution.md +22 -0
- package/docs/hooks.md +8 -1
- package/docs/settings.md +134 -8
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// @ham2k/extension-sdk 1.12.
|
|
1
|
+
// @ham2k/extension-sdk 1.12.1
|
|
2
2
|
/** Experimental v1 panel scene contract. All coordinates are in the scene's viewBox. */
|
|
3
3
|
export interface PanelScene {
|
|
4
4
|
version: 1;
|
|
@@ -1595,6 +1595,12 @@ export interface ExtensionRelevance {
|
|
|
1595
1595
|
dates?: string[];
|
|
1596
1596
|
interests?: string[];
|
|
1597
1597
|
}
|
|
1598
|
+
export type SettingsSection = "activities" | "hunting" | "contests" | "lookups" | "spotting" | "dashboard" | "logging" | "radio" | "map" | "exports";
|
|
1599
|
+
export interface ExtensionSettingsPlacement {
|
|
1600
|
+
section?: SettingsSection | (string & {});
|
|
1601
|
+
sidebar?: boolean;
|
|
1602
|
+
common?: boolean;
|
|
1603
|
+
}
|
|
1598
1604
|
export interface ExtensionManifest {
|
|
1599
1605
|
key: string;
|
|
1600
1606
|
name: string;
|
|
@@ -1620,6 +1626,7 @@ export interface ExtensionManifest {
|
|
|
1620
1626
|
requiresClusterCommand?: boolean;
|
|
1621
1627
|
experiments?: string[];
|
|
1622
1628
|
relevance?: ExtensionRelevance;
|
|
1629
|
+
settings?: ExtensionSettingsPlacement;
|
|
1623
1630
|
translations?: Record<string, {
|
|
1624
1631
|
name?: string;
|
|
1625
1632
|
description?: string;
|
package/docs/distribution.md
CHANGED
|
@@ -144,6 +144,28 @@ The packer refuses:
|
|
|
144
144
|
The matcher reads a key it cannot parse as "does not gate", so each of the
|
|
145
145
|
shape errors would otherwise ship the bundle as worldwide.
|
|
146
146
|
|
|
147
|
+
### Settings
|
|
148
|
+
|
|
149
|
+
An extension with a `settingsPanel` says where its panel goes:
|
|
150
|
+
|
|
151
|
+
```json
|
|
152
|
+
"settings": { "section": "activities" }
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
`section` is one of the app's settings sections, picked by the extension's
|
|
156
|
+
main purpose; `sidebar: true` asks for a sidebar entry for a panel that is a
|
|
157
|
+
category of its own, and `common: true` for Common Preferences rows. The section list, and what the app does with a
|
|
158
|
+
placement the manifest does not declare, are in
|
|
159
|
+
[settings.md](./settings.md#where-an-extensions-settings-go).
|
|
160
|
+
|
|
161
|
+
The packer refuses a `settings` that is not an object, a key inside it other
|
|
162
|
+
than those three, a `section` that is not a section key, and a `sidebar` or
|
|
163
|
+
`common` that is not `true` or `false`. It does not refuse a placement beyond
|
|
164
|
+
the usual — a section outside the list, no section for a `settingsPanel`, a
|
|
165
|
+
sidebar entry, Common Preferences — but prints `held for review on the
|
|
166
|
+
catalog` for each, because the catalog holds such an upload for an admin
|
|
167
|
+
even from a trusted publisher.
|
|
168
|
+
|
|
147
169
|
## Using the host's libraries
|
|
148
170
|
|
|
149
171
|
The host carries a set of libraries and hands every extension the same
|
package/docs/hooks.md
CHANGED
|
@@ -1961,7 +1961,8 @@ stay as drawn and only spread apart or close in; a layer with `stretch: true`
|
|
|
1961
1961
|
a line the length of the scene — scales along the scroll instead. That preview holds until
|
|
1962
1962
|
the render that answers the `commit` arrives, so a scene meant to zoom draws its pieces as
|
|
1963
1963
|
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
|
|
1964
|
-
still scrolls.
|
|
1964
|
+
still scrolls. A trackpad's two-finger swipe scrolls on the strip as anywhere else; a trackpad
|
|
1965
|
+
pinch begun on it zooms by the pinch's own scale, clamped the same way, and commits as a drag does.
|
|
1965
1966
|
|
|
1966
1967
|
A scroll steps a slider or knob by its `step`, down and left lowering it; a one-axis
|
|
1967
1968
|
control takes a sideways scroll by its own direction. A slider or knob with
|
|
@@ -2477,6 +2478,12 @@ schema, kernel dispatch, `ExtensionService`, and `SettingsView` wiring; see
|
|
|
2477
2478
|
[settings.md](./settings.md). Complementary to `account`, not a replacement.
|
|
2478
2479
|
Implemented by: `settings` (the core General panel).
|
|
2479
2480
|
|
|
2481
|
+
An extension puts all its settings in one panel, placed in the section that
|
|
2482
|
+
fits its main purpose and declared in the manifest's `settings` — see
|
|
2483
|
+
[Where an extension's settings go](./settings.md#where-an-extensions-settings-go).
|
|
2484
|
+
A category of its own, a sidebar entry or Common Preferences rows are reviewed
|
|
2485
|
+
on the catalog.
|
|
2486
|
+
|
|
2480
2487
|
## ✅ `account` — account connections
|
|
2481
2488
|
|
|
2482
2489
|
Account connections (QRZ, LoFi, SOTA): credential fields, `testCredentials`,
|
package/docs/settings.md
CHANGED
|
@@ -26,6 +26,122 @@ There are two tiers, discriminated by a required `kind` tag.
|
|
|
26
26
|
|
|
27
27
|
---
|
|
28
28
|
|
|
29
|
+
## Where an extension's settings go
|
|
30
|
+
|
|
31
|
+
**Put all of an extension's settings in one panel, and that panel in the
|
|
32
|
+
section that fits the extension's main purpose.** The panel shows there as a
|
|
33
|
+
single row that opens it in a dialog. An extension does not add a category of
|
|
34
|
+
its own to Application Preferences, an entry to the Settings sidebar, or
|
|
35
|
+
fields to Common Preferences — not without an admin's review on the catalog.
|
|
36
|
+
|
|
37
|
+
These sections take an extension's panel without review:
|
|
38
|
+
|
|
39
|
+
| `section` | Shown as | For |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| `activities` | Activities | an activity program — POTA, SOTA, WWFF |
|
|
42
|
+
| `hunting` | Hunting | chasing and awards: what an operator works rather than activates |
|
|
43
|
+
| `contests` | Contests | a contest or event |
|
|
44
|
+
| `lookups` | Lookups | callsign lookups, notes and history |
|
|
45
|
+
| `spotting` | Spotting | a spot source or destination |
|
|
46
|
+
| `dashboard` | Dashboard | a dashboard panel's app-wide preferences |
|
|
47
|
+
| `logging` | Logging | something that changes how QSOs are entered |
|
|
48
|
+
| `radio` | CAT Control | radios, rigs and keyers |
|
|
49
|
+
| `map` | Maps | the map views |
|
|
50
|
+
| `exports` | Exports | export files and formats |
|
|
51
|
+
|
|
52
|
+
Prefer the first six — they say what the extension is. The last four suit an
|
|
53
|
+
extension that tunes something the app already has a section for. A section
|
|
54
|
+
holding no panel is not shown.
|
|
55
|
+
|
|
56
|
+
The section is declared twice: in the **manifest**, which is what the catalog
|
|
57
|
+
reviews and what the app places the panel by, and on the **panel**, for an app
|
|
58
|
+
older than the manifest field. In `manifest.json`:
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{
|
|
62
|
+
"key": "w7abc-park-notes",
|
|
63
|
+
"category": "activity",
|
|
64
|
+
"hooks": ["settingsPanel"],
|
|
65
|
+
"settings": { "section": "activities" }
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
And where the panel is registered:
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
api.registerHook('settingsPanel', {
|
|
73
|
+
hook: {
|
|
74
|
+
kind: 'simple',
|
|
75
|
+
title: 'Park Notes',
|
|
76
|
+
section: 'activities',
|
|
77
|
+
sidebar: false,
|
|
78
|
+
fields: [ /* … */ ],
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
`settings` has three keys, all optional:
|
|
84
|
+
|
|
85
|
+
- **`section`** — the key of the section, from the table above.
|
|
86
|
+
- **`sidebar: true`** — a panel that is a category of its own (no `section`,
|
|
87
|
+
or one the app does not have) may also have an entry in the Settings
|
|
88
|
+
sidebar. A panel placed in a section is a row there and never has one.
|
|
89
|
+
Reviewed.
|
|
90
|
+
- **`common: true`** — the panel's fields flagged `common: true` may also show
|
|
91
|
+
in Common Preferences. Reviewed.
|
|
92
|
+
|
|
93
|
+
### What is reviewed
|
|
94
|
+
|
|
95
|
+
The catalog reads a manifest and never runs a bundle, so the manifest is what
|
|
96
|
+
it reviews. An upload is held for an admin — even one from a trusted
|
|
97
|
+
publisher, whose uploads otherwise skip the queue — when its manifest:
|
|
98
|
+
|
|
99
|
+
- lists `settingsPanel` in `hooks` and names no `settings.section` — the panel
|
|
100
|
+
would be a category of its own;
|
|
101
|
+
- names a `settings.section` outside the table above — a new category, which
|
|
102
|
+
the app also has to know (a section the app does not know is shown as a
|
|
103
|
+
category of its own);
|
|
104
|
+
- sets `settings.sidebar` or `settings.common`.
|
|
105
|
+
|
|
106
|
+
A placement an admin has approved stays approved: a later version whose
|
|
107
|
+
`settings` are unchanged is not held for it again. To ask for a new category
|
|
108
|
+
or a sidebar entry, declare it and say why in the release notes; the reviewer
|
|
109
|
+
reads both. `npm run pack` (`h2kext-pack`) prints `held for review on the
|
|
110
|
+
catalog` for each of these, so it is no surprise.
|
|
111
|
+
|
|
112
|
+
### What the app enforces
|
|
113
|
+
|
|
114
|
+
The manifest is a promise the code could break, so the app holds every
|
|
115
|
+
extension it did not ship to its manifest, whatever the panel asks for:
|
|
116
|
+
|
|
117
|
+
- the panel goes in the manifest's `settings.section`; with none declared, in
|
|
118
|
+
the panel's own `section` if it is one of the table's; otherwise it is a
|
|
119
|
+
category of its own;
|
|
120
|
+
- it has a sidebar entry only when it is a category of its own, the panel's
|
|
121
|
+
`sidebar` is not false AND the manifest declares `sidebar: true` — so with
|
|
122
|
+
no `settings`, `sidebar` reads as false;
|
|
123
|
+
- its `common: true` fields reach Common Preferences only when the manifest
|
|
124
|
+
declares `common: true`; otherwise the flag is ignored and the fields stay
|
|
125
|
+
in the panel.
|
|
126
|
+
|
|
127
|
+
A panel from an extension whose manifest `hooks` does not list
|
|
128
|
+
`settingsPanel` is not shown at all: the catalog decides what to review by
|
|
129
|
+
that list, so an undeclared panel is one nobody was asked about.
|
|
130
|
+
`buildExtension` fails the build when the bundle registers a panel its
|
|
131
|
+
manifest does not declare, unless it cannot activate the bundle to find out,
|
|
132
|
+
in which case it warns.
|
|
133
|
+
|
|
134
|
+
An extension installed from a `.h2kext` file never passed through the
|
|
135
|
+
catalog, so nobody reviewed its manifest: the app takes its `settings` as
|
|
136
|
+
written, `sidebar` and `common` included. Installing a file is the
|
|
137
|
+
operator's own choice to trust it.
|
|
138
|
+
|
|
139
|
+
Everything else about a panel is untouched: `dataFilesSection` still adds its
|
|
140
|
+
row to the Data Files screen, and `target` still reaches the Logging and
|
|
141
|
+
Developer dialogs (see [Settings targets](#settings-targets)).
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
29
145
|
## Key namespacing
|
|
30
146
|
|
|
31
147
|
Wherever an extension can define more than one of something under one
|
|
@@ -76,7 +192,9 @@ export interface SimpleSettingsPanel {
|
|
|
76
192
|
order?: number;
|
|
77
193
|
// Defaults true. Set false to keep this panel out of the app's top-level
|
|
78
194
|
// settings navigation (the sidebar list). Independent of dataFilesSection
|
|
79
|
-
// below — this only controls the top-level nav.
|
|
195
|
+
// below — this only controls the top-level nav. An extension the app did
|
|
196
|
+
// not ship also needs the manifest's `settings.sidebar: true`, which is
|
|
197
|
+
// reviewed; see "Where an extension's settings go".
|
|
80
198
|
sidebar?: boolean;
|
|
81
199
|
// Defaults false. Set true to also show this panel as a row in the Data
|
|
82
200
|
// Files screen's own "Extensions" section — leave this false for anything
|
|
@@ -85,10 +203,12 @@ export interface SimpleSettingsPanel {
|
|
|
85
203
|
// the type level — inferring this from `sidebar: false` alone would sweep
|
|
86
204
|
// any sidebar-opt-out panel in here.
|
|
87
205
|
dataFilesSection?: boolean;
|
|
88
|
-
// The key of one of the app's own settings sections ('
|
|
89
|
-
//
|
|
90
|
-
//
|
|
91
|
-
//
|
|
206
|
+
// The key of one of the app's own settings sections ('activities',
|
|
207
|
+
// 'spotting', … — see "Where an extension's settings go") to show this
|
|
208
|
+
// panel inside, as one row that opens it in a dialog — instead of a
|
|
209
|
+
// section of its own in Settings and a sidebar entry, whatever `sidebar`
|
|
210
|
+
// says. Declare the same key as the manifest's `settings.section`, which is
|
|
211
|
+
// what the app places the panel by. An app without that section (an older
|
|
92
212
|
// one, or a key it doesn't know) shows the panel as if this weren't set,
|
|
93
213
|
// so it needs no newer API level.
|
|
94
214
|
section?: string;
|
|
@@ -363,8 +483,11 @@ override) without it cluttering the panel for regular users:
|
|
|
363
483
|
A panel with nothing to show at the current developer-mode setting is left
|
|
364
484
|
out of the Settings screen's list of categories rather than shown as an empty
|
|
365
485
|
heading, so a panel whose every field is `devMode` appears there only while
|
|
366
|
-
developer mode is on.
|
|
367
|
-
|
|
486
|
+
developer mode is on. A panel placed in a `section` is treated the same way:
|
|
487
|
+
its row there is a developer-mode row when every field it has is `devMode`,
|
|
488
|
+
and it has no row at all when it has no fields on this platform. Its sidebar
|
|
489
|
+
entry is not: give such a panel `sidebar: false`, or the entry opens on an
|
|
490
|
+
empty page.
|
|
368
491
|
|
|
369
492
|
## `aliases`: short names for the SET command
|
|
370
493
|
|
|
@@ -404,7 +527,10 @@ maintained as a separate list somewhere else in the app. Any field, link, or
|
|
|
404
527
|
action (core-declared or extension-declared, Tier 1 or Tier 2 alike) can set:
|
|
405
528
|
|
|
406
529
|
- **`common: true`** — also show this element in the Common Preferences
|
|
407
|
-
section, on top of its own group's. Off by default.
|
|
530
|
+
section, on top of its own group's. Off by default. An extension's
|
|
531
|
+
`common` fields reach Common Preferences only when its manifest declares
|
|
532
|
+
`settings.common: true`, which is reviewed — see
|
|
533
|
+
[Where an extension's settings go](#where-an-extensions-settings-go). Not the same thing as
|
|
408
534
|
`FormFieldOption.common`/`uncommon` above — that's a `multiselect`
|
|
409
535
|
option's own disclosure tier (upfront vs. behind "Show more"), a
|
|
410
536
|
different scope (an option inside one field, not the field itself).
|