jordanbyron / react-native-quick-actions

A react-native interface for Touch 3D home screen quick actions
MIT License
1.06k stars 94 forks source link

How to deal with QuickActions, Linking and "normal opening"... #41

Closed njt1982 closed 6 years ago

njt1982 commented 7 years ago

I have an opening scene component which does something like this:

  _handleQuickAction(action) {
    switch (action.type) {
      case 'com.domain.myapp.action1' :
        this.authenticate('DeepLinkedPage1');
        break

      case 'com.domain.myapp.action2' :
        this.authenticate('DeepLinkedPage2');
        break

      default :
        console.log('Unknown Action');
    }
  }

  _processUrl(url) {
    const result = url.match('myapp://page/(.+)');
    if (result) {
      this.authenticate('DeepLinkedPage1', {id: result[1]});
      return true;
    }
    return false;
  }

  componentDidMount() {
    DeviceEventEmitter.addListener('quickActionShortcut', this._handleQuickAction.bind(this));
    QuickActions.popInitialAction().then(this._handleQuickAction.bind(this)).catch(console.error)

    Linking.addEventListener('url', this._handleOpenURL.bind(this));

    Linking.getInitialURL().then((url) => {
      if (url && this._processUrl(url)) {
        console.log('Initial url is: ' + url);
      }
      else {
        this.authenticate();
      }
    });
  }

This doesn't entirely work... Essentially I'm getting race conditions where promises are firing the authenticate method after the "else" toward the end.

When this page loads, I need to know if I need to:

However, of course, the nature of a promise is that it's asynchronous. the popInitialAction fires then lets the promise go off and do what it wants and in the mean time, this thread goes off and says "Ok, there is no URL, so just authenticate to HomeScene. THEN the QuickActions fires up and tries to authenticate to one of the actions.

This Authentication is usually TouchID (Falls back to GoogleAuth). The above workflow causes this error:

Authentication was canceled by system—for example, if another application came to foreground while the authentication dialog was up.

How would you suggest dealing with multiple listeners and promises which fall back to a normal auth?

Do I need to wrap the QuickActions and Linking in some kind of Promise.Race?

njt1982 commented 7 years ago

The problem with Promise.Race is that it'll resolve as soon as any one of the 3 cases resolves (like the "nothing to do lets go to Home" scenario).

Promise.all is closer.. it'll wait for all of them to resolve... I guess I could use that to resolve Linking and QuickActions and then use a .finally for the main authenticate... but I'd only want finally to run if the first two promises resolve with no action. And Promise.all fails fast; if I get my QuickAction/Linking promises to reject if they have nothing to do, then the first one that rejects will cause the other to not run.

jordanbyron commented 6 years ago

Hey @njt1982,

This seems more like a question suited for StackOverflow rather than our bug tracker. If you think there is a defect in react-native-quick-actions or a feature that could be added to allow for the type of workflow you are suggesting then this is the right place. Sorry it took me so long to say "Try someplace else". Best of luck! 🐎