navigator.share won't resolve nor reject when user cancels native selector on android
Asked Answered
A

1

7

So, we are implementing navigator.share() (https://developers.google.com/web/updates/2016/09/navigator-share) in an Ionic v3 PWA.

It works, but there's a little problem we encountered which we don't know how to fix: when the navite share selector pops up (user can select betwen inbox, gmail, twitter, etc) and the user then presses the back button on android (dismissing the native modal that came up), the function doesn't trigger any response in the promise. Not success, not error.

The problem here is that we show a loading spinner before we call the navigator.share function and if the user presses that back button at that precise moment, we can't trigger the function that hides the loading spinner.

This is the part of the code where we implement the feature:

public share(title: string, message: string, url: string) {
    // if it's mobile & web (ie: chrome on android)
    if (this.isMobileWeb === true) {
        this.showLoading();
        if ((navigator as any).share) {
            (navigator as any).share({
                title,
                message,
                url,
            })
                .then(() => {
                    console.log('Success share');
                    this.hideLoading();
                })
                .catch((error) => {
                    console.log('Error share', error);
                    this.hideLoading();
                });
        }
        else {
            console.log('navigator.share() not supported.');
            this.hideLoading();
        }
    }
}

With this implementation, no success or error is thrown if the user presses the back button when the native share modal comes up. Is there something wrong with this code?

I've also tried adding another callback function inside the .then() function, as in: .then(successFn, errorFn). The errorFn is never called either.

Thanks for your time.-

Attending answered 5/4, 2018 at 2:28 Comment(1)
I have a similar problem. The promise gets resolved right away when user shares, but it doesn't get rejected right away when user cancels. It will get rejected whenever share menu is opened again though.Somatic
A
5

This is a long-standing bug in Android. Here is my solution for it, but I can't take credit for the technique. It was mentioned in the bug tracker linked below. Pardon the use of ES6 syntax. The idea is that you would call this share function instead of the 'navigator.share' function directly.

export default options => new Promise((resolve, reject) => {
  navigator.share(options).then(resolve).catch(error => {
    // Differentiate between user 'AbortError' and internal errors.
    // E.g. Internal error: could not connect to Web Share interface.
    if (error.message.startsWith('Internal error:'))
      error.name = 'InternalError';

    reject(error);
  });

  /*
   * https://bugs.chromium.org/p/chromium/issues/detail?id=636274
   * If the share promise is not resolved or rejected when focus is returned to
   * the window, then reject it after a 100ms delay.
   */
  let cancel = () => setTimeout(() => {
    window.removeEventListener('focus', cancel);

    let error = new Error('Share cancelled');
    error.name = 'ShareTimeout';
    reject(error);
  }, 100);

  window.addEventListener('focus', cancel);
});
Aeolis answered 29/8, 2019 at 14:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.