Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle images offline in a PWA share target?

I can register my Progressive Web App as a share target for images (supported from Chrome Android 76):

"share_target": {
    "action": "/share-target",
    "method": "POST",
    "enctype": "multipart/form-data",
    "params": {
      "files": [
        {
          "name": "myImage",
          "accept": ["image/jpeg", "image/png"]
        }
      ]
    }
  }

I can then intercept attempts to share images to the app in a service worker:

self.addEventListener('fetch', e => {
  if (e.request.method === 'POST' && e.request.url.endsWith('/share-target')) {
    // todo
  }
})

How would I display the shared image in my offline PWA?

like image 512
Daniel Elkington Avatar asked Sep 13 '19 05:09

Daniel Elkington


People also ask

Does PWA support offline?

Our app is caching its resources on install and serving them with fetch from the cache, so it works even if the user is offline.

How do I make PWA available offline?

In order for your PWA to be offline-capable, service workers pay a part in serving the content, but you'd also need to cache your page's resources as well. To cache your page's resources, first you need to plan out the size of your Cache Storage since there's a limit to it.

What is PWA offline?

PWA is a web application, which can be installed on your system. It works offline when there is no internet connection, leveraging data cached during your last interactions with the app.

How do you share PWA?

You can share to the app by registering it as a share target, with the Web Share Target API. This is done through an entry in the manifest file. These two advanced capabilities help your PWA integrate seamlessly with your platform, and create a smooth, unified sharing experience.


Video Answer


1 Answers

There are a few different steps to take here.

I put together a working example at https://web-share-offline.glitch.me/, with the source at https://glitch.com/edit/#!/web-share-offline

Ensure your web app works offline

This is a prerequisite, and I accomplished it by generating a service worker that would precache my HTML, JS, and CSS using Workbox.

The JS that runs when the home page is loaded uses the Cache Storage API to read a list of image URLs that have been cached, to creates <img> elements on the page corresponding to each one.

Create a share target handler that will cache images

I also used Workbox for this, but it's a bit more involved. The salient points are:

  • Make sure that you intercept POST requests for the configured share target URL.
  • It's up to you to read in the body of the shared images and to write them to your local cache using the Cache Storage API.
  • After you save the shared image to cache, it's a good idea to respond to the POST with a HTTP 303 redirected response, so that the browser will display the actual home page for your web app.

Here's the Workbox configuration code that I used to handle this:

const shareTargetHandler = async ({event}) => {
  const formData = await event.request.formData();
  const cache = await caches.open('images');

  await cache.put(
      // TODO: Come up with a more meaningful cache key.
      `/images/${Date.now()}`,
      // TODO: Get more meaningful metadata and use it
      // to construct the response.
      new Response(formData.get('image'))
  );

  // After the POST succeeds, redirect to the main page.
  return Response.redirect('/', 303);
};

module.exports = {
  // ... other Workbox config ...
  runtimeCaching: [{
    // Create a 'fake' route to handle the incoming POST.
    urlPattern: '/share-target',
    method: 'POST',
    handler: shareTargetHandler,
  }, {
    // Create a route to serve the cached images.
    urlPattern: new RegExp('/images/\\d+'),
    handler: 'CacheOnly',
    options: {
      cacheName: 'images',
    },
  }],
};
like image 161
Jeff Posnick Avatar answered Oct 10 '22 05:10

Jeff Posnick