StreamDeckPlugin icon indicating copy to clipboard operation
StreamDeckPlugin copied to clipboard

thanks ! and one small question

Open justme-1968 opened this issue 1 year ago • 2 comments

thanks for the three fixes/changes. everything works like a charm. including me routing the deep link event from the plugin to the specific action it has to go to.

just one question at the moment, but also not really important as hardcoding works for now: for generating the deep link callback url i have to access the uuid/uri of my plugin. i had hoped to use PluginCommunication.shared.uuid for this, but of course this is the runtime uuid to for the websocket communication and not the id/uri that is used to generate the manifest.

do you have an idea if it is possible to access this information from the manifest generation at runtime in the plugin? maybe setting it in the plugin/plugin delagate so it has not to be fiven at the cmd line later?

the api and documentation is quite sloppy here also. it mixes uuid and uri and both are not really in a format they should be if the names were to be taken literally...

justme-1968 avatar Mar 11 '24 20:03 justme-1968

Glad everything is working, thanks for bringing all of the various issues to my attention. None of my current plugins need deep linking, so if you wouldn't mind sharing how you're doing the routing it might be helpful to add to the readme.

The UUID is the identifier given by the Stream Deck app to the plugin instance. It's only used by the plugin to identify requests, and generally shouldn't be used by users of the library.

The URI is the more public facing identifier of the plugin, however isn't currently defined in the code of a Plugin implementation, only by the export command. This is something I've thought about changing, including the URI as part of the Plugin protocol.

As a workaround you could define a uri property on your Plugin and access the value through the shared plugin instance like so (PluginCommunication.shared.plugin as! YourPlugin).uri. The alternative would be to locate the binary at runtime, locate the manifest, and parse it manually.

emorydunn avatar Mar 12 '24 02:03 emorydunn

our suggestion for the uri is nice and similar to my idea for the routing so i should have came up with this myself :). but it still has the possibility of having two different values: one in the plugin code and one in the call to create the manifest. a single source for both would be better.

for the forwarding of the deep link reply from the plugin to the action (without the need to change the framework) i came up with this:

  • the format that has to be used for the reply looks like this (see api documentation):
    streamdeck://plugins/message/<PLUGIN_UUID>/{MESSAGE} where <PLUGIN_UUID> is what is the uri given during manifest creation. not the uuid from the registration api. when the stream deck application receives this link only the {MESSAGE} part is forwarded to the plugin. everything in front is stripped.

  • to allow forwarding i'm using the action's uuid as the first part of {MESSAGE} so the format looks like this: streamdeck://plugins/message/<PLUGIN_UUID>/<ACTION_UUID>/{MESSAGE}

  • then i use a small protocol like this:

    protocol deepLinkReceiver {
       func didReceiveDeepLink(_ url: URL)
    }
    

    and make the Action implementation conform to deepLinkReceiver

  • in the Plugin implementation i use a didReceiveDeepLink implementation like so:

      func didReceiveDeepLink(_ url: URL) {
          log.log("didReceiveDeepLink: \(url.description, privacy: .public)")
    
          let uuid = url.pathComponents[1]
    
          if let action = PluginCommunication.shared[uuid],
             let action = action as? deepLinkReceiver {
              action.didReceiveDeepLink(url)
    
          } else {
              log.log("not found ...")
          }
      }
    

there are certainly more elegant ways but this works fine and requires no changes to the framework.

one more thing: the openURL call from the plugin api can not be used issue the initial x-callback call. it handles only http and https calls. you have to use one of the platform native calls.

justme-1968 avatar Mar 12 '24 11:03 justme-1968