MaikuB / flutter_appauth

A Flutter wrapper for AppAuth iOS and Android SDKs
270 stars 243 forks source link

[MacOS] Deeplink handling fails when another plugin registers an event handler #358

Open JordyLangen opened 2 years ago

JordyLangen commented 2 years ago

We've run into the issue that we have multiple plugins that depend on setting an event handler through NSAppleEventManager.shared().setEventHandler, the next one always overwriting the previous one.

In our case it's the uni_links_desktop plugin that handles every deeplink as it registers after the flutter app_auth plugin. To solve this, we've come up with two solutions:

  1. A FlutterAppAuth static instance is exposed, so we can do something like this:
    // our own event handler that calls every plugins `handleURLEvent` method
    public func handleURLEvent(_ event: NSAppleEventDescriptor, with replyEvent: NSAppleEventDescriptor) {
        HandlerA.instance.handleURLEvent(...)
        HandlerB.instance.handleURLEvent(...)
       // other handlers
    }
  1. A new method on the platform interface like processCallback(url) which we can call after uni_links gave us the callback url on the flutter side. (I understand this solution solves our problem, not necessarily everyones problem who might run into the same issue). I've made a quick proof of concept and this would work.

Let me know what you think, we'd be happy to help out and create the PR if needed.

MaikuB commented 2 years ago

Thanks for raising this issue. Unfortunately I'm having trouble visualising both approaches so would it be possible to have a draft PR for each one?

JordyLangen commented 2 years ago

Hi @MaikuB

As for the drafts:

  1. An example can be found here: https://github.com/pichillilorenzo/flutter_inappwebview/blob/master/ios/Classes/SwiftFlutterPlugin.swift#L27 Basicly this would mean there is a singleton instance available of the native plugin instance.
  2. I've created https://github.com/MaikuB/flutter_appauth/pull/363

Let me know what you think

MaikuB commented 2 years ago

Thanks for that @JordyLangen . Should preface this by saying I don't have much experience working on macOS so bear with me as my questions could be stupid :)

Anyway, I've been doing some researching, looking at what you have and got the following questions

  1. Regarding the approach to expose the singleton, suppose that is exposed then how would the singleton be used? If it involves making more methods public then most plugins shouldn't need to expose the native methods as as consumers typically use the Dart API. Exposing the methods means there's the public API surface has expanded so means there could be more breaking changes that can happen
  2. I was able to reproduce the issue you mentioned when using this plugin alongside uni_links_desktop. However, the way I interpreted your original message was that the issue happens when multiple plugins call NSAppleEventManager.shared().setEventHandler. I didn't see this code at all with that plugin. I'm wondering if the issue lies elsewhere
  3. Suppose there is an issue that requires the 2nd approach, how does one decide which plugin is the one that should be fixing the issue? It sounds like potentially the uni_links_desktop plugin could also be the one that could have the fix done rather than this plugin
  4. Is there a better approach? Seems like either approach could potentially require plugins developed by the community to conform to an approach to get around the issue as the issue doesn't look like one that's specific to just this plugin but any that deals with handling deep links. Furthermore, I would think this issue is more common within the macOS development community that there's potentially a better approach. For example, I know method swizzling tends to be used when there are multiple libraries that need handle the same event e.g. multiple libraries that register themselves as the delegate to process notification events. I'm not familiar with implementing this but perhaps this is a solution? In case the issue is to do with multiple handlers, then perhaps the Flutter APIs on macOS could allow for adding multiple handlers. For example on iOS, there's this API available so multiple plugins can process UIApplicationDelegate calls