Skip to content

Commit

Permalink
Implemented cancelBeacon and buildBeacon hooks for Android
Browse files Browse the repository at this point in the history
  • Loading branch information
mrigankmg committed Nov 12, 2024
1 parent dd14225 commit ecb7fb1
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.intuit.playerui.core.bridge.hooks

import com.intuit.hooks.HookContext
import com.intuit.hooks.AsyncSeriesWaterfallHook
import com.intuit.playerui.core.bridge.Node
import com.intuit.playerui.core.bridge.serialization.serializers.NodeWrapperSerializer
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable

@Serializable(NodeAsyncWaterfallHook2.Serializer::class)
public class NodeAsyncWaterfallHook2<T1, T2>(
override val node: Node,
private val serializer1: KSerializer<T1>,
private val serializer2: KSerializer<T2>,
) : AsyncSeriesWaterfallHook<(HookContext, T1?, T2?) -> T1?, T1?>(), AsyncNodeHook<T1?> {

init { init(serializer1, serializer2) }

override suspend fun callAsync(context: HookContext, serializedArgs: Array<Any?>): T1 {
require(serializedArgs.size == 2) { "Expected exactly two arguments, but got ${serializedArgs.size}" }
val p1 = serializedArgs[0] as? T1
val p2 = serializedArgs[1] as? T2
return call(
null,
{ f, _, _ -> f(context, p1, p2) },
{ f, _ -> f(context, p1, p2) },
) as T1
}

internal class Serializer<T1, T2>(private val serializer1: KSerializer<T1>, private val serializer2: KSerializer<T2>) : NodeWrapperSerializer<NodeAsyncWaterfallHook2<T1, T2>>({
NodeAsyncWaterfallHook2(it, serializer1, serializer2)
})
}
Original file line number Diff line number Diff line change
@@ -1,28 +1,45 @@
package com.intuit.playerui.plugins.beacon

import com.intuit.playerui.core.asset.Asset
import com.intuit.playerui.core.bridge.Invokable
import com.intuit.playerui.core.bridge.Node
import com.intuit.playerui.core.bridge.NodeWrapper
import com.intuit.playerui.core.bridge.getInvokable
import com.intuit.playerui.core.bridge.hooks.NodeSyncBailHook1
import com.intuit.playerui.core.bridge.hooks.NodeAsyncWaterfallHook2
import com.intuit.playerui.core.bridge.runtime.Runtime
import com.intuit.playerui.core.bridge.runtime.ScriptContext
import com.intuit.playerui.core.bridge.runtime.add
import com.intuit.playerui.core.bridge.serialization.serializers.GenericSerializer
import com.intuit.playerui.core.bridge.serialization.serializers.InvokableSerializer
import com.intuit.playerui.core.bridge.serialization.serializers.NodeSerializableField
import com.intuit.playerui.core.bridge.serialization.serializers.NodeWrapperSerializer
import com.intuit.playerui.core.player.Player
import com.intuit.playerui.core.player.state.PlayerFlowState
import com.intuit.playerui.core.plugins.JSPluginWrapper
import com.intuit.playerui.core.plugins.JSScriptPluginWrapper
import com.intuit.playerui.core.plugins.Pluggable
import com.intuit.playerui.core.plugins.findPlugin
import com.intuit.playerui.plugins.settimeout.SetTimeoutPlugin
import kotlinx.serialization.Contextual
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.builtins.MapSerializer
import kotlinx.serialization.builtins.nullable
import kotlinx.serialization.builtins.serializer
import kotlinx.serialization.json.Json

public typealias LoggerType = Map<LogSeverity, Invokable<Unit>>

/**
* Core beaconing plugin wrapper for the JVM. Beaconing format can be augmented with a wrapped core beaconing plugin passed in as [JSPluginWrapper]s.
*/
public class BeaconPlugin(override val plugins: List<JSPluginWrapper>) : JSScriptPluginWrapper(pluginName, sourcePath = bundledSourcePath), Pluggable {

public constructor(vararg plugins: JSPluginWrapper) : this(plugins.toList())

public val hooks: Hooks by NodeSerializableField(Hooks.serializer())

override fun apply(runtime: Runtime<*>) {
SetTimeoutPlugin().apply(runtime)

Expand Down Expand Up @@ -68,6 +85,49 @@ public class BeaconPlugin(override val plugins: List<JSPluginWrapper>) : JSScrip
)
}

@Serializable(Hooks.Serializer::class)
public class Hooks internal constructor(override val node: Node) : NodeWrapper {
/** A hook to build beacon */
public val buildBeacon: NodeAsyncWaterfallHook2<Any?, HookArgs>
by NodeSerializableField(NodeAsyncWaterfallHook2.serializer(GenericSerializer(), HookArgs.serializer()))
/** A hook to cancel beacon */
public val cancelBeacon: NodeSyncBailHook1<HookArgs, Boolean>
by NodeSerializableField(NodeSyncBailHook1.serializer(HookArgs.serializer(), Boolean.serializer()))

internal object Serializer : NodeWrapperSerializer<Hooks>(::Hooks)
}

@Serializable(HookArgs.Serializer::class)
public class HookArgs internal constructor(override val node: Node) : NodeWrapper {
/** The current player state */
public val state: PlayerFlowState? by NodeSerializableField(PlayerFlowState.serializer().nullable)

/** The beacon plugin logger */
public val logger: LoggerType by NodeSerializableField(
MapSerializer(
LogSeverity.serializer(),
InvokableSerializer(GenericSerializer()) as KSerializer<Invokable<Unit>>,
),
)

/** The action being performed */
public val action: String by NodeSerializableField(String.serializer())

/** The specific element that the beacon originated from */
public val element: String by NodeSerializableField(String.serializer())

/** The asset firing the beacon */
public val asset: Asset by NodeSerializableField(Asset.serializer())

/** The current view */
public val view: Asset? by NodeSerializableField(Asset.serializer().nullable)

/** Any additional data to attach to the event */
public val data: Any? by NodeSerializableField(GenericSerializer())

internal object Serializer : NodeWrapperSerializer<HookArgs>(::HookArgs)
}

private companion object {
private const val pluginName = "BeaconPlugin"
private const val bundledSourcePath = "plugins/beacon/core/dist/BeaconPlugin.native.js"
Expand All @@ -80,6 +140,11 @@ public class BeaconPlugin(override val plugins: List<JSPluginWrapper>) : JSScrip
)
}

@Serializable
public enum class LogSeverity {
TRACE, DEBUG, INFO, WARN, ERROR
}

/** Convenience getter to find the first [BeaconPlugin] registered to the [Player] */
public val Player.beaconPlugin: BeaconPlugin? get() = findPlugin()

Expand Down

0 comments on commit ecb7fb1

Please sign in to comment.