@vestra-player/sdk 1.5.58 → 1.6.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/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.6.0
4
+
5
+ **Who must change: nobody.** No change to the TypeScript API, the wire or `TestHost`, `apiVersion` stays `vestra/1`, no new capability. New since 1.5.58 for plugin authors: Markdown the user can select and copy (`selectable` on `MarkdownView` and `MarkdownBlocks`, `plain` and `links` on `MarkdownBlock`, in the SDK's copy of the player's `@vestra/markdown.slint`; a plugin that uses them sets `"minPlayerVersion": "0.6.8"`), and, from player 0.6.7, plugins started on demand by default: a plugin starts on its first use and is stopped when idle, so `activate` can run many times and must never wait for its own commands or views (see 1.5.58). This is a minor release because it adds backward-compatible API and marks that milestone; nothing is removed or changed, and a plugin built with 1.5.x keeps working as it is.
6
+
7
+ - **Selectable Markdown** (player 0.6.8; the SDK's `slint/vestra/markdown.slint` is synced with the player's). `MarkdownView` and `MarkdownBlocks` take `in property <bool> selectable: false`. With `true`, a paragraph, heading, list item or quote without links is shown as its plain text in a read-only selectable text field (right-click Copy / Select All, where Copy with nothing selected copies the whole block; Ctrl+C / Ctrl+A; each field is a Tab stop); a block with links keeps its clickable links, and its right-click menu copies it as plain text with each address after its link text, `text (url)`, plus Copy Link when it has one link. Code blocks are always selectable, whatever `selectable` says (in player 0.6.8 this applies to every plugin's Markdown). A selection stays inside one block and is lost when its row scrolls out of a `MarkdownView`. `MarkdownBlock` gains `plain: string` (the block as plain text) and `links: [string]` (its link addresses). Older players do not have the property: set `"minPlayerVersion": "0.6.8"` before using it. See [Reference: theme › Markdown](docs/reference/theme.md#markdown).
8
+ - **Start retries corrected** ([How the player runs and talks to plugins](docs/explanation/host-and-node.md#the-start-deadline), [Reference: limits](docs/reference/limits.md#plugin-processes), [How a plugin runs](docs/explanation/plugins.md#restarts-activate-can-run-more-than-once)). 1.5.58 said a start that is not ready within the start timeout is tried up to three more times. That was player 0.6.6; from player 0.6.7 a timed-out start gets one try (60 s) and is not retried, and only a process that cannot be created is tried again (about 250 ms, 500 ms and 1 s apart).
9
+
3
10
  ## 1.5.58
4
11
 
5
12
  **Who must change: nobody.** Documentation only: no change to the TypeScript API, the wire or `TestHost`, `apiVersion` stays `vestra/1`, no new capability, no player version needed. Plugin authors should read what the player's new plugin supervisor does with their plugin (player 0.6.6, and the defaults planned for 0.6.7), and check that `activate` never waits for its own commands or views.
Binary file
@@ -1773,6 +1773,13 @@ export interface Ui {
1773
1773
  * the list on every streamed chunk keeps the scroll position and costs
1774
1774
  * little.
1775
1775
  *
1776
+ * From player 0.6.8 both views take `selectable: true` (default `false`):
1777
+ * the user can select and copy the text, one block at a time; blocks with
1778
+ * links keep their clickable links and copy as `text (url)`. Code blocks
1779
+ * are always selectable. `MarkdownBlock.plain` (the block as plain text)
1780
+ * and `MarkdownBlock.links` (its link addresses) are readable in Slint.
1781
+ * See [Reference: theme › Markdown](../../docs/reference/theme.md#markdown).
1782
+ *
1776
1783
  * @capability None.
1777
1784
  * @player 0.2.0 (set `"minPlayerVersion": "0.2.0"` in the manifest)
1778
1785
  *
package/llms.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  # Vestra Player SDK
2
2
 
3
- > @vestra-player/sdk 1.5.58: write plugins for Vestra Player in TypeScript (plugin API `vestra/1`). A plugin is a folder with `manifest.json` and an entry module whose default export `activate(plugin)` the player calls. The documentation is a tree of short pages read by path, like `go doc`: the same pages and API as https://vestrasys.github.io/vestra-player-sdk/.
3
+ > @vestra-player/sdk 1.6.0: write plugins for Vestra Player in TypeScript (plugin API `vestra/1`). A plugin is a folder with `manifest.json` and an entry module whose default export `activate(plugin)` the player calls. The documentation is a tree of short pages read by path, like `go doc`: the same pages and API as https://vestrasys.github.io/vestra-player-sdk/.
4
4
 
5
5
  ## Read the documentation
6
6
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vestra-player/sdk",
3
- "version": "1.5.58",
3
+ "version": "1.6.0",
4
4
  "description": "Plugin API types, test host and plugin CLI for Vestra Player (apiVersion vestra/1)",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -9,7 +9,15 @@
9
9
  // row (a chat message: a `[MarkdownBlock]` field of the row's struct).
10
10
  // `code-copy: true` adds a Copy button to code blocks that reports
11
11
  // `copy-code(code)`; the plugin copies it (`plugin.clipboard`).
12
- import { ListView } from "std-widgets.slint";
12
+ // `selectable: true` lets the user select and copy text with the mouse:
13
+ // paragraphs, headings, list items and quotes without links then show their
14
+ // plain text (`MarkdownBlock.plain`, no inline styles) in a read-only text
15
+ // field, one field per block, with a Copy / Select All menu. A block with
16
+ // links keeps its styled text (links stay clickable); its right-click menu
17
+ // copies the block as plain text with each address after its link text,
18
+ // `text (url)`, and offers Copy Link when the block has one link. Code
19
+ // blocks are always selectable.
20
+ import { ListView, Palette } from "std-widgets.slint";
13
21
  import { Theme } from "theme.slint";
14
22
  import { Icon } from "icons.slint";
15
23
 
@@ -36,21 +44,130 @@ export struct MarkdownBlock {
36
44
  // Task list item: 0 none, 1 open, 2 done (a drawn box, no font glyph).
37
45
  task: int,
38
46
  text: styled-text,
47
+ // The block's text without styles, what `selectable` shows: a code
48
+ // block's code, a table's cells (tab-separated lines), an image's alt.
49
+ plain: string,
39
50
  code: string,
40
51
  image: image,
41
52
  has-image: bool,
42
53
  image-width: int,
43
54
  image-height: int,
44
55
  alt: string,
56
+ // The addresses of the block's links, in order.
57
+ links: [string],
45
58
  rows: [MarkdownRow],
46
59
  // Table column alignment: "left", "center", "right" or "" (left).
47
60
  aligns: [string],
48
61
  }
49
62
 
63
+ // Read-only text the user can select: a right-click menu with Copy and
64
+ // Select All (as Slint's own text fields; Copy without a selection copies
65
+ // the whole block), and Ctrl+C / Ctrl+A (⌘C / ⌘A) while it has focus. No
66
+ // caret, as selectable text on a web page. Each one is a Tab stop, and
67
+ // while one has focus the arrow keys move in it (Slint 1.18's read-only
68
+ // TextInput).
69
+ component SelectableText {
70
+ in property <string> text;
71
+ in property <brush> color: Theme.text;
72
+ in property <length> font-size: Theme.font-tab;
73
+ in property <int> font-weight: 400;
74
+ in property <string> font-family;
75
+ min-height: input.min-height;
76
+ preferred-height: input.preferred-height;
77
+ ContextMenuArea {
78
+ Menu {
79
+ MenuItem {
80
+ title: @tr("Copy");
81
+ enabled: root.text != "";
82
+ activated => {
83
+ if input.anchor-position-byte-offset == input.cursor-position-byte-offset {
84
+ input.select-all();
85
+ input.copy();
86
+ input.clear-selection();
87
+ } else {
88
+ input.copy();
89
+ }
90
+ }
91
+ }
92
+ MenuItem {
93
+ title: @tr("Select All");
94
+ enabled: root.text != "";
95
+ activated => { input.select-all(); }
96
+ }
97
+ }
98
+ input := TextInput {
99
+ width: root.width;
100
+ height: root.height;
101
+ text: root.text;
102
+ read-only: true;
103
+ single-line: false;
104
+ wrap: word-wrap;
105
+ color: root.color;
106
+ font-size: root.font-size;
107
+ font-weight: root.font-weight;
108
+ font-family: root.font-family;
109
+ text-cursor-width: 0px;
110
+ // The std-widgets LineEdit's selection colours, legible in both
111
+ // palettes (as the info plugin's properties).
112
+ selection-background-color: Palette.selection-background;
113
+ selection-foreground-color: Palette.selection-foreground;
114
+ }
115
+ }
116
+ }
117
+
118
+ // A block with links in a selectable view: its styled text (links stay
119
+ // clickable) under a right-click menu that copies `plain` (with the
120
+ // addresses) and, for one link, the link. The menu lies above the text: a
121
+ // left click passes through it to the links.
122
+ component LinkText {
123
+ in property <styled-text> text;
124
+ in property <string> plain;
125
+ in property <[string]> links;
126
+ in property <brush> color: Theme.text;
127
+ in property <length> font-size: Theme.font-tab;
128
+ callback link-clicked(string);
129
+ min-height: styled.min-height;
130
+ preferred-height: styled.preferred-height;
131
+ function put(text: string) {
132
+ clip.text = text;
133
+ clip.select-all();
134
+ clip.copy();
135
+ }
136
+ styled := StyledText {
137
+ width: root.width;
138
+ height: root.height;
139
+ text: root.text;
140
+ default-color: root.color;
141
+ default-font-size: root.font-size;
142
+ link-color: Theme.accent;
143
+ link-clicked(url) => { root.link-clicked(url); }
144
+ }
145
+ ContextMenuArea {
146
+ Menu {
147
+ MenuItem {
148
+ title: @tr("Copy");
149
+ activated => { root.put(root.plain); }
150
+ }
151
+ if root.links.length == 1: MenuItem {
152
+ title: @tr("Copy Link");
153
+ activated => { root.put(root.links[0]); }
154
+ }
155
+ }
156
+ }
157
+ // Puts text on the clipboard (Slint has no clipboard function).
158
+ clip := TextInput {
159
+ visible: false;
160
+ width: 0px;
161
+ height: 0px;
162
+ read-only: true;
163
+ }
164
+ }
165
+
50
166
  component MarkdownBlockView {
51
167
  in property <MarkdownBlock> block;
52
168
  in property <length> available;
53
169
  in property <bool> code-copy;
170
+ in property <bool> selectable;
54
171
  callback link-clicked(string);
55
172
  callback copy-code(string);
56
173
  private property <length> quote-indent: block.quote * 12px;
@@ -61,7 +178,21 @@ component MarkdownBlockView {
61
178
  HorizontalLayout {
62
179
  padding-left: root.quote-indent + root.list-indent;
63
180
  VerticalLayout {
64
- if block.kind == "heading": StyledText {
181
+ if block.kind == "heading" && root.selectable && block.links.length > 0: LinkText {
182
+ width: root.inner;
183
+ text: block.text;
184
+ plain: block.plain;
185
+ links: block.links;
186
+ font-size: root.heading-size;
187
+ link-clicked(url) => { root.link-clicked(url); }
188
+ }
189
+ if block.kind == "heading" && root.selectable && block.links.length == 0: SelectableText {
190
+ width: root.inner;
191
+ text: block.plain;
192
+ font-size: root.heading-size;
193
+ font-weight: 700;
194
+ }
195
+ if block.kind == "heading" && !root.selectable: StyledText {
65
196
  width: root.inner;
66
197
  text: block.text;
67
198
  default-color: Theme.text;
@@ -69,7 +200,20 @@ component MarkdownBlockView {
69
200
  link-color: Theme.accent;
70
201
  link-clicked(url) => { root.link-clicked(url); }
71
202
  }
72
- if block.kind == "paragraph": StyledText {
203
+ if block.kind == "paragraph" && root.selectable && block.links.length > 0: LinkText {
204
+ width: root.inner;
205
+ text: block.text;
206
+ plain: block.plain;
207
+ links: block.links;
208
+ color: block.quote > 0 ? Theme.text-dim : Theme.text;
209
+ link-clicked(url) => { root.link-clicked(url); }
210
+ }
211
+ if block.kind == "paragraph" && root.selectable && block.links.length == 0: SelectableText {
212
+ width: root.inner;
213
+ text: block.plain;
214
+ color: block.quote > 0 ? Theme.text-dim : Theme.text;
215
+ }
216
+ if block.kind == "paragraph" && !root.selectable: StyledText {
73
217
  width: root.inner;
74
218
  text: block.text;
75
219
  default-color: block.quote > 0 ? Theme.text-dim : Theme.text;
@@ -106,7 +250,18 @@ component MarkdownBlockView {
106
250
  }
107
251
  }
108
252
  }
109
- StyledText {
253
+ if root.selectable && block.links.length > 0: LinkText {
254
+ width: root.inner - 20px;
255
+ text: block.text;
256
+ plain: block.plain;
257
+ links: block.links;
258
+ link-clicked(url) => { root.link-clicked(url); }
259
+ }
260
+ if root.selectable && block.links.length == 0: SelectableText {
261
+ width: root.inner - 20px;
262
+ text: block.plain;
263
+ }
264
+ if !root.selectable: StyledText {
110
265
  width: root.inner - 20px;
111
266
  text: block.text;
112
267
  default-color: Theme.text;
@@ -123,12 +278,12 @@ component MarkdownBlockView {
123
278
  VerticalLayout {
124
279
  padding: 6px;
125
280
  // Plain lines in the monospace font; CJK falls back.
126
- StyledText {
281
+ // Always selectable: code is there to be copied.
282
+ SelectableText {
127
283
  width: root.inner - 12px;
128
- text: block.text;
129
- default-color: Theme.text;
130
- default-font-family: Theme.font-mono;
131
- default-font-size: Theme.font-body;
284
+ text: block.code;
285
+ font-family: Theme.font-mono;
286
+ font-size: Theme.font-body;
132
287
  }
133
288
  }
134
289
  if root.code-copy: Rectangle {
@@ -216,6 +371,8 @@ export component MarkdownBlocks inherits Rectangle {
216
371
  in property <[MarkdownBlock]> blocks;
217
372
  // A Copy button on code blocks, reporting `copy-code(code)`.
218
373
  in property <bool> code-copy: false;
374
+ // Text the user can select and copy (see the top of this file).
375
+ in property <bool> selectable: false;
219
376
  callback link-clicked(string);
220
377
  callback copy-code(string);
221
378
  min-height: column.min-height;
@@ -228,6 +385,7 @@ export component MarkdownBlocks inherits Rectangle {
228
385
  block: block;
229
386
  available: root.width;
230
387
  code-copy: root.code-copy;
388
+ selectable: root.selectable;
231
389
  link-clicked(url) => { root.link-clicked(url); }
232
390
  copy-code(code) => { root.copy-code(code); }
233
391
  }
@@ -244,6 +402,10 @@ export component MarkdownView inherits Rectangle {
244
402
  in property <length> inset: 10px;
245
403
  // A Copy button on code blocks, reporting `copy-code(code)`.
246
404
  in property <bool> code-copy: false;
405
+ // Text the user can select and copy (see the top of this file). A
406
+ // selection is lost when its block scrolls out of view (the `ListView`
407
+ // drops the row).
408
+ in property <bool> selectable: false;
247
409
  callback link-clicked(string);
248
410
  callback copy-code(string);
249
411
  list := ListView {
@@ -261,6 +423,7 @@ export component MarkdownView inherits Rectangle {
261
423
  block: block;
262
424
  available: self.width;
263
425
  code-copy: root.code-copy;
426
+ selectable: root.selectable;
264
427
  link-clicked(url) => { root.link-clicked(url); }
265
428
  copy-code(code) => { root.copy-code(code); }
266
429
  }