From eb1e17770af84d50ecba0500a6980ba9531d4b67 Mon Sep 17 00:00:00 2001 From: nancywu1 Date: Thu, 6 Mar 2025 10:30:08 -0500 Subject: [PATCH] iOS expose onStart hook --- ios/core/Sources/Player/HeadlessPlayer.swift | 3 ++ ios/core/Sources/Types/Core/FlowType.swift | 43 +++++++++++++++++++ ios/core/Tests/FlowStateTests.swift | 6 +++ .../Sources/FlowData.swift | 3 ++ ios/swiftui/Sources/SwiftUIPlayer.swift | 4 ++ .../utilities/HeadlessPlayerImpl.swift | 3 ++ .../Sources/utilities/TestPlayer.swift | 3 ++ 7 files changed, 65 insertions(+) create mode 100644 ios/core/Sources/Types/Core/FlowType.swift diff --git a/ios/core/Sources/Player/HeadlessPlayer.swift b/ios/core/Sources/Player/HeadlessPlayer.swift index ae7d57e8b..313b80e4b 100644 --- a/ios/core/Sources/Player/HeadlessPlayer.swift +++ b/ios/core/Sources/Player/HeadlessPlayer.swift @@ -59,6 +59,9 @@ public protocol CoreHooks { /// Fired when the state changes var state: Hook { get } + /// A hook to access the current flow + var onStart: Hook { get } + /// Initialize hooks from reference to javascript core player init(from: JSValue) } diff --git a/ios/core/Sources/Types/Core/FlowType.swift b/ios/core/Sources/Types/Core/FlowType.swift new file mode 100644 index 000000000..08925200f --- /dev/null +++ b/ios/core/Sources/Types/Core/FlowType.swift @@ -0,0 +1,43 @@ +// +// FlowType.swift +// PlayerUI +// +// Created by Zhao Xia Wu on 2025-03-05. +// + +import Foundation +import JavaScriptCore + +/** +A wrapper around the JS FlowType in the core player +The JSON payload for running Player, different from the Flow class which is the Flow Instance which contains the navigation state machine +*/ +public class FlowType: CreatedFromJSValue { + /// Typealias for associated type + public typealias T = FlowType + + /// The ID of this flow + public var id: String? { value.objectForKeyedSubscript("id")?.toString() } + + /// The original data associated with this flow + public var data: [String: Any]? { value.objectForKeyedSubscript("data")?.toObject() as? [String: Any] } + + /** + Creates an instance from a JSValue, used for generic construction + - parameters: + - value: The JSValue to construct from + */ + public static func createInstance(value: JSValue) -> FlowType { FlowType(value) } + + /// The JSValue that backs this wrapper + public private(set) var value: JSValue + + /** + Construct a Flow from a JSValue + - parameters: + - value: The JSValue that is the Flow + */ + public init(_ value: JSValue) { + self.value = value + } +} diff --git a/ios/core/Tests/FlowStateTests.swift b/ios/core/Tests/FlowStateTests.swift index 7121f2058..01e150ea5 100644 --- a/ios/core/Tests/FlowStateTests.swift +++ b/ios/core/Tests/FlowStateTests.swift @@ -39,6 +39,12 @@ class FlowStateTests: XCTestCase { func testActionFlowState() { let player = HeadlessPlayerImpl(plugins: []) let hitActionNode = expectation(description: "ACTION state hit") + + player.hooks?.onStart.tap { flow in + XCTAssertEqual(flow.id, "counter-flow") + XCTAssertEqual(flow.data as? [String: Int], ["count": 0]) + } + player.hooks?.flowController.tap({ flowController in flowController.hooks.flow.tap { flow in flow.hooks.transition.tap { oldState, _ in diff --git a/ios/internal-test-utils/Sources/FlowData.swift b/ios/internal-test-utils/Sources/FlowData.swift index bd2555eb1..be3be8e97 100644 --- a/ios/internal-test-utils/Sources/FlowData.swift +++ b/ios/internal-test-utils/Sources/FlowData.swift @@ -122,6 +122,9 @@ public struct FlowData { { "id": "counter-flow", "views": [], + "data": { + "count": 0 + }, "navigation": { "BEGIN": "FLOW_1", "FLOW_1": { diff --git a/ios/swiftui/Sources/SwiftUIPlayer.swift b/ios/swiftui/Sources/SwiftUIPlayer.swift index 13bb62ee0..a98036544 100644 --- a/ios/swiftui/Sources/SwiftUIPlayer.swift +++ b/ios/swiftui/Sources/SwiftUIPlayer.swift @@ -288,6 +288,9 @@ public struct SwiftUIPlayerHooks: CoreHooks { /// Provide Transition Animation information for transition views in the same flow public var transition: SyncBailHook + /// Provides access to the current flow + public var onStart: Hook + /// Initialize hooks from reference to javascript core player public init(from player: JSValue) { flowController = Hook(baseValue: player, name: "flowController") @@ -296,6 +299,7 @@ public struct SwiftUIPlayerHooks: CoreHooks { state = Hook(baseValue: player, name: "state") view = SyncWaterfallHook() transition = SyncBailHook() + onStart = Hook(baseValue: player, name: "onStart") } } diff --git a/ios/test-utils-core/Sources/utilities/HeadlessPlayerImpl.swift b/ios/test-utils-core/Sources/utilities/HeadlessPlayerImpl.swift index 8c870b82c..fc2e25a68 100644 --- a/ios/test-utils-core/Sources/utilities/HeadlessPlayerImpl.swift +++ b/ios/test-utils-core/Sources/utilities/HeadlessPlayerImpl.swift @@ -33,11 +33,14 @@ public class HeadlessHooks: CoreHooks { public var state: Hook + public var onStart: Hook + required public init(from value: JSValue) { flowController = Hook(baseValue: value, name: "flowController") viewController = Hook(baseValue: value, name: "viewController") dataController = Hook(baseValue: value, name: "dataController") state = Hook(baseValue: value, name: "state") + onStart = Hook(baseValue: value, name: "onStart") } } diff --git a/ios/test-utils-core/Sources/utilities/TestPlayer.swift b/ios/test-utils-core/Sources/utilities/TestPlayer.swift index 80b4da123..8bf34c205 100644 --- a/ios/test-utils-core/Sources/utilities/TestPlayer.swift +++ b/ios/test-utils-core/Sources/utilities/TestPlayer.swift @@ -48,10 +48,13 @@ public class TestHooks: CoreHooks { public var state: Hook + public var onStart: Hook + public required init(from player: JSValue) { flowController = Hook(baseValue: player, name: "flowController") viewController = Hook(baseValue: player, name: "viewController") dataController = Hook(baseValue: player, name: "dataController") state = Hook(baseValue: player, name: "state") + onStart = Hook(baseValue: player, name: "onStart") } }