@vestra-player/sdk 1.5.27 → 1.5.29
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 +20 -0
- package/bin/vestra-plugin.mjs +103 -0
- package/dist/commands.d.ts +47 -1
- package/dist/commands.js +79 -6
- package/dist/player-runtime.d.ts +1 -1
- package/dist/player-runtime.js +1 -1
- package/dist/plugin/commands.js +29 -2
- package/dist/plugin/testing.d.ts +54 -3
- package/dist/plugin/testing.js +69 -3
- package/dist/plugin/types.d.ts +81 -0
- package/llms-full.txt +194 -13
- package/llms.txt +22 -22
- package/package.json +1 -1
- package/slint/vestra/bar-buttons.slint +138 -0
- package/slint/vestra/icons.slint +4 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// Command buttons of a bottom bar (player 0.5.10, SDK 1.5.29): the buttons
|
|
2
|
+
// that plugins' commands contribute (`commands.add({ button })`) and the
|
|
3
|
+
// player's sidebar toggle, rightmost. The player fills `BarButtonsHost` in
|
|
4
|
+
// every window it composes and runs the clicks; a bottom bar places one
|
|
5
|
+
// `BarButtons` in its own layout and gives it the width it can spare:
|
|
6
|
+
// import { BarButtons } from "@vestra/bar-buttons.slint";
|
|
7
|
+
// strip := BarButtons { x: parent.width - self.width - 4px; room: ...; }
|
|
8
|
+
// It shows as many 41×40 cells as fit in `room`, the strip as wide as the
|
|
9
|
+
// cells shown (`width`). Cells go from the strip's outer (left) end inward:
|
|
10
|
+
// of the plugins' buttons (ascending `order`, left to right) the lowest
|
|
11
|
+
// order goes first, and the sidebar toggle goes last. A bar without a `BarButtons` shows none of them (their menu
|
|
12
|
+
// entries stay; the player logs which buttons are hidden).
|
|
13
|
+
//
|
|
14
|
+
// The cells look like the bar's own icon buttons: a 32×32 plate on hover
|
|
15
|
+
// and press, the V-Line icon in the text colour (accent while a toggle is
|
|
16
|
+
// on), the bar's tooltip (ToolTipArea). They are persistent elements shown with
|
|
17
|
+
// `visible:`; nothing is created on hover or resize.
|
|
18
|
+
import { Theme } from "theme.slint";
|
|
19
|
+
import { Icon } from "icons.slint";
|
|
20
|
+
import { ToolTipArea } from "widgets.slint";
|
|
21
|
+
|
|
22
|
+
// One button as the player shows it.
|
|
23
|
+
export struct BarButtonItem {
|
|
24
|
+
// What a click runs (the player's own token; "" for no button).
|
|
25
|
+
token: string,
|
|
26
|
+
// A name of @vestra/icons.slint, or "" for `image`.
|
|
27
|
+
icon: string,
|
|
28
|
+
// The plugin's image (`plugin.ui.image`), drawn in the icon colour.
|
|
29
|
+
image: image,
|
|
30
|
+
// The command's title (the accessibility label).
|
|
31
|
+
label: string,
|
|
32
|
+
// The tooltip: the title and its key, the reason it is unavailable.
|
|
33
|
+
tip: string,
|
|
34
|
+
enabled: bool,
|
|
35
|
+
// The command has a checked state; `checked` draws the icon in the accent.
|
|
36
|
+
checkable: bool,
|
|
37
|
+
checked: bool,
|
|
38
|
+
// At half opacity: on, but not shown for want of room (the sidebar).
|
|
39
|
+
dimmed: bool,
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Filled by the player; a bar reads it only through `BarButtons`.
|
|
43
|
+
export global BarButtonsHost {
|
|
44
|
+
// The plugins' buttons, left to right, at most 8.
|
|
45
|
+
in property <[BarButtonItem]> buttons;
|
|
46
|
+
// The sidebar toggle (`token` "" while there is none).
|
|
47
|
+
in property <BarButtonItem> toggle;
|
|
48
|
+
// Set when a `BarButtons` exists in this window.
|
|
49
|
+
in-out property <bool> placed;
|
|
50
|
+
// A click on the cell with this token.
|
|
51
|
+
callback clicked(string);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// One 41×40 cell (the bar's BarButton). `shown`: on screen; a hidden cell
|
|
55
|
+
// is not actionable from the accessibility tree either.
|
|
56
|
+
component Cell inherits Rectangle {
|
|
57
|
+
in property <BarButtonItem> item;
|
|
58
|
+
in property <bool> shown;
|
|
59
|
+
private property <bool> live: root.shown && root.item.enabled;
|
|
60
|
+
private property <brush> tint: !root.item.enabled ? Theme.icon-disabled
|
|
61
|
+
: root.item.checked ? (touch.pressed ? Theme.accent-press : Theme.accent)
|
|
62
|
+
: Theme.text;
|
|
63
|
+
width: 41px;
|
|
64
|
+
height: 40px;
|
|
65
|
+
visible: root.shown;
|
|
66
|
+
opacity: root.item.dimmed ? 0.5 : 1;
|
|
67
|
+
accessible-role: button;
|
|
68
|
+
accessible-label: root.item.label;
|
|
69
|
+
accessible-description: root.item.tip;
|
|
70
|
+
accessible-enabled: root.live;
|
|
71
|
+
accessible-checkable: root.item.checkable;
|
|
72
|
+
accessible-checked: root.item.checked;
|
|
73
|
+
accessible-action-default => { if root.live { BarButtonsHost.clicked(root.item.token); } }
|
|
74
|
+
Rectangle {
|
|
75
|
+
x: 4px;
|
|
76
|
+
y: 4px;
|
|
77
|
+
width: parent.width - 9px;
|
|
78
|
+
height: parent.height - 8px;
|
|
79
|
+
border-radius: Theme.radius-panel;
|
|
80
|
+
background: !root.live ? transparent
|
|
81
|
+
: touch.pressed ? Theme.press-bg
|
|
82
|
+
: touch.has-hover ? Theme.hover-bg : transparent;
|
|
83
|
+
}
|
|
84
|
+
Icon {
|
|
85
|
+
visible: root.item.icon != "";
|
|
86
|
+
x: (root.width - 1px - self.width) / 2;
|
|
87
|
+
y: (root.height - self.height) / 2;
|
|
88
|
+
name: root.item.icon;
|
|
89
|
+
color: root.tint;
|
|
90
|
+
}
|
|
91
|
+
// A plugin's image in the icon box (14×12), aspect kept, coloured like the icons.
|
|
92
|
+
Image {
|
|
93
|
+
visible: root.item.icon == "";
|
|
94
|
+
x: (root.width - 1px - self.width) / 2;
|
|
95
|
+
y: (root.height - self.height) / 2;
|
|
96
|
+
width: 14px;
|
|
97
|
+
height: 12px;
|
|
98
|
+
source: root.item.image;
|
|
99
|
+
image-fit: contain;
|
|
100
|
+
colorize: root.tint;
|
|
101
|
+
}
|
|
102
|
+
ToolTipArea {
|
|
103
|
+
width: 100%;
|
|
104
|
+
height: 100%;
|
|
105
|
+
text: root.shown ? root.item.tip : "";
|
|
106
|
+
touch := TouchArea {
|
|
107
|
+
enabled: root.live;
|
|
108
|
+
clicked => { BarButtonsHost.clicked(root.item.token); }
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// The strip: place it at the bar's right end and give it the width you can
|
|
114
|
+
// spare; it is as wide as the cells it shows (read `width` to lay out the rest).
|
|
115
|
+
export component BarButtons {
|
|
116
|
+
// The width the bar can give the strip; the cells that fit show.
|
|
117
|
+
in property <length> room;
|
|
118
|
+
// The index (in the player's list, ascending order) of the leftmost
|
|
119
|
+
// plugin button shown; the ones before it are hidden for want of room.
|
|
120
|
+
out property <int> first-shown: BarButtonsHost.buttons.length - root.count;
|
|
121
|
+
// The cells that fit in `room`.
|
|
122
|
+
private property <int> fit: Math.max(0, Math.floor(root.room / 41px));
|
|
123
|
+
private property <bool> toggle: BarButtonsHost.toggle.token != "" && root.fit >= 1;
|
|
124
|
+
// The plugins' buttons shown: the highest orders, left of the toggle's cell.
|
|
125
|
+
private property <int> count: Math.max(0, Math.min(BarButtonsHost.buttons.length, root.fit - (root.toggle ? 1 : 0)));
|
|
126
|
+
width: (root.count + (root.toggle ? 1 : 0)) * 41px;
|
|
127
|
+
height: 40px;
|
|
128
|
+
init => { BarButtonsHost.placed = true; }
|
|
129
|
+
Cell { x: (0 - root.first-shown) * 41px; shown: 0 >= root.first-shown && 0 < BarButtonsHost.buttons.length; item: BarButtonsHost.buttons[0]; }
|
|
130
|
+
Cell { x: (1 - root.first-shown) * 41px; shown: 1 >= root.first-shown && 1 < BarButtonsHost.buttons.length; item: BarButtonsHost.buttons[1]; }
|
|
131
|
+
Cell { x: (2 - root.first-shown) * 41px; shown: 2 >= root.first-shown && 2 < BarButtonsHost.buttons.length; item: BarButtonsHost.buttons[2]; }
|
|
132
|
+
Cell { x: (3 - root.first-shown) * 41px; shown: 3 >= root.first-shown && 3 < BarButtonsHost.buttons.length; item: BarButtonsHost.buttons[3]; }
|
|
133
|
+
Cell { x: (4 - root.first-shown) * 41px; shown: 4 >= root.first-shown && 4 < BarButtonsHost.buttons.length; item: BarButtonsHost.buttons[4]; }
|
|
134
|
+
Cell { x: (5 - root.first-shown) * 41px; shown: 5 >= root.first-shown && 5 < BarButtonsHost.buttons.length; item: BarButtonsHost.buttons[5]; }
|
|
135
|
+
Cell { x: (6 - root.first-shown) * 41px; shown: 6 >= root.first-shown && 6 < BarButtonsHost.buttons.length; item: BarButtonsHost.buttons[6]; }
|
|
136
|
+
Cell { x: (7 - root.first-shown) * 41px; shown: 7 >= root.first-shown && 7 < BarButtonsHost.buttons.length; item: BarButtonsHost.buttons[7]; }
|
|
137
|
+
Cell { x: root.count * 41px; shown: root.toggle; item: BarButtonsHost.toggle; }
|
|
138
|
+
}
|
package/slint/vestra/icons.slint
CHANGED
|
@@ -48,6 +48,10 @@ export global Icons {
|
|
|
48
48
|
// Four corners pointing out (enter) or in (leave), the default 14 × 12 box.
|
|
49
49
|
if name == "fullscreen" { return "M 1.5 4.5 V 1.5 H 4.5 M 9.5 1.5 H 12.5 V 4.5 M 12.5 7.5 V 10.5 H 9.5 M 4.5 10.5 H 1.5 V 7.5"; }
|
|
50
50
|
if name == "exit-fullscreen" { return "M 4.5 1.5 V 4.5 H 1.5 M 9.5 1.5 V 4.5 H 12.5 M 12.5 7.5 H 9.5 V 10.5 M 1.5 7.5 H 4.5 V 10.5"; }
|
|
51
|
+
// A shopping bag (the plugin store) and a four-point sparkle with a
|
|
52
|
+
// small cross (AI), the default 14 × 12 box; bar buttons use them.
|
|
53
|
+
if name == "store" { return "M 2.5 4 H 11.5 L 10.9 9.6 Q 10.8 10.5 9.9 10.5 H 4.1 Q 3.2 10.5 3.1 9.6 Z M 5.2 4 V 3.3 A 1.8 1.8 0 0 1 8.8 3.3 V 4"; }
|
|
54
|
+
if name == "ai" { return "M 6 1.5 Q 6.6 5.4 10.5 6 Q 6.6 6.6 6 10.5 Q 5.4 6.6 1.5 6 Q 5.4 5.4 6 1.5 Z M 11.5 1.2 V 3.8 M 10.2 2.5 H 12.8"; }
|
|
51
55
|
return "";
|
|
52
56
|
}
|
|
53
57
|
// Line width.
|