Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions ios/core/Sources/Player/HeadlessPlayer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ public protocol CoreHooks {
/// Fired when the state changes
var state: Hook<BaseFlowState> { get }

/// A hook to access the current flow
var onStart: Hook<FlowType> { get }

/// Initialize hooks from reference to javascript core player
init(from: JSValue)
}
Expand Down
43 changes: 43 additions & 0 deletions ios/core/Sources/Types/Core/FlowType.swift
Original file line number Diff line number Diff line change
@@ -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
}
}
6 changes: 6 additions & 0 deletions ios/core/Tests/FlowStateTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions ios/internal-test-utils/Sources/FlowData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ public struct FlowData {
{
"id": "counter-flow",
"views": [],
"data": {
"count": 0
},
"navigation": {
"BEGIN": "FLOW_1",
"FLOW_1": {
Expand Down
4 changes: 4 additions & 0 deletions ios/swiftui/Sources/SwiftUIPlayer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,9 @@ public struct SwiftUIPlayerHooks: CoreHooks {
/// Provide Transition Animation information for transition views in the same flow
public var transition: SyncBailHook<Void, PlayerViewTransition>

/// Provides access to the current flow
public var onStart: Hook<FlowType>

/// Initialize hooks from reference to javascript core player
public init(from player: JSValue) {
flowController = Hook<FlowController>(baseValue: player, name: "flowController")
Expand All @@ -296,6 +299,7 @@ public struct SwiftUIPlayerHooks: CoreHooks {
state = Hook<BaseFlowState>(baseValue: player, name: "state")
view = SyncWaterfallHook<AnyView>()
transition = SyncBailHook<Void, PlayerViewTransition>()
onStart = Hook<FlowType>(baseValue: player, name: "onStart")
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,14 @@ public class HeadlessHooks: CoreHooks {

public var state: Hook<BaseFlowState>

public var onStart: Hook<FlowType>

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<FlowType>(baseValue: value, name: "onStart")
}
}

Expand Down
3 changes: 3 additions & 0 deletions ios/test-utils-core/Sources/utilities/TestPlayer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,13 @@ public class TestHooks: CoreHooks {

public var state: Hook<BaseFlowState>

public var onStart: Hook<FlowType>

public required init(from player: JSValue) {
flowController = Hook<FlowController>(baseValue: player, name: "flowController")
viewController = Hook<ViewController>(baseValue: player, name: "viewController")
dataController = Hook<DataController>(baseValue: player, name: "dataController")
state = Hook<BaseFlowState>(baseValue: player, name: "state")
onStart = Hook<FlowType>(baseValue: player, name: "onStart")
}
}