Afficher un widget PWA dans le tableau Widgets de Windows

Divers systèmes d’exploitation ont des tableaux de bord widgets qui permettent aux utilisateurs de lire du contenu et d’effectuer des tâches. Par exemple, citons les widgets de l’écran d’accueil Android, les widgets du tableau de bord macOS et du panneau Aujourd’hui, la barre tactile Apple, les cartes quotidiennes Samsung, les widgets Mini App et les assistants d’application de montre intelligente.

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

Tableau des widgets dans Windows 11

Dans Windows 11, les applications Progressive Web Apps (PWA) peuvent définir des widgets, les mettre à jour et gérer les interactions utilisateur au sein de ceux-ci.

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

Un PWA existant ne peut pas simplement être placé dans le tableau de bord du widget tel quel, comme vous pouvez le faire avec la barre latérale Microsoft Edge. Au lieu de cela, vous devez créer une expérience de widget personnalisée adaptée à l’hôte de widgets, qui est actuellement le tableau des widgets de Windows 11. (Il peut y avoir d’autres hôtes de widgets à l’avenir.) Le tableau des widgets de Windows 11 nécessite que les widgets soient créés à l’aide de modèles de cartes adaptatives 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 diffuser via le Microsoft Store, aucun code C++/C# n’est nécessaire. Une fois que vous avez produit le widget et que vous pouvez installer et exécuter le widget à partir d’un point de terminaison public, vous pouvez créer un package de l’application à l’aide de PWABuilder.com et l’expédier vers le Microsoft Store sans avoir besoin de code supplémentaire. Le PWA qui sauvegarde le widget doit pouvoir être installé à partir d’un point de terminaison public, car PWABuilder ne prend pas en charge l’empaquetage d’applications à partir de localhost.

Voir aussi :

Installer WinAppSDK et activer le mode développeur

Pour activer, développer et tester des widgets sur votre ordinateur local :

  • Installez WinAppSDK 1.2.

  • Activer 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 de développeur de Windows 11

Définir des widgets

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

{
  "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 illustré 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 :

Field Description Obligatoire ?
name Titre du widget, présenté aux utilisateurs. Oui
short_name Une autre version abrégée du nom. Non
description Description de l’action du widget. Oui
icons Tableau d’icônes à utiliser pour le widget. S’il est manquant, le membre manifeste est utilisé à la icons place. Les icônes supérieures à 1 024 x 1 024 sont ignorées. Non
screenshots Une série de captures d’écran montrant à quoi ressemble le widget. Analogue au membre du 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 1 024 pixels sont ignorées. Pour connaître la configuration requise pour les captures d’écran spécifiques au tableau des widgets de Windows 11, consultez Exigences relatives aux 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é n’est actuellement qu’informative et n’est pas utilisée. Voir ms_ac_template ci-dessous. Non
ms_ac_template URL du modèle de 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 Un booléen indiquant si le widget nécessite une authentification. Non
update Fréquence, en secondes, à laquelle le widget est mis à jour. code de votre worker de service doit effectuer la mise à jour ; Le widget n’est pas mis à jour automatiquement. Afficher les instances de widget Access au moment de l’exécution. Non
multiple Un booléen 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 aux différents tableaux de bord des widgets du 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 l’instant, seuls les modèles de cartes adaptatives personnalisés sont pris en charge. Les cartes adaptatives sont un format d’échange de cartes ouvert qui peut être utilisé pour échanger du contenu de l’interface utilisateur de manière commune et cohérente. Voir la vue d’ensemble des cartes adaptatives.

Pour définir un modèle de cartes adaptatives personnalisé sur Windows 11, utilisez le champ de la définition de widget qui se trouve dans le ms_ac_template manifeste de votre application web. Bien qu’il template ne soit 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 modèle de fichier.

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 en savoir plus, consultez Création de modèles de cartes adaptatives.

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

Lier des données à un 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 champ dans la définition de data votre widget. Ce champ doit être défini sur une URL qui renvoie 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 de l’expression de liaison : ${}. Les données renvoyées par l’URL dans la data définition de votre widget doivent contenir des valeurs pour ces variables.

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

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

Définir des actions de widget

Si vous souhaitez que votre widget permette 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 de worker du service. Voir 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 du worker du service PWA. L’accès aux widgets au moment de l’exécution est utile dans les cas suivants :

Un worker du service a accès à l’objet 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 self.widgets .

Les sections suivantes fournissent des exemples de code. Pour obtenir une référence de l’API, consultez la référence de l’API du worker du service.

Restituer les widgets lors de l’installation

Lorsqu’un PWA est installé, 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 n’est installé que lorsque l’utilisateur choisit d’ajouter le widget à partir du tableau de bord.

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

Pour afficher le widget, écoutez l’événement widgetinstall dans votre worker du service 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 worker du service

Lorsque le code du Worker du service change dans une PWA, le navigateur détecte cette modification, installe le nouveau Worker du service, puis active le Worker du service.

Dans ce cas, il est important de mettre à jour toutes les instances de widget qui sont déjà en cours d’exécution. Les widgets ont peut-être été installés avant l’émission de l’événement du worker activate du service. Pour éviter d’afficher des widgets vides, mettez-les à jour 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 celles-ci en cliquant sur des boutons dans le widget rendu. Pour plus d’informations sur la définition d’actions dans un modèle, reportez-vous à la rubrique 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;
  }
});

Pour des raisons de concision, le code de l’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 transmis à 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 et les informations auxquelles vous pouvez accéder, consultez la référence de l’API widgetclickworker du service ci-dessous.

Mettre à jour les widgets lors des 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 worker du service spécifiques se produisent. Il peut également être utile de mettre à jour les widgets lorsqu’un problème se produit dans l’application, ou lorsqu’une notification push se produit, ou périodiquement.

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

Dans l’extrait de code suivant, un écouteur d’événements est utilisé pour réagir à divers événements du 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 n’est pas inscrite.

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});
}

Demo app

PWAmp est une application de démonstration de lecteur de musique PWA 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 déjà 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 des widgets de Windows 11 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 du mini-lecteur PWAmp et ajoutez-le.

  5. Fermez l’écran des paramètres des widgets . Le mini-lecteur PWAmp est maintenant affiché dans le tableau des widgets.

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

Tableau des widgets Windows, à côté de l’application de démonstration PWAmp. Le tableau des widgets contient le widget du mini lecteur PWAmp, qui affiche la chanson en cours de lecture dans l’application PWAmp

Informations de référence sur l’API du worker du service

L’objet global du worker du service (ou ServiceWorkerGlobalScope) contient un widgets attribut qui expose les méthodes basées sur la promesse suivantes :

Méthode Description Paramètres Valeur renvoyée
getByTag(tag) Gets a widget by tag. Balise widget Une promesse qui se résout en l’objet widget qui correspond à la balise, ou undefined.
getByInstanceId(id) Obtient un widget par ID d’instance. ID d’instance du widget Une promesse qui se résout en l’objet widget correspondant, ou undefined.
getByHostId(id) Obtient les widgets par ID d’hôte. ID d’hôte Tableau d’objets widget trouvés dans cet hôte.
matchAll(options) Obtient les widgets en faisant correspondre les options. Objet WidgetOptions Une promesse qui résout un tableau d’objets widget qui correspondent aux options critères.
updateByInstanceId(id, payload) Mises à jour un widget par ID d’instance. L’ID d’instance et un objet widgetPayload Une promesse qui résout en undefined ou Error.
updateByTag(tag, payload) Mises à jour d’un widget par balise. La balise widget et un objet widgetPayload Une promesse qui résout en undefined ou Error.

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

  • widgetinstall: Déclenché lorsque l’hôte de widgets installe un widget.
  • widgetuninstall: Déclenché lorsque l’hôte de widgets 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 ait 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 objets widgetEvent et 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

Lors de l’utilisation matchAll(options) pour obtenir plusieurs widgets, un widgetOptions objet est nécessaire pour filtrer les widgets à renvoyer. L’objet widgetOptions contient les propriétés suivantes, toutes facultatives :

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

widgetobjet de charge utile

Lors de la création ou de la mise à jour d’une instance de widget, le worker du service 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 cordifié d’un modèle de carte adaptative.
  • data: Les données, sous forme de chaîne, à utiliser avec le modèle de widget. Ces données peuvent être des données JSON converties en chaînes.

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 l’instance.
  • host: pointeur interne vers l’hôte de widget qui a installé cette instance.
  • updated Date: objet qui représente la dernière fois où les données ont été envoyées à l’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, trouvée dans le fichier manifeste PWA. Les propriétés de cet objet correspondent aux propriétés répertoriées dans Définir les widgets, ci-dessus.

widgetObjet événement

Cet objet est transmis en tant qu’argument aux auditeurs d’événements de widget de worker du service de type widgetinstall, widgetuninstall, et widgetresume.

Pour les types d’événements widgetinstall, widgetuninstallet widgetresume , l’objet widgetEvent possède les propriétés suivantes :

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

objet widgetClickEvent

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

L’objet widgetClickEvent possède les propriétés suivantes :

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