Générer des widgets pilotés par PWA

Différents systèmes d’exploitation ont des tableaux de bord de widgets qui permettent aux utilisateurs de lire du contenu et d’effectuer des tâches. Les widgets Écran d’accueil Android, le tableau de bord macOS et le panneau Aujourd’hui, la barre tactile Apple, les cartes quotidiennes Samsung, les widgets mini-applications et les compagnons d’application watch intelligents en sont des exemples.

Sur Windows 11, les widgets apparaissent dans le tableau widgets, que vous ouvrez à gauche de la barre des tâches :

Tableau des widgets dans Windows 11

Dans Windows 11, les Web Apps progressives (PWA) peuvent définir des widgets, les mettre à jour et gérer les interactions utilisateur qu’ils contiennent.

Nécessite la création d’un widget personnalisé pour le PWA

Une PWA existante ne peut pas simplement être placée dans le tableau de bord du widget en l’état, comme vous le pouvez avec la barre latérale Microsoft Edge. Au lieu de cela, vous devez créer une expérience de widget personnalisée appropriée pour l’hôte de widget, qui est actuellement le Windows 11 Widgets Board. (Il peut y avoir d’autres hôtes de widgets à l’avenir.) Le Windows 11 Widgets Board exige que les widgets soient générés à l’aide de modèles de carte adaptative au lieu de HTML et JavaScript. Le widget doit donc être conçu séparément du reste de l’interface utilisateur de l’application.

Voir aussi :

Pour créer un widget piloté par PWA et le remettre via le Microsoft Store, aucun code C++/C# n’est requis. Une fois que vous avez produit le widget et que vous pouvez l’installer et l’exécuter correctement à partir d’un point de terminaison public, vous pouvez empaqueter l’application à l’aide de PWABuilder.com et expédier l’application au Microsoft Store sans nécessiter de code supplémentaire. Le widget PWA de sauvegarde doit être installable à partir d’un point de terminaison public, car PWABuilder.com ne prend pas en charge l’empaquetage des applications à partir de localhost.

Voir aussi :

Installer WinAppSDK et activer le mode développeur

Pour activer le développement et le test de widgets sur votre ordinateur local :

  • Installez WinAppSDK 1.2.

  • Activez le mode développeur dans Windows 11 :

    1. Ouvrez Paramètres.

    2. Dans la zone de texte Rechercher un paramètre , entrez developer, puis cliquez sur Utiliser les fonctionnalités de développement.

    3. Activer le mode développeur :

      Paramètres développeur de Windows 11

Définir des widgets

Les widgets sont définis dans votre fichier manifeste PWA, à l’aide du membre de widgets manifeste. Ce membre de manifeste est un tableau qui peut contenir plusieurs définitions de widget.

{
  "name": "PWAmp",
  "description": "A music player app",
  "icons": [
    { "src": "img/icon-96.png", "sizes": "96x96" },
    { "src": "img/icon-128.png", "sizes": "128x128" },
    { "src": "img/icon-256.png", "sizes": "256x256" },
    { "src": "img/icon-512.png", "sizes": "512x512" }
  ],
  "widgets": [
    /* widget definitions go here */
  ]
}

Chaque entrée du widgets tableau contient plusieurs champs, comme indiqué ci-dessous :

{
  ...
  "widgets": [
    {
      "name": "PWAmp mini player",
      "description": "widget to control the PWAmp music player",
      "tag": "pwamp",
      "template": "pwamp-template",
      "ms_ac_template": "widgets/mini-player-template.json",
      "data": "widgets/mini-player-data.json",
      "type": "application/json",
      "screenshots": [
        {
          "src": "./screenshot-widget.png",
          "sizes": "600x400",
          "label": "The PWAmp mini-player widget"
        }
      ],
      "icons": [
        {
          "src": "./favicon-16.png",
          "sizes": "16x16"
        }
      ],
      "auth": false,
      "update": 86400
    }
  ]
}

Dans l’exemple ci-dessus, une application de lecteur de musique définit un widget de mini-lecteur. Une définition de widget dans le manifeste de l’application web comporte les champs obligatoires et facultatifs suivants :

Champ Description Obligatoire
name Titre du widget, présenté aux utilisateurs. Oui
short_name Autre version courte du nom. Non
description Description de ce que fait le widget. Oui
icons Tableau d’icônes à utiliser pour le widget. S’il est manquant, le membre de icons manifeste est utilisé à la place. Les icônes supérieures à 1024 x 1024 sont ignorées. Non
screenshots Tableau de captures d’écran qui montrent à quoi ressemble le widget. Analogue au membre de screenshot manifeste. Le platform champ d’un élément de capture d’écran prend en charge les Windows valeurs et any . Les images d’une taille supérieure à 1024 x 1024 pixels sont ignorées. Pour connaître les exigences de capture d’écran spécifiques au Windows 11 Widgets Board, consultez Configuration requise pour les images de capture d’écran dans Intégrer au sélecteur de widgets. Oui
tag Chaîne utilisée pour référencer le widget dans le worker du service PWA. Oui
template Modèle à utiliser pour afficher le widget dans le tableau de bord des widgets du système d’exploitation. Remarque : cette propriété est actuellement uniquement informative et n’est pas utilisée. Voir ms_ac_template ci-dessous. Non
ms_ac_template URL du modèle cartes adaptatives personnalisé à utiliser pour afficher le widget dans le tableau de bord des widgets du système d’exploitation. Consultez Définir un modèle de widget ci-dessous. Oui
data URL où se trouvent les données avec lesquelles remplir le modèle. Si elle est présente, cette URL est requise pour retourner un JSON valide. Non
type Type MIME pour les données du widget. Non
auth Valeur booléenne indiquant si le widget nécessite une authentification. Non
update Fréquence, en secondes, à laquelle le widget sera mis à jour. Le code de votre worker de service doit effectuer la mise à jour ; le widget n’est pas mis à jour automatiquement. Consultez Accéder aux instances de widget au moment de l’exécution. Non
multiple Valeur booléenne indiquant s’il faut autoriser plusieurs instances du widget. La valeur par défaut est true. Non

Définir un modèle de widget

Pour faciliter la création et l’adaptation des widgets à différents tableaux de bord de widgets de système d’exploitation, ils sont affichés à l’aide de modèles. Il existe deux types de modèles :

  • Modèles génériques, définis par leur nom à l’aide du template champ .
  • Modèles personnalisés, définis par leurs URL à l’aide d’un champ de modèle personnalisé.

Pour le moment, seuls les modèles de cartes adaptatives personnalisés sont pris en charge. Cartes adaptatives est un format d’échange ouvert carte qui peut être utilisé pour échanger le contenu de l’interface utilisateur d’une manière commune et cohérente. Consultez Vue d’ensemble des cartes adaptatives.

Pour définir un modèle de cartes adaptatives personnalisé sur Windows 11, utilisez le ms_ac_template champ dans la définition de widget qui se trouve dans le manifeste de votre application web. Bien qu’il ne soit template pas utilisé actuellement, il s’agit d’un champ obligatoire.

{
  ...
  "template": "pwamp-template",
  "ms_ac_template": "widgets/mini-player.json",
  ...
}

La ms_ac_template valeur du champ doit être une URL valide d’un fichier de modèle.

Voici un exemple de modèle de cartes adaptatives :

{
  "type": "AdaptiveCard",
  "body": [
    {
      "type": "TextBlock",
      "size": "Medium",
      "text": "Now playing...",
      "horizontalAlignment": "Center"
    },
    {
      "type": "TextBlock",
      "spacing": "Large",
      "weight": "Bolder",
      "horizontalAlignment": "Center",
      "text": "${song}, by ${artist}",
    }
  ],
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
  "version": "1.5"
}

Pour plus d’informations, consultez Création de modèles de cartes adaptatives.

Ensuite, vous devez lier les données à votre modèle.

Lier des données à votre modèle

Le modèle déclare l’interface utilisateur d’un widget. Les données remplissent ensuite cette interface utilisateur.

Pour lier des données à votre modèle, utilisez le data champ dans votre définition de widget. Ce champ doit être défini sur une URL qui retourne des données JSON valides.

Le modèle défini dans la section précédente contient deux variables : song et artist, qui sont incluses dans la syntaxe d’expression de liaison : ${}. Les données retournées par l’URL dans votre data définition de widget doivent contenir des valeurs pour ces variables.

Voici un exemple de ce que l’URL data peut retourner :

{
  "song": "I Will Always Love You",
  "artist": "Whitney Houston"
}

Définir des actions de widget

Si vous souhaitez que votre widget permet aux utilisateurs d’effectuer des tâches, définissez un modèle qui prend en charge les actions.

Voici un exemple d’action définie dans un modèle de cartes adaptatives personnalisé :

{
  "type": "AdaptiveCard",
  "body": [
    {
      "type": "TextBlock",
      "size": "Medium",
      "text": "Now playing...",
      "horizontalAlignment": "Center"
    },
    {
      "type": "TextBlock",
      "spacing": "Large",
      "weight": "Bolder",
      "horizontalAlignment": "Center",
      "text": "${song}, by ${artist}",
    }
  ],
  "actions": [
    {
      "type": "Action.Execute",
      "title": "Previous",
      "verb": "previous-song"
    },
    {
      "type": "Action.Execute",
      "title": "Next",
      "verb": "next-song"
    }
  ],
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
  "version": "1.5"
}

Notez le verb champ dans le modèle JSON ci-dessus. Il sera utilisé lors de la gestion des actions de widget dans votre code worker de service. Consultez Gérer les actions de widget.

Accéder aux instances de widget au moment de l’exécution

Vous pouvez accéder aux widgets et les mettre à jour à partir du code worker du service PWA. L’accès aux widgets au moment de l’exécution est utile dans les cas suivants :

Les workers de service ont accès à l’objet self.widgets et à plusieurs événements de widget qui, ensemble, constituent une API que vous utilisez pour réagir aux modifications et accéder aux widgets au moment de l’exécution.

Les sections suivantes fournissent des exemples de code. Pour obtenir une référence de l’API, consultez les informations de référence sur l’API de travail de service.

Afficher les widgets lors de l’installation

Lorsqu’une PWA est installée, les widgets que l’application définit dans son manifeste sont ajoutés au tableau de bord des widgets, mais pas encore installés. Un widget est installé uniquement lorsque l’utilisateur choisit d’ajouter le widget à partir du tableau de bord.

Lorsqu’un widget est installé, il n’est pas automatiquement affiché à l’aide des ms_ac_template champs et data de la définition du widget.

Pour afficher le widget, écoutez l’événement widgetinstall dans votre service Worker et mettez à jour le widget à l’aide de la widgets.updateByTag fonction :

// Listen to the widgetinstall event.
self.addEventListener("widgetinstall", event => {
  // The widget just got installed, render it using renderWidget.
  // Pass the event.widget object to the function.
  event.waitUntil(renderWidget(event.widget));
});

async function renderWidget(widget) {
  // Get the template and data URLs from the widget definition.
  const templateUrl = widget.definition.msAcTemplate;
  const dataUrl = widget.definition.data;

  // Fetch the template text and data.
  const template = await (await fetch(templateUrl)).text();
  const data = await (await fetch(dataUrl)).text();

  // Render the widget with the template and data.
  await self.widgets.updateByTag(widget.definition.tag, {template, data});
}

Mettre à jour les widgets sur les mises à jour du Service Worker

Lorsque le code du service Worker change dans une PWA, le navigateur détecte cette modification, installe le nouveau worker de service, puis l’active ultérieurement.

Dans ce cas, il est important de mettre à jour toutes les instances de widget qui sont peut-être déjà en cours d’exécution. Les widgets ont peut-être été installés avant l’émission de l’événement service Worker activate . Pour éviter d’afficher des widgets vides, mettez à jour vos widgets lorsque l’événement activate se produit

// Update the widgets to their initial states
// when the service worker is activated.
self.addEventListener("activate", event => {
  event.waitUntil(updateWidgets());
});

async function updateWidgets() {
  // Get the widget that match the tag defined in the web app manifest.
  const widget = await self.widgets.getByTag("pwamp");
  if (!widget) {
    return;
  }

  // Using the widget definition, get the template and data.
  const template = await (await fetch(widget.definition.msAcTemplate)).text();
  const data = await (await fetch(widget.definition.data)).text();

  // Render the widget with the template and data.
  await self.widgets.updateByTag(widget.definition.tag, {template, data});
}

Gérer les actions de widget

Si le modèle de widget contient des actions, les utilisateurs peuvent exécuter ces actions en cliquant sur des boutons dans le widget rendu. Pour plus d’informations sur la définition d’actions dans un modèle, consultez Définir des actions de widget.

Lorsqu’un utilisateur exécute une action de widget, un widgetclick événement est déclenché dans le worker du service PWA. Pour gérer l’action de l’utilisateur, écoutez l’événement :

self.addEventListener('widgetclick', (event) => {
  switch (event.action) {
    case 'previous-song':
      // Application logic to play the previous song...
      break;
    case 'next-song':
      // Application logic to play the next song...
      break;
  }
});

Par souci de concision, le code d’application réel n’est pas affiché dans l’extrait de code ci-dessus. Lorsque les previous-song actions ou next-song sont reçues, un message doit probablement être envoyé à l’application à l’aide de Client.postMessage pour informer l’application qu’elle doit commencer à lire les chansons précédentes ou suivantes.

Notez que la action propriété de l’objet widgetEvent passé à l’écouteur d’événements ci-dessus correspond à la chaîne définie dans le action.verb champ du modèle de widget.

Pour plus d’informations sur l’événement widgetclick et sur les informations accessibles à partir de celui-ci, consultez les informations de référence sur l’API Service Worker ci-dessous.

Mettre à jour les widgets sur les modifications apportées à l’application

Dans les sections précédentes, vous avez appris à mettre à jour des widgets lorsque des événements de widget, des actions de widget et des mises à jour de travail de service spécifiques se sont produits. Il peut également être utile de mettre à jour les widgets lorsqu’un événement se produit dans l’application, ou lorsqu’une notification Push se produit, ou régulièrement.

Dans cette section, vous allez apprendre à utiliser l’API synchronisation périodique en arrière-plan pour mettre à jour régulièrement les widgets. Pour plus d’informations sur l’API synchronisation périodique en arrière-plan, consultez Utiliser l’API de synchronisation en arrière-plan périodique pour obtenir régulièrement du contenu actualisé.

Dans l’extrait de code suivant, un écouteur d’événements est utilisé pour réagir à différents événements de cycle de vie du widget d’application. Lorsqu’une installation de widget est détectée, une synchronisation périodique est inscrite et lorsqu’une suppression de widget est détectée, la synchronisation périodique est annulée.

Lorsque des événements de synchronisation périodiques se produisent, les instances de widget sont mises à jour à l’aide de la widgets.updateByTag fonction .

self.addEventListener("widgetinstall", event => {
  event.waitUntil(onWidgetInstall(event.widget));
});

self.addEventListener("widgetuninstall", event => {
  event.waitUntil(onWidgetUninstall(event.widget));
});

async function onWidgetInstall(widget) {
  // Register a periodic sync, if this wasn't done already.
  // We use the same tag for the sync registration and the widget to
  // avoid registering several periodic syncs for the same widget.
  const tags = await self.registration.periodicSync.getTags();
  if (!tags.includes(widget.definition.tag)) {
    await self.registration.periodicSync.register(widget.definition.tag, {
      minInterval: widget.definition.update
    });
  }

  // And also update the instance.
  await updateWidget(widget);
}

async function onWidgetUninstall(widget) {
  // On uninstall, unregister the periodic sync.
  // If this was the last widget instance, then unregister the periodic sync.
  if (widget.instances.length === 1 && "update" in widget.definition) {
    await self.registration.periodicSync.unregister(widget.definition.tag);
  }
}

// Listen to periodicsync events to update all widget instances
// periodically.
self.addEventListener("periodicsync", async event => {
  const widget = await self.widgets.getByTag(event.tag);

  if (widget && "update" in widget.definition) {
    event.waitUntil(updateWidget(widget));
  }
});

async function updateWidget(widget) {
  // Get the template and data URLs from the widget definition.
  const templateUrl = widget.definition.msAcTemplate;
  const dataUrl = widget.definition.data;

  // Fetch the template text and data.
  const template = await (await fetch(templateUrl)).text();
  const data = await (await fetch(dataUrl)).text();

  // Render the widget with the template and data.
  await self.widgets.updateByTag(widget.definition.tag, {template, data});
}

Application de démonstration

PWAmp est une application de démonstration PWA de lecteur de musique qui définit un widget. Le widget PWAmp permet aux utilisateurs de visualiser la chanson actuelle et de lire les chansons précédentes ou suivantes.

  1. Si ce n’est pas encore fait, installez WinAppSDK 1.2 et activez le mode développeur dans Windows 11.

  2. Accédez à PWAmp et installez l’application sur Windows 11.

  3. Ouvrez le tableau Windows 11 widgets en appuyant sur la touche de logo Windows + W.

  4. Cliquez sur Ajouter des widgets pour ouvrir l’écran des paramètres des widgets , faites défiler jusqu’au widget de mini-lecteur PWAmp et ajoutez-le.

  5. Fermez l’écran des paramètres des widgets . Le mini-lecteur PWAmp s’affiche désormais dans le tableau widgets.

Le widget PWAmp affiche la chanson actuelle et les boutons pour lire la chanson précédente ou suivante.

Panneau Widgets Windows, en regard de l’application de démonstration PWAmp. Le panneau Widgets contient le widget de mini-lecteur PWAmp, montrant la chanson en cours de lecture dans l’application PWAmp

Informations de référence sur l’API Service Worker

L’objet global Service Worker (ou ServiceWorkerGlobalScope) contient un widgets attribut qui expose les méthodes basées sur promise suivantes :

Méthode Description Parameters Valeur renvoyée
getByTag(tag) Obtenir un widget par étiquette Balise de widget Promesse qui se résout en objet widget qui correspond à la balise, ou undefined.
getByInstanceId(id) Obtenir un widget par ID instance ID de instance du widget Promesse qui se résout en objet widget correspondant, ou undefined.
getByHostId(id) Obtenir des widgets par ID d’hôte ID d’hôte Tableau d’objets widget trouvés dans cet hôte.
matchAll(options) Obtenir des widgets en mettant en correspondance les options Objet widgetOptions Promesse qui se résout en tableau d’objets de widget qui correspondent aux options critères.
updateByInstanceId(id, payload) Mettre à jour un widget par ID instance ID instance et objet widgetPayload Promesse qui se résout en undefined ou Error.
updateByTag(tag, payload) Mettre à jour un widget par étiquette Balise de widget et objet widgetPayload Promesse qui se résout en undefined ou Error.

L’objet global service Worker définit également les événements suivants :

  • widgetinstall: déclenché lorsque l’hôte du widget installe un widget.
  • widgetuninstall: déclenché lorsque l’hôte du widget désinstalle un widget.
  • widgetresume: déclenché lorsque l’hôte du widget reprend le rendu des widgets installés, ce qui peut se produire après que l’hôte a suspendu le rendu des widgets pour préserver les ressources.
  • widgetclick: déclenché lorsque l’utilisateur exécute l’une des actions du widget.

Pour plus d’informations sur les objets fournis avec ces événements, consultez les définitions de l’objet widgetEvent et de l’objet widgetClickEvent ci-dessous.

objet widget

Chaque widget est représenté sous la forme d’un widget objet, qui contient les propriétés suivantes :

objet widgetOptions

Lorsque vous utilisez matchAll(options) pour obtenir plusieurs widgets, un widgetOptions objet est nécessaire pour filtrer les widgets à retourner. L’objet widgetOptions contient les propriétés suivantes, toutes facultatives :

  • installable: valeur booléenne indiquant si les widgets retournés doivent être installables.
  • installed: valeur booléenne indiquant si les widgets retournés sont installés dans l’hôte du widget.
  • tag: chaîne utilisée pour filtrer les widgets retournés par balise.
  • instanceId: chaîne utilisée pour filtrer les widgets retournés par id de instance.
  • hostId: chaîne utilisée pour filtrer les widgets retournés par ID d’hôte de widget.

objet widgetPayload

Lors de la création ou de la mise à jour d’un widget instance, le service worker doit envoyer le modèle et les données nécessaires pour remplir le widget. Le modèle et les données sont appelés charge utile. L’objet widgetPayload contient les propriétés suivantes :

  • template: modèle, sous forme de chaîne, à utiliser pour afficher le widget. Il s’agit du json stringifié d’un modèle de carte adaptative.
  • data: données, sous forme de chaîne, à utiliser avec le modèle de widget. Ces données peuvent être des données JSON stringifiées.

objet widgetInstance

Cet objet représente une instance donnée d’un widget dans un hôte de widget et contient les propriétés suivantes :

  • id: chaîne GUID interne utilisée pour référencer le instance.
  • host: pointeur interne vers l’hôte de widget qui a installé cette instance.
  • updatedDate: objet qui représente la dernière fois que les données ont été envoyées au instance.
  • payload: objet widgetPayload qui représente la dernière charge utile envoyée à cette instance.

objet widgetDefinition

Cet objet représente la définition d’origine du widget, qui se trouve dans le fichier manifeste PWA. Les propriétés de cet objet correspondent aux propriétés répertoriées dans Définir des widgets, ci-dessus.

objet widgetEvent

Cet objet est passé en tant qu’argument aux écouteurs des événements de widget de travail de service de type widgetinstall, widgetuninstallet widgetresume.

Pour les widgetinstalltypes d’événements , widgetuninstallet widgetresume , l’objet widgetEvent a les propriétés suivantes :

Propriété Description Type
widget Le widget instance qui a déclenché l’événement. Widget
instanceId ID de instance du widget. String
hostId ID d’hôte du widget. String

objet widgetClickEvent

Cet objet est passé en tant qu’argument aux écouteurs des événements de widget de travail de service de type widgetclick. Vous pouvez ouvrir la fenêtre de votre application en réponse à l’événement, à l’aide widgetclickclients.openWindow()de .

L’objet widgetClickEvent a les propriétés suivantes :

Propriété Description Type
action Action qui a déclenché l’événement, telle que définie dans les actions.verb champs du modèle de widget. Consultez Définir des actions de widget. String
widget Le widget instance qui a déclenché l’événement. widgetInstance
hostId ID d’hôte du widget. String
instanceId ID de instance du widget. String