Aplicaciones web progresivas: Potencia tu AWP

1. Te damos la bienvenida

En este lab, tomarás una aplicación web existente y le agregarás capacidades avanzadas. Este es el sexto de una serie de codelabs complementarios para el taller de apps web progresivas. El codelab anterior fue Mensajes y medición de la instalación. Hay dos codelabs más en esta serie.

Qué aprenderás

  • Abrir y guardar archivos del sistema de archivos del usuario con la API de File System Access
  • Registra tu AWP instalada como controlador de archivos con la API de File Handling
  • Cómo elegir la pantalla correcta para abrir una ventana con la API de Multi-Screen Window Placement
  • Cómo evitar que una pantalla entre en suspensión con la API de Screen Wake Lock

Lo que debe saber

  • JavaScript

Lo que necesitarás

  • Un navegador que admita las APIs anteriores En el caso de algunas APIs, es posible que debas usar un navegador con una prueba para desarrolladores o una prueba de origen activa para completar el proceso.

2. Prepárate

Para comenzar, clona o descarga el código de partida necesario para completar este codelab:

Si clonas el repositorio, asegúrate de estar en la rama pwa05--empowering-your-pwa. El archivo ZIP también contiene el código de esa rama.

Este código base requiere Node.js 14 o una versión posterior. Una vez que tengas el código disponible, ejecuta npm ci desde la línea de comandos en la carpeta del código para instalar todas las dependencias que necesitarás. Luego, ejecuta npm start para iniciar el servidor de desarrollo del codelab.

El archivo README.md del código fuente proporciona una explicación de todos los archivos distribuidos. Además, los siguientes son los archivos existentes clave con los que trabajarás a lo largo de este codelab:

Archivos de claves

  • js/lib/actions.js: Proporciona una clase base para el menú.

Nota arquitectónica importante

A lo largo de este codelab, editarás js/lib/action.js, que administra las acciones de los diferentes botones del menú de la app. Puedes acceder a cualquier propiedad en el constructor del menú inicializado, que incluirá this.editor para una instancia del editor de texto principal. A lo largo de este codelab, usarás dos métodos importantes del editor:

  • this.editor.setContent(content): Establece el contenido del editor en el argumento de contenido proporcionado.
  • this.editor.content(): Obtiene el contenido actual del editor.

3. Administrar archivos

Ahora es posible abrir, guardar y crear archivos nuevos en la computadora de un usuario gracias a la API de File System Access. Si se combina con la API de File Handling, que permite a los usuarios abrir archivos directamente en tu AWP, tu AWP puede sentirse integrada sin problemas en la vida cotidiana de los usuarios.

Cómo abrir desde la app

La primera acción que se debe conectar es la capacidad de abrir un archivo del sistema de archivos del usuario desde la app. En js/lib/actions.js, en el método open de la clase Actions, escribe código que haga lo siguiente:

  • Abre un selector de archivos que tomará el archivo text/markdown con las extensiones .md o .markdown.
  • Establece el título de la página como el nombre de los archivos abiertos, más PWA Edit.
  • Almacena el controlador de archivos en this.handler
  • Establece el contenido del editor en el contenido de texto del archivo.
  • Guarda el controlador en el almacén de objetos settings en la base de datos IndexedDB settings-store.

Positivo: Recuerda que los constructores de clase no pueden ser funciones async, pero puedes llamar a Promises dentro de ellos.

Ahora que puedes abrir un archivo y guardar qué archivo está abierto entre cargas, hay dos cosas más que debes hacer: volver a configurar el controlador cuando se carga la app y anular su configuración cuando el usuario restablece la app.

Para lograr lo primero, en el constructor de la clase Actions en js/lib/actions.js, haz lo siguiente:

  • Abre la base de datos settings-store.
  • Obtén el controlador guardado del almacén de objetos settings.
  • Establece this.handler en el valor recuperado y el título de la página en el nombre de archivo del controlador (más PWA Edit) si hay un controlador guardado.

Para restablecer el estado de la app (lo que se puede lograr con CTRL/CMD + Shift + R), actualiza el método reset de la clase Actions en js/lib/actions.js para hacer lo siguiente:

  • Establece el título del documento en PWA Edit.
  • Establece el contenido del editor en una cadena vacía.
  • Configura this.handler en null.
  • Borra el controlador guardado del almacén de objetos settings

Abrir desde el sistema de archivos del usuario

Ahora que puedes abrir un archivo desde tu app, debes permitir que los usuarios abran tu app con sus archivos. Registrarse como controlador de archivos para un dispositivo permitirá que un usuario abra archivos en tu app desde cualquier lugar de su sistema de archivos.

Negativo : Es posible que debas habilitar una prueba de origen o para desarrolladores para que esto funcione. Si necesitas habilitar una versión de prueba para desarrolladores, te recomendamos que lo hagas en una copia de Chrome Canary en lugar de tu navegador normal. Si necesitas habilitar una prueba de origen, debes registrarte como de costumbre y agregar la etiqueta a index.html.

Para comenzar, en manifest.json, agrega una entrada file_handlers que haga lo siguiente:

  • Abre: /
  • Se acepta text/markdown con extensiones de archivo .md o .markdown.

Esto permitirá que los usuarios abran archivos con tu app, pero no los abrirá en ella. Para hacerlo, en la clase Actions de js/lib/actions.js, haz lo siguiente:

  • Agrega un consumidor de window.launchQueue en el constructor y llama a this.open con el controlador, si hay alguno.
  • Actualiza this.open para que acepte un controlador de inicio opcional
    • Si existe y es una instancia de FileSystemFileHandle, úsala como controlador de archivos para la función.
    • Si no es así, abre el selector de archivos.

Después de hacer lo anterior, instala tu PWA y trata de abrir un archivo con ella desde el sistema de archivos.

Cómo guardar un archivo

Hay dos rutas de guardado diferentes que un usuario puede querer tomar: guardar los cambios en un archivo ya abierto o guardar en un archivo nuevo. Con la API de File System Access, guardar en un archivo nuevo es, en realidad, crear un archivo nuevo y obtener un controlador de archivos. Por lo tanto, para comenzar, guardemos desde un controlador existente.

En el método save de la clase Actions en js/lib/actions.js, haz lo siguiente:

  • Obtén el controlador de this.handler o, si no existe, obtén el controlador guardado de la base de datos.
  • Crea el FileSystemWritableFileStream del controlador de archivos
  • Escribe el contenido del editor en el flujo
  • Cierra la transmisión

Una vez que puedas guardar un archivo, es hora de implementar la función Guardar como. Para ello, en el método saveAs de la clase Actions en js/lib/actions.js, haz lo siguiente:

  • Mostrar el selector de archivos de guardado, describirlo como un Markdown File y hacer que acepte archivos text/markdown con una extensión .md
  • Configura this.handler en el controlador devuelto
  • Guarda el controlador en el almacén de objetos settings.
  • Espera a que finalice this.save para guardar el contenido en el archivo recién creado.

Una vez que lo hayas hecho, vuelve al método save, verifica si existe el handler antes de intentar escribir en él y, si no existe, espera a que termine this.saveAs.

4. Cómo mostrar una vista previa

Con un editor de Markdown, los usuarios quieren ver una vista previa del resultado renderizado. Con la API de Window Management, abrirás una vista previa del contenido renderizado en la pantalla principal del usuario.

Antes de comenzar, crea un archivo js/preview.js y agrégale el siguiente código para que muestre una vista previa cuando se cargue:

import { openDB } from 'idb';
import { marked } from 'marked';

window.addEventListener('DOMContentLoaded', async () => {
  const preview = document.querySelector('.preview');
  const db = await openDB('settings-store');
  const content = (await db.get('settings', 'content')) || '';

  preview.innerHTML = marked(content);
});

La vista previa debería comportarse de las siguientes maneras:

  • Cuando un usuario hace clic en el botón de vista previa y no se abre una vista previa, se debe abrir la vista previa.
  • Cuando un usuario hace clic en el botón de vista previa y se abre una vista previa, esta debe cerrarse.
  • Cuando el usuario cierre o actualice la PWA, la vista previa debería cerrarse.

Comienza por editar el método preview en la clase Actions en js/lib/actions.js para hacer lo siguiente:

  • Obtén las pantallas disponibles con la API de Window Management
  • Filtra las pantallas para encontrar la principal
  • Abre una ventana para /preview con el título Markdown preview que ocupa la mitad del ancho disponible y toda la altura disponible de la pantalla principal, y se posiciona de modo que ocupe toda la mitad derecha disponible de esa pantalla. Las dimensiones disponibles excluyen las áreas reservadas de la pantalla, como la barra de menú, la barra de herramientas, el estado o la ubicación del sistema.
  • Guarda esta ventana abierta en this.previewWindow
  • En la parte superior del método, verifica si existe this.previewWindow y, si es así, cierra la ventana y anula this.previewWindow en lugar de abrir una vista previa de la ventana.

Por último, haz lo siguiente al final del constructor de la clase Actions en js/lib/actions.js:

  • Cerrar this.previewWindow durante el evento de beforeunload

5. Enfoque

Por último, queremos ofrecer a los usuarios un modo de escritura sin distracciones. La ausencia de distracciones no solo significa que no hay desorden de otras apps, sino que también evita que la pantalla del usuario se apague. Para ello, usarás la API de Screen Wake Lock.

El botón de bloqueo de activación funcionará igual que el botón de vista previa, alternando entre el estado de activación y desactivación. Para ello, en el método focus de la clase Actions en js/lib/actions.js, haz lo siguiente:

  • Comprueba si el documento tiene un elemento de pantalla completa
  • Si es así, haz lo siguiente:
    • Salir de la pantalla completa
    • Si existe this.wakeLock, libera el bloqueo de activación y restablece this.wakeLock.
  • Si no es así, haz lo siguiente:
    • Solicita un centinela de bloqueo de activación y configúralo en this.wakeLock
    • Solicita que el cuerpo del documento se muestre en pantalla completa.

6. ¡Felicitaciones!

Aprendiste a administrar archivos del sistema y a integrar tu PWA con un sistema usando la API de File System Access y la API de File Handling, a abrir ventanas en diferentes pantallas con la API de Window Management y a evitar que una pantalla entre en suspensión con la API de Screen Wake Lock.

El siguiente codelab de la serie es Service Worker Includes.