Search code examples
javascriptcodeignitermanifestservice-workerprogressive-web-apps

How to display shared photo in PWA?


I have successfully managed to add my PWA to the share options of my device, the problem is that I don't know how to receive/display the shared photo in my PWA.

share_target in manifest.json

"share_target": {
      "action": "/photos/shared",
      "method": "POST",
      "enctype": "multipart/form-data",
      "params": {
        "files": [{
            "name": "file",
            "accept": ["*/*"]
        }]
      }
    }

I'm using CodeIgniter so I've added photos/shared as a route

$route['photos/shared']['post'] = 'webapp/PhotosController/sharedPhoto';

and expected to receive post data of shared photo in my controller

public function sharedPhoto () {

            echo "<pre>";
                die(var_dump( $_POST )); // empty!
            echo "</pre>";

    }

But, unfortunately it is empty.

After some reading I found this:

The foreground page cannot process this data directly. Since the page sees the data as a request, the page passes it to the service worker, where you can intercept it with a fetch event listener.

on this website, so I've added this code to my service worker(I followed this tutorial)

self.addEventListener('fetch', function(event) {
  if (event.request.clone().method === 'POST') {
       const url = new URL(event.request.clone().url);
       console.log( 'URL' );
       console.log( url );
       if (event.request.clone().url.endsWith('/photos/shared') || url.pathname == '/photos/shared') {
            event.respondWith(Response.redirect('./'));

            event.waitUntil(async function () {
                const data = await event.request.formData();
                console.log( data );
                const client = await self.clients.get(event.resultingClientId);
                console.log( client );
                const file = data.get('file');
                client.postMessage( {file});
            }());
       } else {
       // do other non related stuff
       }

After that I've added event listener for post message to my javascript file

    navigator.serviceWorker.addEventListener('message', event => {
    // this is triggered but file is always empty
    const file = event.data.file;
    const img  = new Image();
    const url = URL.createObjectURL(file);
    img.src = url;
    document.body.append(img);
  });

But, I just can't get the image to display in my app, the file is always empty.


Solution

  • Ok so the latest changes to manifest and service worker(I've updated my question) actually worked. The only thing I had to do is change code in message event listener to be able to see the image.

    navigator.serviceWorker.addEventListener('message', event => {
    
     const file = event.data.file;
     const img  = new Image();
     const url = URL.createObjectURL(file);
     img.src = url;
     $("body").empty();
     $("body").append(img);
     $("body").append(url);
     $("body").append('<h1>test</h1>');
    
    });
    

    Now that I can access the photo in my app, I can finally do the operations neccessary on it.