External Action
The External Action Plugin is an easy way to handle External states from the navigation of a Player flow.
Install the plugin:
npm i @player-ui/external-action-pluginyarn add @player-ui/external-action-pluginpnpm add @player-ui/external-action-pluginCreate a handler for external actions:
import { ExternalStateHandler } from '@player-ui/external-action-plugin';
const externalActionHandler: ExternalStateHandler = async (state, options) => { if (state.ref === 'custom') { return 'next'; }}Add it to Player:
import { Player } from "@player-ui/player";import { ExternalActionPlugin } from "@player-ui/external-action-plugin";
const player = new Player({ plugins: [new ExternalActionPlugin(externalActionHandler)],});This will transition any EXTERNAL state in Player’s navigation, with a ref property of custom using the next transition.
The ExternalActionPlugin adds support for handling EXTERNAL navigation states in the application. The handler, which can be provided during plugin initialization, receives three parameters:
- state:
NavigationFlowExternalStateprovides access to the information defined in theEXTERNALstate node - options:
ControllerStateprovides access to the current player controllers - transition:
(String) -> Unitis provided to enable the handler to “complete” theEXTERNALstate and transition using the providedStringvalue
In build.gradle
implementation "com.intuit.playerui.plugins:external-action:$PLAYER_VERSION"In Player constructor
import com.intuit.playerui.plugins.externalAction.ExternalActionPlugin
val externalActionPlugin = ExternalActionPlugin { state, options, transition -> // access external state node val extraProperty = state["extraProperty"] // access data model options.data.get("{{foo.bar}}") // evaluate expression options.expression.evaluate("{{foo.bar}} = 1") // do other processing or show non-player experience
// transition to the next node using "Next" transition("Next")}AndroidPlayer(externalActionPlugin)
// handler can be configured after instantiationexternalActionPlugin.onExternalAction { /** handle external action */ }
// extension method for configuring plugin with player instanceandroidPlayer.onExernalAction { /** handle external action */ }In Player content
{ "navigation": { "BEGIN": "FLOW_1", "FLOW_1": { "startState": "EXT_1", "EXT_1": { "state_type": "EXTERNAL", "ref": "test-1", "transitions": { "Next": "END_FWD", "Prev": "END_BCK" }, "extraProperty": "extraValue" }, "END_FWD": { "state_type": "END", "outcome": "FWD" }, "END_BCK": { "state_type": "END", "outcome": "BCK" } } }}Public API available from sources here:
CocoaPods
Add the subspec to your Podfile.
pod 'PlayerUI/ExternalActionPlugin'In your Swift file, import the pod. Only one import is needed for all PlayerUI pods.
import PlayerUISwift Package Manager
Add the product to the appropriate target's dependencies in your Package.swift.
.target( name: "MyApp", dependencies: [ .product(name: "PlayerUIExternalActionPlugin", package: "playerui-swift-package"), ])In your Swift file, import the sub-package. A different import is needed for each PlayerUI sub-package.
import PlayerUIExternalActionPluginSwift Usage
Section titled “Swift Usage”For an example flow with an external state such as:
{ "id": "test-flow", "data": { "transitionValue": "Next" }, "navigation": { "BEGIN": "FLOW_1", "FLOW_1": { "startState": "EXT_1", "EXT_1": { "state_type": "EXTERNAL", "ref": "test-1", "transitions": { "Next": "END_FWD", "Prev": "END_BCK" }, "extraProperty": "extraValue" }, "END_FWD": { "state_type": "END", "outcome": "FWD" }, "END_BCK": { "state_type": "END", "outcome": "BCK" } } }}The plugin can be declared to handle this external state, whether that means integrating an existing platform native experience, or doing headless processing:
let plugin = ExternalActionPlugin { state, options, transition in guard state.ref == "test-1" else { return transition("Prev") } // Options contains the dataModel as well as an evaluate function for expressions let transitionValue = options.data.get(binding: "transitionValue") as? String options.expression.evaluate("{{foo}} = 'bar'")
let extraProperty: String? = state.extraProperty // uses @dynamicMemberLookup // Do some processing transition(transitionValue ?? "Next")}
var body: some View { SwiftUIPlayer( flow: flow, plugins: [ plugin ], result: $resultBinding )}