Codelab Web Capabilities

Recursos da Web

Queremos diminuir a lacuna de recursos entre a Web e o nativo e facilitar a criação de ótimas experiências na Web aberta para os desenvolvedores. Acreditamos que todos os desenvolvedores precisam ter acesso aos recursos de que precisam para proporcionar uma ótima experiência na Web. Temos o compromisso de criar uma Web mais eficiente.

No entanto, alguns recursos, como o acesso ao sistema de arquivos e a detecção de inatividade, estão disponíveis para anúncios nativos, mas não estão disponíveis na Web. Esses recursos ausentes significam que alguns tipos de aplicativos não podem ser entregues na Web ou são menos úteis.

Projetaremos e desenvolveremos esses novos recursos de forma aberta e transparente, usando os processos de padrões de plataforma da Web abertos e receba feedback antecipado de desenvolvedores e outros fornecedores de navegadores à medida que iterarmos o design para garantir um design interoperável.

O que você vai criar

Neste codelab, você vai testar várias APIs da Web novas ou que estão disponíveis apenas por trás de uma sinalização. Assim, este codelab se concentra nas próprias APIs e nos casos de uso desbloqueados, em vez de criar um produto final específico.

O que você aprenderá

Este codelab ensinará a mecânica básica de várias APIs de ponta. Essas mecânicas ainda não estão totalmente definidas, e seu feedback sobre o fluxo de desenvolvedor é muito importante para nós.

Pré-requisitos

Como as APIs apresentadas neste codelab estão no limite, os requisitos de cada uma delas variam. Leia atentamente as informações de compatibilidade no início de cada seção.

Como usar o codelab

O codelab não é necessariamente realizado de maneira sequencial. Cada seção representa uma API independente, então você pode escolher o que mais interessa a você.

O objetivo da API Badging é chamar a atenção dos usuários para coisas que acontecem em segundo plano. Para simplificar a demonstração deste codelab, vamos usar a API para chamar a atenção de usuários que estão acontecendo em primeiro plano. Assim, você pode fazer a transferência mental de acontecimentos que acontecem em segundo plano.

Instalar o Airhorner

Para que essa API funcione, você precisa de um PWA instalado na tela inicial. Por isso, a primeira etapa é instalar um PWA, como o conhecido airhorner.com, que é conhecido mundialmente. Pressione o botão Instalar no canto superior direito ou use o menu de três pontos para instalar manualmente.

Você verá um prompt de confirmação. Clique em Install.

Agora você tem um novo ícone na base do sistema operacional. Clique nele para iniciar o PWA. Ela terá a própria janela do app e será executada no modo independente.

Como definir um selo

Agora que você tem um PWA instalado, precisa ter alguns dados numéricos para exibir um selo. Os selos só podem conter números. O suspiro é um número simples de vezes que ele está com chifres. Na verdade, com o app Airhorner instalado, tente testar o alarme e verificar o selo. Ele é incluído quando você soa o alarme.

Como isso funciona? Basicamente, o código é este:

let hornCounter = 0;
const horn = document.querySelector('.horn');
horn.addEventListener('click', () => {
  navigator.setExperimentalAppBadge(++hornCounter);
});

Sonda o airhorn algumas vezes e verifique o ícone do PWA: ele será atualizado a cada vez. Tão fácil assim.

Limpar um selo

O contador sobe até 99, em seguida, recomeça. Também é possível redefini-lo manualmente. Abra a guia do Console do DevTools, cole a linha abaixo e pressione Enter.

navigator.setExperimentalAppBadge(0);

Como alternativa, você também pode limpar o selo apagando-o explicitamente, conforme mostrado no snippet a seguir. O ícone do PWA será exibido novamente com clareza, no início e sem um selo.

navigator.clearExperimentalAppBadge();

Feedback

O que você achou dessa API? Responda a esta pesquisa para que possamos ajudar você:

O uso desta API era intuitivo?

Sim Não

Você conseguiu executar o exemplo?

Sim Não

Quer compartilhar algo mais? Faltam recursos? Responda rapidamente a esta pesquisa. Agradecemos sua colaboração.

Com a API Native File System, os desenvolvedores podem criar apps da Web eficientes que interagem com arquivos no dispositivo local do usuário. Depois que um usuário concede acesso a um app da Web, essa API permite que esses apps leiam ou salvem alterações diretamente em arquivos e pastas no dispositivo do usuário.

Como ler um arquivo

O "quot;Hello, world" da API Native File System é ler um arquivo local e obter o conteúdo do arquivo. Crie um arquivo .txt simples e insira um texto. Em seguida, acesse qualquer site seguro (por exemplo, veiculado por HTTPS), como example.com e abra o console do DevTools. Cole o snippet de código abaixo no console. Como a API Native File System exige um gesto do usuário, anexamos um gerenciador de dois cliques no documento. Precisaremos do identificador de arquivos mais tarde, então apenas a tornamos uma variável global.

document.ondblclick = async () => {
  window.handle = await window.chooseFileSystemEntries();
  const file = await handle.getFile();
  document.body.textContent = await file.text();
};

Quando você clica duas vezes em qualquer lugar da página example.com, um seletor de arquivo é exibido.

Selecione o arquivo .txt que você criou anteriormente. O conteúdo do arquivo substituirá o conteúdo do body de example.com.

Salvar um arquivo

Agora, queremos fazer algumas alterações. Portanto, vamos tornar o body editável colando o snippet de código abaixo. Agora você pode editar o texto como se o navegador fosse um editor de texto.

document.body.contentEditable = true;

Agora, vamos gravar essas alterações no arquivo original. Portanto, precisamos de um gravador no identificador de arquivo, que pode ser obtido colando o snippet abaixo no console. Novamente, precisamos de um gesto do usuário. Dessa vez, esperamos um clique no documento principal.

document.onclick = async () => {
  const writer = await handle.createWriter();
  await writer.truncate(0);
  await writer.write(0, document.body.textContent);
  await writer.close();
};

Quando você clicar no documento (não clique duas vezes) no documento, um prompt de permissão será exibido. Quando você concede permissão, o conteúdo do arquivo será o que você editou no body antes. Verifique as alterações. Para fazer isso, abra o arquivo em outro editor ou clique duas vezes no documento e abra o arquivo novamente para iniciar o processo.

Parabéns! Você acabou de criar o menor editor de texto do mundo: [citation needed].

Feedback

O que você achou dessa API? Responda a esta pesquisa para que possamos ajudar você:

O uso desta API era intuitivo?

Sim Não

Você conseguiu executar o exemplo?

Sim Não

Quer compartilhar algo mais? Faltam recursos? Responda rapidamente a esta pesquisa. Agradecemos sua colaboração.

A API Shape Detection oferece acesso a detectores de formato acelerados (por exemplo, para rostos humanos) e funciona com imagens estáticas e/ou feeds de imagens em tempo real. Os sistemas operacionais têm detectores de recursos com alto desempenho e otimizados, como o FaceDetector do Android. A API Shape Detection abre essas implementações nativas e as expõe por meio de um conjunto de interfaces JavaScript.

Atualmente, os recursos compatíveis são a detecção facial por meio da interface FaceDetector, a detecção de código de barras pela interface BarcodeDetector e a detecção de texto (reconhecimento óptico de caracteres) pela interface TextDetector.

Detecção facial

Um recurso fascinante da API Shape Detection é a detecção facial. Para testá-lo, precisamos de uma página com rostos. Esta página com o rosto do autor é um bom começo. Ele será parecido com a captura de tela abaixo. Em um navegador compatível, a caixa de limite do rosto e os pontos de referência do rosto serão reconhecidos.

Você pode ver quanto código foi necessário para que isso aconteça remixando ou editando o projeto Glitch, especialmente o arquivo script.js.

Se você quiser ser totalmente dinâmico e não funcionar somente com o rosto do autor, acesse esta página de resultados da Pesquisa Google cheia de rostos em uma guia particular ou no modo visitante. Nessa página, abra as Ferramentas para desenvolvedores do Chrome clicando com o botão direito do mouse em qualquer lugar e depois clique em Inspecionar. Em seguida, cole o snippet abaixo na guia "Console". O código destacará os rostos detectados com uma caixa vermelha transparente.

document.querySelectorAll('img[alt]:not([alt=""])').forEach(async (img) => {
  try {
    const faces = await new FaceDetector().detect(img);
    faces.forEach(face => {
      const div = document.createElement('div');
      const box = face.boundingBox;
      const computedStyle = getComputedStyle(img);
      const [top, right, bottom, left] = [
        computedStyle.marginTop,
        computedStyle.marginRight,
        computedStyle.marginBottom,
        computedStyle.marginLeft
      ].map(m => parseInt(m, 10));
      const scaleX = img.width / img.naturalWidth;
      const scaleY = img.height / img.naturalHeight;
      div.style.backgroundColor = 'rgba(255, 0, 0, 0.5)';
      div.style.position = 'absolute';
      div.style.top = `${scaleY * box.top + top}px`;
      div.style.left = `${scaleX * box.left + left}px`;
      div.style.width = `${scaleX * box.width}px`;
      div.style.height = `${scaleY * box.height}px`;
      img.before(div);
    });
  } catch(e) {
    console.error(e);
  }
});

Há alguns espaços do DOMException, e nem todas as imagens estão sendo processadas. Isso ocorre porque as imagens acima da dobra são inline como URIs de dados e podem ser acessadas, enquanto as imagens abaixo da dobra vêm de um domínio diferente que não está configurado para ser compatível com CORS. Para a demonstração, não precisamos nos preocupar com isso.

Detecção de pontos de referência do rosto

Além de rostos, o macOS também permite a detecção de pontos de referência. Para testar a detecção de pontos de referência do rosto, cole o snippet a seguir no Console. Lembrete: a lista de pontos de referência não é perfeita por causa do crbug.com/914348, mas você pode ver onde isso está ocorrendo e o poder desse recurso.

document.querySelectorAll('img[alt]:not([alt=""])').forEach(async (img) => {
  try {
    const faces = await new FaceDetector().detect(img);
    faces.forEach(face => {
      const div = document.createElement('div');
      const box = face.boundingBox;
      const computedStyle = getComputedStyle(img);
      const [top, right, bottom, left] = [
        computedStyle.marginTop,
        computedStyle.marginRight,
        computedStyle.marginBottom,
        computedStyle.marginLeft
      ].map(m => parseInt(m, 10));
      const scaleX = img.width / img.naturalWidth;
      const scaleY = img.height / img.naturalHeight;
      div.style.backgroundColor = 'rgba(255, 0, 0, 0.5)';
      div.style.position = 'absolute';
      div.style.top = `${scaleY * box.top + top}px`;
      div.style.left = `${scaleX * box.left + left}px`;
      div.style.width = `${scaleX * box.width}px`;
      div.style.height = `${scaleY * box.height}px`;
      img.before(div);

      const landmarkSVG = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
      landmarkSVG.style.position = 'absolute';
      landmarkSVG.classList.add('landmarks');
      landmarkSVG.setAttribute('viewBox', `0 0 ${img.width} ${img.height}`);
      landmarkSVG.style.width = `${img.width}px`;
      landmarkSVG.style.height = `${img.height}px`;
      face.landmarks.map((landmark) => {                    
        landmarkSVG.innerHTML += `<polygon class="landmark-${landmark.type}" points="${
        landmark.locations.map((point) => {          
          return `${scaleX * point.x},${scaleY * point.y} `;
        }).join(' ')
      }" /></svg>`;          
      });
      div.before(landmarkSVG);
    });
  } catch(e) {
    console.error(e);
  }
});

Detecção de código de barras

O segundo recurso da API Shape Detection é a detecção de código de barras. Assim como antes, precisamos de uma página com códigos de barras, como esta. Ao abri-lo em um navegador, você verá os vários códigos QR descriptografados. Remixe ou edite o projeto Glitch, especialmente o arquivo script.js, para ver como ele é feito.

Se você quiser algo mais dinâmico, use a Pesquisa de imagens do Google novamente. Desta vez, no seu navegador, acesse esta página de resultados da Pesquisa Google em uma guia particular ou no modo visitante. Agora, cole o snippet abaixo na guia do Console do Chrome DevTools. Depois de um breve momento, os códigos de barras reconhecidos serão anotados com o valor bruto e o tipo de código de barras.

document.querySelectorAll('img[alt]:not([alt=""])').forEach(async (img) => {
  try {
    const barcodes = await new BarcodeDetector().detect(img);
    barcodes.forEach(barcode => {
      const div = document.createElement('div');
      const box = barcode.boundingBox;
      const computedStyle = getComputedStyle(img);
      const [top, right, bottom, left] = [
        computedStyle.marginTop,
        computedStyle.marginRight,
        computedStyle.marginBottom,
        computedStyle.marginLeft
      ].map(m => parseInt(m, 10));
      const scaleX = img.width / img.naturalWidth;
      const scaleY = img.height / img.naturalHeight;
      div.style.backgroundColor = 'rgba(255, 255, 255, 0.75)';
      div.style.position = 'absolute';
      div.style.top = `${scaleY * box.top + top}px`;
      div.style.left = `${scaleX * box.left - left}px`;
      div.style.width = `${scaleX * box.width}px`;
      div.style.height = `${scaleY * box.height}px`;
      div.style.color = 'black';
      div.style.fontSize = '14px';      
      div.textContent = `${barcode.rawValue}`;
      img.before(div);
    });
  } catch(e) {
    console.error(e);
  }
});

Detecção de texto

O recurso final da API Shape Detection é a detecção de texto. Agora você já sabe o que precisamos fazer: precisamos de uma página com imagens que contenham texto, como esta com resultados de digitalização do Google Livros. Em navegadores compatíveis, você verá o texto reconhecido e uma caixa delimitadora ao redor dos trechos do texto. Remixe ou edite o projeto Glitch, especialmente o arquivo script.js, para ver como ele é feito.

Para testar isso de maneira dinâmica, acesse esta página de resultados da Pesquisa em uma guia particular ou no modo visitante. Agora, cole o snippet abaixo na guia do Console do Chrome DevTools. Com um pouco de espera, uma parte do texto será reconhecida.

document.querySelectorAll('img[alt]:not([alt=""])').forEach(async (img) => {
  try {
    const texts = await new TextDetector().detect(img);
    texts.forEach(text => {
      const div = document.createElement('div');
      const box = text.boundingBox;
      const computedStyle = getComputedStyle(img);
      const [top, right, bottom, left] = [
        computedStyle.marginTop,
        computedStyle.marginRight,
        computedStyle.marginBottom,
        computedStyle.marginLeft
      ].map(m => parseInt(m, 10));
      const scaleX = img.width / img.naturalWidth;
      const scaleY = img.height / img.naturalHeight;
      div.style.backgroundColor = 'rgba(255, 255, 255, 0.75)';
      div.style.position = 'absolute';
      div.style.top = `${scaleY * box.top + top}px`;
      div.style.left = `${scaleX * box.left - left}px`;
      div.style.width = `${scaleX * box.width}px`;
      div.style.height = `${scaleY * box.height}px`;
      div.style.color = 'black';
      div.style.fontSize = '14px';      
      div.innerHTML = text.rawValue;
      img.before(div);
    });
  } catch(e) {
    console.error(e);
  }
});

Feedback

O que você achou dessa API? Responda a esta pesquisa para que possamos ajudar você:

O uso desta API era intuitivo?

Sim Não

Você conseguiu executar o exemplo?

Sim Não

Quer compartilhar algo mais? Faltam recursos? Responda rapidamente a esta pesquisa. Agradecemos sua colaboração.

A API Web Share Target permite que apps da Web instalados se registrem no sistema operacional subjacente como um alvo de compartilhamento para receber conteúdo compartilhado da API Web Share ou de eventos do sistema, como o botão de compartilhamento no nível do sistema operacional.

Instalar um PWA para compartilhar

O primeiro passo é compartilhar um PWA. Desta vez, o Airhorner (Felizmente) não vai fazer esse trabalho, mas o app de demonstração Web Share Target está aqui para ajudar. Instale o app na tela inicial do dispositivo.

Compartilhe algo com o PWA

Em seguida, você precisa de algo para compartilhar, como uma foto do Google Fotos. Use o botão "Compartilhar" e selecione o PWA do mural como destino de compartilhamento.

Ao tocar no ícone do app, você entra diretamente no PWA do Scrapbook, e a foto é exibida aqui.

Como isso funciona? Para descobrir, explore o manifesto do app da Web do PWA do Scrapbook. A configuração para que a API Web Share Target funcione na propriedade "share_target" do manifesto, no campo "action", aponta para um URL que é decorado com parâmetros, conforme listado em "params".

O lado de compartilhamento preenche esse modelo de URL adequadamente, seja facilitado por uma ação de compartilhamento ou controlado programaticamente pelo desenvolvedor usando a API Web Share. Assim, o lado do destinatário pode extrair os parâmetros e fazer algo com eles, como exibi-los.

{
  "action": "/_share-target",
  "enctype": "multipart/form-data",
  "method": "POST",
  "params": {
    "files": [{
      "name": "media",
      "accept": ["audio/*", "image/*", "video/*"]
    }]
  }
}

Feedback

O que você achou dessa API? Responda a esta pesquisa para que possamos ajudar você:

O uso desta API era intuitivo?

Sim Não

Você conseguiu executar o exemplo?

Sim Não

Quer compartilhar algo mais? Faltam recursos? Responda rapidamente a esta pesquisa. Agradecemos sua colaboração.

Para evitar o descarregamento da bateria, a maioria dos dispositivos entra no modo de suspensão rapidamente quando fica inativa. Embora isso não seja um problema na maioria das vezes, alguns aplicativos precisam manter a tela ou o dispositivo ativado para concluir o trabalho. A API Wake Lock oferece uma forma de impedir que o dispositivo escureça e bloqueie a tela ou impeça que o dispositivo entre em suspensão. Essa funcionalidade permite novas experiências que, até agora, exigiam um aplicativo nativo.

Configurar um protetor de tela

Para testar a API Wake Lock, primeiro verifique se o dispositivo está suspenso. Por isso, no painel de preferências do sistema operacional, ative um protetor de tela de sua preferência e ele comece em um minuto. Para que o recurso funcione, deixe seu dispositivo sozinho durante esse período (sabe, é difícil). As capturas de tela abaixo mostram o macOS, mas você pode tentar fazer isso no seu dispositivo móvel Android ou em qualquer plataforma de computador compatível.

Definir um wake lock de tela

Agora que você sabe que o protetor de tela está funcionando, use um wake lock do tipo "screen" para evitar que o protetor de tela faça o trabalho dele. Acesse o app de demonstração do Wake Lock e clique na caixa de seleção Ativarscreen Wake Lock.

A partir desse momento, um wake lock fica ativo. Se você tiver paciência para deixar o dispositivo intocado por um minuto, verá que o protetor de tela realmente não começou.

Como isso funciona? Para descobrir, acesse o projeto Glitch para o app de demonstração Wake Lock e confira script.js. A essência do código está no snippet abaixo. Abra uma nova guia (ou use qualquer que estiver aberta) e cole o código abaixo em um Console das Ferramentas para desenvolvedores do Chrome. Ao clicar na janela, você verá um wake lock ativo por exatamente 10 segundos (veja os registros do console) e o protetor de tela não deverá ser iniciado.

if ('wakeLock' in navigator && 'request' in navigator.wakeLock) {  
  let wakeLock = null;
  
  const requestWakeLock = async () => {
    try {
      wakeLock = await navigator.wakeLock.request('screen');
      wakeLock.addEventListener('release', () => {        
        console.log('Wake Lock was released');                    
      });
      console.log('Wake Lock is active');      
    } catch (e) {      
      console.error(`${e.name}, ${e.message}`);
    } 
  };

  requestWakeLock();
  window.setTimeout(() => {
    wakeLock.release();
  }, 10 * 1000);
}

Feedback

O que você achou dessa API? Responda a esta pesquisa para que possamos ajudar você:

O uso desta API era intuitivo?

Sim Não

Você conseguiu executar o exemplo?

Sim Não

Quer compartilhar algo mais? Faltam recursos? Responda rapidamente a esta pesquisa. Agradecemos sua colaboração.

Uma API que estamos muito empolgadas é a API Contact Picker. Ele permite que um app da Web acesse os contatos do gerenciador de contatos nativo do dispositivo para que ele tenha acesso aos seus contatos, nomes, endereços de e-mail e números de telefone. Você pode especificar se quer usar um ou vários contatos e todos os campos ou apenas um subconjunto de nomes, endereços de e-mail e números de telefone.

Considerações sobre privacidade

Quando o seletor for aberto, você poderá selecionar os contatos que deseja compartilhar. Você não verá a opção "Selecionar tudo" deliberadamente: queremos que o compartilhamento seja uma decisão consciente. Da mesma forma, o acesso não é contínuo, mas sim uma decisão única.

Como acessar contatos

Acessar contatos é uma tarefa simples. Antes de abrir o seletor, você pode especificar quais campos serão adicionados (as opções name, email e telephone) e se você quer acessar vários ou apenas um contato. Para testar essa API em um dispositivo Android, abra o app de demonstração. A seção relevante do código-fonte é essencialmente o snippet abaixo:

getContactsButton.addEventListener('click', async () => {
  const contacts = await navigator.contacts.select(
      ['name', 'email'],
      {multiple: true});
  if (!contacts.length) {
    // No contacts were selected, or picker couldn't be opened.
    return;
  }
  console.log(contacts);
});

Copiar e colar texto

Até agora, não era possível copiar e colar imagens de forma programática na área de transferência do sistema. Recentemente, adicionamos suporte a imagens à API Async Clipboard,

para copiar e colar imagens. A novidade é que você também pode gravar imagens na área de transferência. A API de área de transferência assíncrona era compatível com o recurso de copiar e colar texto por um tempo. Você pode copiar o texto da área de transferência chamando navigator.clipboard.writeText() e, em seguida, colar esse texto chamando navigator.clipboard.readText().

Copiar e colar imagens

Agora você também pode gravar imagens na área de transferência. Para que isso funcione, você precisa dos dados da imagem como um blob, que será transmitido para o construtor do item da área de transferência. Por fim, você pode copiar esse item da área de transferência chamando navigator.clipboard.write().

// Copy: Writing image to the clipboard
try {
  const imgURL = 'https://developers.google.com/web/updates/images/generic/file.png';
  const data = await fetch(imgURL);
  const blob = await data.blob();
  await navigator.clipboard.write([
    new ClipboardItem(Object.defineProperty({}, blob.type, {
      value: blob,
      enumerable: true
    }))
  ]);
  console.log('Image copied.');
} catch(e) {
  console.error(e, e.message);
}

Colar a imagem na área de transferência parece bastante complexa, mas, na verdade, apenas consiste em recuperar o blob do item da área de transferência. Como pode haver várias opções, é necessário repeti-las até encontrar aquela em que você tem interesse. Por motivos de segurança, no momento isso está limitado a imagens PNG, mas mais formatos de imagem poderão ser compatíveis no futuro.

async function getClipboardContents() {
  try {
    const clipboardItems = await navigator.clipboard.read();
    for (const clipboardItem of clipboardItems) {
      try {
        for (const type of clipboardItem.types) {
          const blob = await clipboardItem.getType(type);
          console.log(URL.createObjectURL(blob));
        }
      } catch (e) {
        console.error(e, e.message);
      }
    }
  } catch (e) {
    console.error(e, e.message);
  }
}

É possível ver essa API em ação em um app de demonstração. Os snippets relevantes do código-fonte deles estão incorporados acima. É possível copiar imagens para a área de transferência sem permissão, mas você precisa conceder acesso para colá-las.

Depois de conceder acesso, você poderá ler a imagem na área de transferência e colá-la no aplicativo:

Parabéns, você chegou ao fim do codelab. Mais uma vez, esse é um lembrete de que a maioria das APIs ainda está em fluxo e em desenvolvimento. Por isso, a equipe trabalha muito com seu feedback, já que somente a interação com pessoas como você vai nos ajudar a aprimorar essas APIs.

Também recomendamos que você confira nossa página de destino de recursos com frequência. Vamos mantê-lo atualizado e ter indicadores para todos os artigos detalhados das APIs em que trabalhamos. Continue arrasando!

Tom e toda a equipe de Recursos 🐡