Le manifeste
manifest.json dit à PlayerVox OverCrow ce qu’est un widget avant que son
code ne s’exécute : son identité et sa version, ses noms, les tailles qu’il
accepte, les permissions qu’il demande et les lignes qu’il ajoute à son menu
d’options. Vous l’écrivez à la main ; il est empaqueté tel quel.
Le fichier est un seul objet JSON strict. Une marque d’ordre des octets, une clé en double, des données après l’objet ou un champ inconnu le font refuser : PlayerVox OverCrow n’ignore aucun champ.
Un exemple complet
{
"schemaVersion": 1,
"apiVersion": 1,
"id": "{{id}}",
"version": "0.1.0",
"name": {
"en": "{{name}}",
"fr": "{{name}}"
},
"sizing": {
"fit": "none",
"preferred": { "width": 200, "height": 96 },
"min": { "width": 140, "height": 72 },
"max": { "width": 640, "height": 640 }
}
}overcrow-widget init écrit ce fichier ; {{id}} et {{name}} sont les
valeurs qu’il remplit. Voici un manifeste avec des permissions et un menu :
{
"schemaVersion": 1,
"apiVersion": 1,
"id": "nova.countdown",
"version": "1.0.0",
"name": { "en": "Countdown", "fr": "Compte à rebours" },
"sizing": {
"fit": "none",
"preferred": { "width": 220, "height": 190 },
"min": { "width": 180, "height": 160 },
"max": { "width": 480, "height": 400 }
},
"permissions": {
"storage": true
},
"wrapper": {
"menu": [
{
"type": "toggle",
"id": "show-rounds",
"label": { "en": "Show finished rounds", "fr": "Afficher les tours terminés" },
"icon": "circle-check",
"default": true
},
{
"type": "action",
"id": "reset-rounds",
"label": { "en": "Reset the rounds", "fr": "Remettre les tours à zéro" },
"icon": "rotate-ccw",
"visibleWhen": "show-rounds"
}
]
}
}Champs
| Champ | Type | Obligatoire | Signification |
|---|---|---|---|
schemaVersion | entier de 1 à 1 | oui | Version du document de manifeste. |
apiVersion | entier de 1 à 1 | oui | Version de l’API des widgets ; elle sélectionne ce schéma. |
id | widget ID | oui | ID du widget, de 3 octets à 128 octets : au moins deux segments de [a-z0-9-] séparés par des points, chacun d’au plus 63 octets, sans - au début ni à la fin ; <pseudo>.<nom> avec le pseudo de l’éditeur, ou un domaine vérifié de l’éditeur, inversé, suivi d’un nom. com.playervox et com.playervox.* sont réservés aux paquets signés par PlayerVox. |
version | version | oui | SemVer 2.0.0 MAJOR.MINOR.PATCH[-PRERELEASE] sous sa forme canonique, d’au plus 64 octets ; les métadonnées de build sont refusées. |
name | WidgetName | oui | Nom localisé du widget, affiché par l’hôte. |
sizing | Sizing | oui | Règles de taille et d’ajustement appliquées par le cadre du widget. |
vm | VmRequest | non | Budget demandé pour la VM ; absent, les valeurs par défaut s’appliquent. |
permissions | Permissions | non | Permissions demandées ; absent, aucune. |
wrapper | wrapper | non | Lignes du widget dans le menu d’options de l’hôte. |
requires | host features | non | Sources de données de l’hôte, distinctes, sans lesquelles le widget ne peut pas fonctionner, comme le requires d’une ligne de wrapper.menu. Sur une machine à laquelle il en manque une, l’hôte ne démarre ni n’affiche le widget et conserve sa place ; le widget revient quand la source revient. |
Identité et version
idest l’identité du widget partout : dans le catalogue, dans le profil de l’utilisateur, dans son stockage. Il s’écrit<pseudo>.<nom>, votre pseudo d’éditeur dans l’espace créateurs de PlayerVox OverCrow et un nom (nova.lol-timers), ou, une fois un domaine vérifié, ce domaine inversé et un nom (gg.nova.lol-timers). Un ID est définitif : il n’est jamais donné à un autre widget, même après la suppression du vôtre.nova,example,yourhandleetyournamesont des pseudos d’exemple sous lesquels personne ne peut publier, et les ID souscom.playervoxsont réservés aux widgets publiés par PlayerVox.versionest une version sémantique. Une version publiée ne change jamais : toute modification d’un widget publié est une nouvelle version, supérieure.schemaVersionetapiVersionvalent tous deux1.
Noms
name donne le nom que PlayerVox OverCrow affiche dans sa liste de widgets
et dans ses menus, en anglais et en français. Les deux sont obligatoires. Un
nom s’affiche tel qu’il est écrit : ni caractère de contrôle, ni caractère
invisible ou de sens d’écriture, comme U+200B (espace sans chasse) ou
U+202E (forçage de droite à gauche). Les libellés du menu suivent la même
règle.
| Champ | Type | Obligatoire | Signification |
|---|---|---|---|
en | name text | oui | Nom en anglais. |
fr | name text | oui | Nom en français. |
Tailles
sizing indique la taille du widget quand l’utilisateur l’ajoute, jusqu’où
celui-ci peut le réduire et l’agrandir, et si PlayerVox OverCrow peut
ajuster son cadre à son contenu. Les longueurs sont en pixels logiques, à
une échelle de 100 % ; l’échelle du contenu choisie par l’utilisateur (de 50
% à 175 %) les multiplie.
| Champ | Type | Obligatoire | Signification |
|---|---|---|---|
fit | none | both | height | oui | Ajustement au contenu que le widget accepte : sur les deux axes (both), en hauteur seulement (height) ou aucun (none). Le redimensionnement manuel reste toujours possible. |
defaultMode | fit | manual | non | Mode d’un widget nouvellement placé ; par défaut fit quand fit n’est pas none, sinon manual. fit avec fit: none est refusé. |
preferred | Dimensions | oui | Taille initiale ; entre min et max. |
min | Dimensions | oui | Plus petite taille. |
max | Dimensions | oui | Plus grande taille. |
preferred, min et max sont chacun une paire de dimensions, avec
min ≤ preferred ≤ max sur les deux axes :
| Champ | Type | Obligatoire | Signification |
|---|---|---|---|
width | entier de 1 à 4096 | oui | Pixels logiques. |
height | entier de 1 à 4096 | oui | Pixels logiques. |
Avec fit: "both", PlayerVox OverCrow donne au cadre la taille dont la vue
a besoin, dans les deux directions : l’Horloge grandit quand l’utilisateur
active les secondes. Avec fit: "height", l’utilisateur choisit la largeur
et la hauteur suit le contenu. Avec fit: "none", le cadre garde la taille
que l’utilisateur lui a donnée et la vue le remplit. L’utilisateur peut
toujours redimensionner à la main.
"sizing": {
"fit": "both",
"preferred": { "width": 110, "height": 60 },
"min": { "width": 40, "height": 24 },
"max": { "width": 480, "height": 240 }
},Permissions
Un widget n’obtient rien qu’il n’ait déclaré ici, et une déclaration n’accorde rien à elle seule : l’utilisateur donne d’abord son accord, dans le Centre de contrôle. Services et permissions explique chaque permission et ce qu’elle autorise.
| Champ | Type | Obligatoire | Signification |
|---|---|---|---|
network | liste de NetworkRule ≤ 32 | non | Règles réseau, distinctes. |
storage | booléen | non | Stockage clé-valeur tenu par l’hôte ; false par défaut. |
clipboardWrite | booléen | non | Écriture de texte dans le presse-papiers ; false par défaut. |
gameEvents | liste de game event ≤ 32 | non | Noms d’événements overcrow.game.<name>.v1, distincts. |
capabilities | capability names | non | Capabilities du schéma, distinctes. |
"permissions": {
"capabilities": ["stopwatch.read", "stopwatch.control"]
}Une règle réseau est un objet à part entière ; ses champs sont décrits avec les règles réseau.
Le menu d’options
Chaque widget a un menu d’options, ouvert depuis son cadre.
PlayerVox OverCrow y place d’abord ses propres lignes : opacité, taille du
contenu, ajustement au contenu et, si le widget en a besoin, son compte. La
visibilité en mode passif est l’œil de la barre d’outils du widget, pas une
ligne du menu. wrapper.menu ajoute les vôtres en dessous : bascules,
curseurs, choix, actions et groupes, chacun avec un libellé dans les deux
langues.
Le menu prend la largeur de sa ligne la plus large, de 248 à 320 points. Au-delà, un libellé se termine par « … » et s’affiche en entier dans une infobulle ; un choix montre sa valeur sur 120 points au plus. Gardez des libellés courts, dans les deux langues.
"wrapper": {
"menu": [
{
"type": "toggle",
"id": "show-seconds",
"label": { "en": "Show seconds", "fr": "Afficher les secondes" },
"default": false
},
{
"type": "toggle",
"id": "show-date",
"label": { "en": "Show date", "fr": "Afficher la date" },
"default": true
},
{
"type": "choice",
"id": "date-format",
"label": { "en": "Date format", "fr": "Format de date" },
"visibleWhen": "show-date",
"choices": [
{ "value": "day-month-year", "label": { "en": "dd/mm/yyyy", "fr": "jj/mm/aaaa" } },
{ "value": "year-month-day", "label": { "en": "yyyy-mm-dd", "fr": "aaaa-mm-jj" } },
{ "value": "month-day-year", "label": { "en": "mm/dd/yyyy", "fr": "mm/jj/aaaa" } }
],
"default": "day-month-year"
}
]
}PlayerVox OverCrow dessine les lignes, enregistre leurs valeurs dans le
profil de l’utilisateur et les donne à la logique : lisez une valeur avec
option(id, fallback) et suivez les changements avec onHost. Une ligne
action n’a pas de valeur : elle appelle le gestionnaire que vous avez
enregistré avec onMenu. Voir
le menu d’options dans la logique.
Une ligne du menu peut fixer l’une de ses valeurs déclarées ou envoyer son action, rien d’autre. Elle ne peut ni accorder une permission ni ouvrir un lien, et choisir une ligne n’est pas une action de l’utilisateur qui autorise un appel de service protégé.
Champs communs à toutes les lignes
| Champ | Type | Obligatoire | Signification |
|---|---|---|---|
type | toggle | slider | choice | action | group | oui | Type de la ligne. |
id | identifiant ≤ 48 octets | oui | Unique parmi toutes les lignes du widget ; clé de la valeur enregistrée. |
label | MenuLabel | oui | Libellé localisé de la ligne. |
icon | nom d’icône Lucide | non | Icône placée devant le libellé, prise dans la liste de l’hôte et dessinée par lui. |
visibleWhen | identifiant ≤ 48 octets | non | ID d’une ligne toggle déclarée plus haut ; cette ligne n’est affichée que tant que cette bascule est activée. |
requires | fps | telemetry.cpuTemperature | telemetry.gpuTemperature | non | Source de données de l’hôte ; l’hôte masque la ligne quand il ne peut pas la fournir. |
Une ligne dotée de visibleWhen ne s’affiche que tant que la bascule nommée
est activée : le format de date de l’Horloge apparaît quand la date est
affichée. Une ligne dotée de requires est masquée sur une machine qui ne
peut pas fournir cette donnée, comme les lignes de température du widget
Performances :
"requires": "telemetry.cpuTemperature",Une ligne group ouvre un sous-menu latéral avec ses propres lignes ; le
widget Performances range ses cinq bascules de mesures sous une seule ligne :
"type": "group",
"id": "shown-values",
"label": { "en": "Shown values", "fr": "Valeurs affichées" },
"rows": [Types de ligne
toggle
Bascule booléenne.
| Champ | Type | Obligatoire | Signification |
|---|---|---|---|
default | booléen | oui | Valeur initiale. |
slider
Nombre borné ; step > 0, step ≤ max - min, au plus 10000 pas, default dans l’intervalle.
| Champ | Type | Obligatoire | Signification |
|---|---|---|---|
min | nombre de -1000000 à 1000000 | oui | Borne inférieure. |
max | nombre de -1000000 à 1000000 | oui | Borne supérieure, plus grande que min. |
step | nombre de -1000000 à 1000000 | oui | Pas. |
default | nombre de -1000000 à 1000000 | oui | Valeur initiale. |
choice
Une valeur parmi les choix déclarés.
| Champ | Type | Obligatoire | Signification |
|---|---|---|---|
choices | liste de MenuChoice ≤ 16 | oui | Au moins 2 choix. |
default | identifiant ≤ 48 octets | oui | Valeur de l’un des choix déclarés. |
action
Appelle le gestionnaire enregistré par onMenu avec l’ID de la ligne. Ce n’est pas une action de l’utilisateur.
group
Sous-menu latéral qui contient des lignes autres que des groupes.
| Champ | Type | Obligatoire | Signification |
|---|---|---|---|
rows | liste de MenuRow ≤ 16 | oui | Au moins une ligne ; un group n’y est pas admis. |
Libellés et choix
Un label est un objet qui porte les deux langues :
| Champ | Type | Obligatoire | Signification |
|---|---|---|---|
en | label text | oui | Libellé en anglais. |
fr | label text | oui | Libellé en français. |
Chaque entrée de choices est une valeur et son libellé :
| Champ | Type | Obligatoire | Signification |
|---|---|---|---|
value | identifiant ≤ 48 octets | oui | Valeur enregistrée ; unique dans la ligne. |
label | MenuLabel | oui | Libellé localisé du choix. |
Sources de données indispensables
Au premier niveau du manifeste, requires liste les sources de données sans
lesquelles le widget ne peut pas fonctionner, avec les mêmes noms que le
requires d’une ligne. Sur une machine à laquelle il en manque une,
PlayerVox OverCrow ne démarre pas le widget, ne l’affiche pas et conserve sa
place dans la disposition ; le widget revient quand la source revient.
Utilisez-le pour un widget qui n’a rien d’autre à afficher, comme un
compteur d’images par seconde sans source de fréquence d’images. Pour une
seule valeur facultative, préférez le requires d’une ligne.
Un budget de mémoire plus grand
La logique s’exécute avec un tas de 16 Mio. Un widget qui a besoin de plus
le demande avec vm ; aucun autre budget de la VM ne peut être modifié.
| Champ | Type | Obligatoire | Signification |
|---|---|---|---|
heapMiB | entier de 16 à 48 | oui | Plafond du tas QuickJS en Mio, de 16 Mio à 48 Mio. Le plafond du processus de la VM (64 Mio) ne change pas. |
Le plafond de mémoire du processus du widget reste le même : un tas plus
grand laisse donc moins de place à tout le reste. Ne le demandez que si
overcrow-widget dev montre que le widget s’arrête avec resource_limit.
Comment le manifeste est vérifié
overcrow-widget check valide le manifeste avec le validateur que
PlayerVox OverCrow exécute lui-même, et désigne le membre qu’il refuse :
error[manifest.sizing]: `sizing` is out of bounds or inconsistent
--> manifest.json:7:3
|
7 | "sizing": {
| ^
= help: `min` <= `preferred` <= `max`, each within the schema's widget size bounds
check: 1 error(s), 0 warning(s)PlayerVox OverCrow le valide de nouveau quand le paquet est admis dans le catalogue, quand il est installé et à chaque démarrage du widget. Une nouvelle version dont le manifeste demande plus que la précédente (une règle réseau, un événement de jeu, une capability, le stockage ou le presse-papiers) attend que l’utilisateur l’approuve dans le Centre de contrôle avant de remplacer la version installée.