diff --git a/redwood-treehouse-host/src/androidMain/kotlin/app/cash/redwood/treehouse/treehouseAppFactoryAndroid.kt b/redwood-treehouse-host/src/androidMain/kotlin/app/cash/redwood/treehouse/treehouseAppFactoryAndroid.kt index 7cdd80e9f9..c2dcdf04ad 100644 --- a/redwood-treehouse-host/src/androidMain/kotlin/app/cash/redwood/treehouse/treehouseAppFactoryAndroid.kt +++ b/redwood-treehouse-host/src/androidMain/kotlin/app/cash/redwood/treehouse/treehouseAppFactoryAndroid.kt @@ -26,7 +26,7 @@ public fun TreehouseAppFactory( context: Context, httpClient: OkHttpClient, manifestVerifier: ManifestVerifier, - eventListener: EventListener = EventListener(), + eventListenerFactory: EventListener.Factory = EventListener.NONE, embeddedDir: Path? = null, embeddedFileSystem: FileSystem? = null, cacheName: String = "zipline", @@ -36,7 +36,7 @@ public fun TreehouseAppFactory( ): TreehouseApp.Factory = TreehouseApp.Factory( platform = AndroidTreehousePlatform(context), dispatchers = AndroidTreehouseDispatchers(), - eventListener = eventListener, + eventListenerFactory = eventListenerFactory, httpClient = httpClient.asZiplineHttpClient(), frameClockFactory = AndroidChoreographerFrameClock.Factory(), manifestVerifier = manifestVerifier, diff --git a/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/CodeSession.kt b/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/CodeSession.kt index 1541ab248f..1334353558 100644 --- a/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/CodeSession.kt +++ b/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/CodeSession.kt @@ -22,6 +22,8 @@ import kotlinx.serialization.json.Json /** The host state for a single code load. We get a new session each time we get new code. */ internal interface CodeSession { + val eventPublisher: EventPublisher + val appService: A val json: Json diff --git a/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/EventListener.kt b/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/EventListener.kt index d00986ec22..0b83455885 100644 --- a/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/EventListener.kt +++ b/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/EventListener.kt @@ -21,6 +21,7 @@ import app.cash.redwood.protocol.Id import app.cash.redwood.protocol.ModifierTag import app.cash.redwood.protocol.PropertyTag import app.cash.redwood.protocol.WidgetTag +import app.cash.redwood.treehouse.EventListener.Factory import app.cash.zipline.Call import app.cash.zipline.CallResult import app.cash.zipline.Zipline @@ -30,26 +31,6 @@ import kotlin.native.ObjCName @ObjCName("EventListener", exact = true) public open class EventListener { - /** - * Invoked each time a [TreehouseApp] is created. When this is triggered the app may not yet have - * any code loaded; but it will always attempt to load code. - */ - public open fun appStart( - app: TreehouseApp<*>, - ) { - } - - /** - * Invoked with [TreehouseApp.cancel] when the application is shut down. - * - * This is different from [codeUnloaded] which occurs during hot reloads; this only occurs if the - * app itself is explicitly closed. - */ - public open fun appCanceled( - app: TreehouseApp<*>, - ) { - } - /** * Invoked for each attempt at loading code. This will be followed by a [codeLoadSuccess], * [codeLoadFailed], or [codeLoadSkipped] if the code is unchanged. @@ -57,10 +38,7 @@ public open class EventListener { * @return any object. This value will be passed back to one of the above functions. The base * function always returns null. */ - public open fun codeLoadStart( - app: TreehouseApp<*>, - manifestUrl: String?, - ): Any? = null + public open fun codeLoadStart(): Any? = null /** * Invoked when code is successfully downloaded and initialized. @@ -69,8 +47,6 @@ public open class EventListener { * is null unless [codeLoadStart] is overridden to return something else. */ public open fun codeLoadSuccess( - app: TreehouseApp<*>, - manifestUrl: String?, manifest: ZiplineManifest, zipline: Zipline, startValue: Any?, @@ -84,8 +60,6 @@ public open class EventListener { * is null unless [codeLoadStart] is overridden to return something else. */ public open fun codeLoadSkipped( - app: TreehouseApp<*>, - manifestUrl: String?, startValue: Any?, ) { } @@ -97,8 +71,6 @@ public open class EventListener { * is null unless [codeLoadStart] is overridden to return something else. */ public open fun codeLoadFailed( - app: TreehouseApp<*>, - manifestUrl: String?, exception: Exception, startValue: Any?, ) { @@ -108,17 +80,13 @@ public open class EventListener { * Invoked when code is unloaded because it is no longer needed. Typically this occurs when a hot * code update is applied. */ - public open fun codeUnloaded( - app: TreehouseApp<*>, - zipline: Zipline, - ) { + public open fun codeUnloaded() { } /** * Invoked on a request to create an unknown widget [kind]. */ public open fun onUnknownWidget( - app: TreehouseApp<*>, tag: WidgetTag, ) { } @@ -127,7 +95,6 @@ public open class EventListener { * Invoked on a request to create an unknown modifier [tag]. */ public open fun onUnknownModifier( - app: TreehouseApp<*>, tag: ModifierTag, ) { } @@ -136,7 +103,6 @@ public open class EventListener { * Invoked on a request to manipulate unknown children [tag] for the specified widget [kind]. */ public open fun onUnknownChildren( - app: TreehouseApp<*>, widgetTag: WidgetTag, tag: ChildrenTag, ) { @@ -146,7 +112,6 @@ public open class EventListener { * Invoked on a request to set an unknown property [tag] for the specified widget [kind]. */ public open fun onUnknownProperty( - app: TreehouseApp<*>, widgetTag: WidgetTag, tag: PropertyTag, ) { @@ -154,7 +119,6 @@ public open class EventListener { /** Invoked on a request to process an unknown event [tag] for the specified widget [widgetTag]. */ public open fun onUnknownEvent( - app: TreehouseApp<*>, widgetTag: WidgetTag, tag: EventTag, ) { @@ -162,7 +126,6 @@ public open class EventListener { /** Invoked for an event whose node [id] is unknown. */ public open fun onUnknownEventNode( - app: TreehouseApp<*>, id: Id, tag: EventTag, ) { @@ -176,7 +139,6 @@ public open class EventListener { * function always returns null. */ public open fun downloadStart( - app: TreehouseApp<*>, url: String, ): Any? = null @@ -187,7 +149,6 @@ public open class EventListener { * is null unless [downloadStart] is overridden to return something else. */ public open fun downloadSuccess( - app: TreehouseApp<*>, url: String, startValue: Any?, ) { @@ -200,7 +161,6 @@ public open class EventListener { * is null unless [downloadStart] is overridden to return something else. */ public open fun downloadFailed( - app: TreehouseApp<*>, url: String, exception: Exception, startValue: Any?, @@ -212,8 +172,6 @@ public open class EventListener { * failures are signaled with [codeLoadFailed]. */ public open fun manifestVerified( - app: TreehouseApp<*>, - manifestUrl: String?, manifest: ZiplineManifest, verifiedKey: String, ) { @@ -226,8 +184,6 @@ public open class EventListener { * completed. The base function always returns null. */ public open fun moduleLoadStart( - app: TreehouseApp<*>, - zipline: Zipline, moduleId: String, ): Any? { return null @@ -240,8 +196,6 @@ public open class EventListener { * null unless [moduleLoadStart] is overridden to return something else. */ public open fun moduleLoadEnd( - app: TreehouseApp<*>, - zipline: Zipline, moduleId: String, startValue: Any?, ) { @@ -254,8 +208,6 @@ public open class EventListener { * completed. The base function always returns null. */ public open fun initializerStart( - app: TreehouseApp<*>, - zipline: Zipline, applicationName: String, ): Any? { return null @@ -268,8 +220,6 @@ public open class EventListener { * null unless [initializerStart] is overridden to return something else. */ public open fun initializerEnd( - app: TreehouseApp<*>, - zipline: Zipline, applicationName: String, startValue: Any?, ) { @@ -282,8 +232,6 @@ public open class EventListener { * completed. The base function always returns null. */ public open fun mainFunctionStart( - app: TreehouseApp<*>, - zipline: Zipline, applicationName: String, ): Any? { return null @@ -296,8 +244,6 @@ public open class EventListener { * null unless [mainFunctionStart] is overridden to return something else. */ public open fun mainFunctionEnd( - app: TreehouseApp<*>, - zipline: Zipline, applicationName: String, startValue: Any?, ) { @@ -308,8 +254,6 @@ public open class EventListener { * a captive portal on the network. */ public open fun manifestParseFailed( - app: TreehouseApp<*>, - url: String?, exception: Exception, ) { } @@ -318,7 +262,6 @@ public open class EventListener { * Invoked when something calls [Zipline.bind], or a service is sent via an API. */ public open fun bindService( - app: TreehouseApp<*>, name: String, service: ZiplineService, ) { @@ -328,7 +271,6 @@ public open class EventListener { * Invoked when something calls [Zipline.take], or a service is received via an API. */ public open fun takeService( - app: TreehouseApp<*>, name: String, service: ZiplineService, ) { @@ -342,7 +284,6 @@ public open class EventListener { * base function always returns null. */ public open fun callStart( - app: TreehouseApp<*>, call: Call, ): Any? = null @@ -353,7 +294,6 @@ public open class EventListener { * unless [callStart] is overridden to return something else. */ public open fun callEnd( - app: TreehouseApp<*>, call: Call, result: CallResult, startValue: Any?, @@ -366,7 +306,6 @@ public open class EventListener { * Note that this method may be invoked after [codeUnloaded]. */ public open fun serviceLeaked( - app: TreehouseApp<*>, name: String, ) { } @@ -382,8 +321,25 @@ public open class EventListener { * execute. A new [Zipline] will start when new code available, or when the app is restarted. */ public open fun uncaughtException( - app: TreehouseApp<*>, exception: Throwable, ) { } + + public fun interface Factory { + /** + * Returns an event listener that receives the events of a specific code session. Each code + * session includes a single [Zipline] instance, unless code loading fails, in which case there + * will be no [Zipline] instance. + */ + public fun create( + app: TreehouseApp<*>, + manifestUrl: String?, + ): EventListener + } + + public companion object { + public val NONE: Factory = Factory { app, manifestUrl -> + EventListener() + } + } } diff --git a/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/EventPublisher.kt b/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/EventPublisher.kt index 92f8ffd7f4..cba874409c 100644 --- a/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/EventPublisher.kt +++ b/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/EventPublisher.kt @@ -26,10 +26,6 @@ internal interface EventPublisher { val widgetProtocolMismatchHandler: ProtocolMismatchHandler - fun appStart() - - fun appCanceled() - fun onUnknownEvent(widgetTag: WidgetTag, tag: EventTag) fun onUnknownEventNode(id: Id, tag: EventTag) diff --git a/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/RealEventPublisher.kt b/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/RealEventPublisher.kt index c527e3514c..e0ffc0f4e7 100644 --- a/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/RealEventPublisher.kt +++ b/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/RealEventPublisher.kt @@ -31,14 +31,18 @@ import app.cash.zipline.ZiplineService internal class RealEventPublisher( private val listener: EventListener, - private val app: TreehouseApp<*>, + private val ziplineToPublisherHack: MutableMap, ) : EventPublisher { override val ziplineEventListener = object : ZiplineEventListener() { + override fun ziplineCreated(zipline: Zipline) { + ziplineToPublisherHack[zipline] = this@RealEventPublisher + } + override fun applicationLoadStart( applicationName: String, manifestUrl: String?, ): Any? { - return listener.codeLoadStart(app, manifestUrl) + return listener.codeLoadStart() } override fun applicationLoadSuccess( @@ -48,7 +52,7 @@ internal class RealEventPublisher( zipline: Zipline, startValue: Any?, ) { - listener.codeLoadSuccess(app, manifestUrl, manifest, zipline, startValue) + listener.codeLoadSuccess(manifest, zipline, startValue) } override fun applicationLoadSkipped( @@ -56,7 +60,7 @@ internal class RealEventPublisher( manifestUrl: String, startValue: Any?, ) { - listener.codeLoadSkipped(app, manifestUrl, startValue) + listener.codeLoadSkipped(startValue) } override fun applicationLoadFailed( @@ -65,7 +69,7 @@ internal class RealEventPublisher( exception: Exception, startValue: Any?, ) { - listener.codeLoadFailed(app, manifestUrl, exception, startValue) + listener.codeLoadFailed(exception, startValue) } override fun bindService( @@ -73,26 +77,26 @@ internal class RealEventPublisher( name: String, service: ZiplineService, ) { - listener.bindService(app, name, service) + listener.bindService(name, service) } override fun callStart( zipline: Zipline, call: Call, ): Any? { - return listener.callStart(app, call) + return listener.callStart(call) } override fun callEnd(zipline: Zipline, call: Call, result: CallResult, startValue: Any?) { - listener.callEnd(app, call, result, startValue) + listener.callEnd(call, result, startValue) } override fun downloadStart(applicationName: String, url: String): Any? { - return listener.downloadStart(app, url) + return listener.downloadStart(url) } override fun downloadEnd(applicationName: String, url: String, startValue: Any?) { - listener.downloadSuccess(app, url, startValue) + listener.downloadSuccess(url, startValue) } override fun downloadFailed( @@ -101,7 +105,7 @@ internal class RealEventPublisher( exception: Exception, startValue: Any?, ) { - listener.downloadFailed(app, url, exception, startValue) + listener.downloadFailed(url, exception, startValue) } override fun manifestVerified( @@ -110,85 +114,77 @@ internal class RealEventPublisher( manifest: ZiplineManifest, verifiedKey: String, ) { - listener.manifestVerified(app, manifestUrl, manifest, verifiedKey) + listener.manifestVerified(manifest, verifiedKey) } override fun moduleLoadStart(zipline: Zipline, moduleId: String): Any? { - return listener.moduleLoadStart(app, zipline, moduleId) + return listener.moduleLoadStart(moduleId) } override fun moduleLoadEnd(zipline: Zipline, moduleId: String, startValue: Any?) { - listener.moduleLoadEnd(app, zipline, moduleId, startValue) + listener.moduleLoadEnd(moduleId, startValue) } override fun initializerStart(zipline: Zipline, applicationName: String): Any? { - return listener.initializerStart(app, zipline, applicationName) + return listener.initializerStart(applicationName) } override fun initializerEnd(zipline: Zipline, applicationName: String, startValue: Any?) { - listener.initializerEnd(app, zipline, applicationName, startValue) + listener.initializerEnd(applicationName, startValue) } override fun mainFunctionStart(zipline: Zipline, applicationName: String): Any? { - return listener.mainFunctionStart(app, zipline, applicationName) + return listener.mainFunctionStart(applicationName) } override fun mainFunctionEnd(zipline: Zipline, applicationName: String, startValue: Any?) { - listener.mainFunctionEnd(app, zipline, applicationName, startValue) + listener.mainFunctionEnd(applicationName, startValue) } override fun manifestParseFailed(applicationName: String, url: String?, exception: Exception) { - listener.manifestParseFailed(app, url, exception) + listener.manifestParseFailed(exception) } override fun takeService(zipline: Zipline, name: String, service: ZiplineService) { - listener.takeService(app, name, service) + listener.takeService(name, service) } override fun serviceLeaked(zipline: Zipline, name: String) { - listener.serviceLeaked(app, name) + listener.serviceLeaked(name) } override fun ziplineClosed(zipline: Zipline) { - listener.codeUnloaded(app, zipline) + listener.codeUnloaded() } } override val widgetProtocolMismatchHandler = object : ProtocolMismatchHandler { override fun onUnknownWidget(tag: WidgetTag) { - listener.onUnknownWidget(app, tag) + listener.onUnknownWidget(tag) } override fun onUnknownModifier(tag: ModifierTag) { - listener.onUnknownModifier(app, tag) + listener.onUnknownModifier(tag) } override fun onUnknownChildren(widgetTag: WidgetTag, tag: ChildrenTag) { - listener.onUnknownChildren(app, widgetTag, tag) + listener.onUnknownChildren(widgetTag, tag) } override fun onUnknownProperty(widgetTag: WidgetTag, tag: PropertyTag) { - listener.onUnknownProperty(app, widgetTag, tag) + listener.onUnknownProperty(widgetTag, tag) } } - override fun appStart() { - listener.appStart(app) - } - - override fun appCanceled() { - listener.appCanceled(app) - } - override fun onUnknownEvent(widgetTag: WidgetTag, tag: EventTag) { - listener.onUnknownEvent(app, widgetTag, tag) + listener.onUnknownEvent(widgetTag, tag) } override fun onUnknownEventNode(id: Id, tag: EventTag) { - listener.onUnknownEventNode(app, id, tag) + listener.onUnknownEventNode(id, tag) } override fun onUncaughtException(exception: Throwable) { - listener.uncaughtException(app, exception) + listener.uncaughtException(exception) } } diff --git a/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/TreehouseApp.kt b/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/TreehouseApp.kt index e4961ab4f6..78c111d96b 100644 --- a/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/TreehouseApp.kt +++ b/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/TreehouseApp.kt @@ -15,6 +15,7 @@ */ package app.cash.redwood.treehouse +import app.cash.zipline.EventListener as ZiplineEventListener import app.cash.zipline.Zipline import app.cash.zipline.loader.LoadResult import app.cash.zipline.loader.ManifestVerifier @@ -46,9 +47,10 @@ public class TreehouseApp private constructor( ) { private val codeHost = ZiplineCodeHost() - public val dispatchers: TreehouseDispatchers = factory.dispatchers + // TODO: remove after https://github.com/cashapp/zipline/pull/1159 + private val ziplineToPublisherHack = mutableMapOf() - private val eventPublisher = RealEventPublisher(factory.eventListener, this) + public val dispatchers: TreehouseDispatchers = factory.dispatchers private var started = false @@ -80,7 +82,6 @@ public class TreehouseApp private constructor( codeHost = codeHost, dispatchers = dispatchers, appScope = appScope, - eventPublisher = eventPublisher, codeListener = codeListener, source = source, ) @@ -96,8 +97,6 @@ public class TreehouseApp private constructor( if (started) return started = true - eventPublisher.appStart() - appScope.launch(dispatchers.zipline) { val ziplineFileFlow = ziplineFlow() ziplineFileFlow.collect { @@ -124,11 +123,17 @@ public class TreehouseApp private constructor( dispatcher = dispatchers.zipline, manifestVerifier = factory.manifestVerifier, httpClient = factory.httpClient, - eventListener = eventPublisher.ziplineEventListener, ) loader.concurrentDownloads = factory.concurrentDownloads + // Adapt [EventListener.Factory] to a [ZiplineEventListener.Factory] + val ziplineEventListenerFactory = ZiplineEventListener.Factory { _, manifestUrl -> + val eventListener = factory.eventListenerFactory.create(this@TreehouseApp, manifestUrl) + RealEventPublisher(eventListener, ziplineToPublisherHack).ziplineEventListener + } + loader = loader.withEventListenerFactory(ziplineEventListenerFactory) + if (!spec.loadCodeFromNetworkOnly) { loader = loader.withCache( cache = factory.cache, @@ -174,7 +179,6 @@ public class TreehouseApp private constructor( session.cancel() codeHost.session = null } - eventPublisher.appCanceled() } private inner class ZiplineCodeHost : CodeHost, CodeSession.Listener { @@ -208,10 +212,13 @@ public class TreehouseApp private constructor( } fun onCodeChanged(zipline: Zipline, appService: A) { + // TODO: replace with a downcast on Zipline.eventListener once that's public. + val eventPublisher = ziplineToPublisherHack.remove(zipline)!! + val next = ZiplineCodeSession( dispatchers = dispatchers, - eventPublisher = eventPublisher, appScope = appScope, + eventPublisher = eventPublisher, appService = appService, zipline = zipline, ) @@ -249,7 +256,7 @@ public class TreehouseApp private constructor( public class Factory internal constructor( private val platform: TreehousePlatform, public val dispatchers: TreehouseDispatchers, - internal val eventListener: EventListener, + internal val eventListenerFactory: EventListener.Factory, internal val httpClient: ZiplineHttpClient, internal val frameClockFactory: FrameClock.Factory, internal val manifestVerifier: ManifestVerifier, diff --git a/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/TreehouseAppContent.kt b/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/TreehouseAppContent.kt index a7646c99eb..399fcacf02 100644 --- a/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/TreehouseAppContent.kt +++ b/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/TreehouseAppContent.kt @@ -71,7 +71,6 @@ internal class TreehouseAppContent( private val codeHost: CodeHost, private val dispatchers: TreehouseDispatchers, private val appScope: CoroutineScope, - private val eventPublisher: EventPublisher, private val codeListener: CodeListener, private val source: TreehouseContentSource, ) : Content, CodeHost.Listener, CodeSession.Listener { @@ -272,7 +271,7 @@ internal class TreehouseAppContent( stateStore = codeHost.stateStore, dispatchers = dispatchers, appScope = appScope, - eventPublisher = eventPublisher, + eventPublisher = codeSession.eventPublisher, contentSource = source, codeListener = codeListener, stateFlow = stateFlow, diff --git a/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/ZiplineCodeSession.kt b/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/ZiplineCodeSession.kt index b9b92d658b..62637efb73 100644 --- a/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/ZiplineCodeSession.kt +++ b/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/ZiplineCodeSession.kt @@ -29,8 +29,8 @@ import kotlinx.serialization.json.Json internal class ZiplineCodeSession( private val dispatchers: TreehouseDispatchers, - private val eventPublisher: EventPublisher, private val appScope: CoroutineScope, + override val eventPublisher: EventPublisher, override val appService: A, val zipline: Zipline, ) : CodeSession, AppLifecycle.Host { diff --git a/redwood-treehouse-host/src/commonTest/kotlin/app/cash/redwood/treehouse/FakeCodeHost.kt b/redwood-treehouse-host/src/commonTest/kotlin/app/cash/redwood/treehouse/FakeCodeHost.kt index 3fd8dc5f01..d769c4b6c1 100644 --- a/redwood-treehouse-host/src/commonTest/kotlin/app/cash/redwood/treehouse/FakeCodeHost.kt +++ b/redwood-treehouse-host/src/commonTest/kotlin/app/cash/redwood/treehouse/FakeCodeHost.kt @@ -21,6 +21,7 @@ import kotlinx.coroutines.CoroutineScope internal class FakeCodeHost( private val eventLog: EventLog, + private val eventPublisher: EventPublisher, ) : CodeHost { override val stateStore = MemoryStateStore() @@ -59,7 +60,7 @@ internal class FakeCodeHost( private val listeners = mutableListOf>() fun startCodeSession(name: String): CodeSession { - val result = FakeCodeSession(eventLog, name) + val result = FakeCodeSession(eventLog, name, eventPublisher) session = result return result } diff --git a/redwood-treehouse-host/src/commonTest/kotlin/app/cash/redwood/treehouse/FakeCodeSession.kt b/redwood-treehouse-host/src/commonTest/kotlin/app/cash/redwood/treehouse/FakeCodeSession.kt index 0e10558927..4658c43d6e 100644 --- a/redwood-treehouse-host/src/commonTest/kotlin/app/cash/redwood/treehouse/FakeCodeSession.kt +++ b/redwood-treehouse-host/src/commonTest/kotlin/app/cash/redwood/treehouse/FakeCodeSession.kt @@ -23,6 +23,7 @@ import kotlinx.serialization.json.Json internal class FakeCodeSession( private val eventLog: EventLog, private val name: String, + override val eventPublisher: EventPublisher, ) : CodeSession { private val listeners = mutableListOf>() diff --git a/redwood-treehouse-host/src/commonTest/kotlin/app/cash/redwood/treehouse/FakeEventPublisher.kt b/redwood-treehouse-host/src/commonTest/kotlin/app/cash/redwood/treehouse/FakeEventPublisher.kt index 9c30fcaa2d..a32296403a 100644 --- a/redwood-treehouse-host/src/commonTest/kotlin/app/cash/redwood/treehouse/FakeEventPublisher.kt +++ b/redwood-treehouse-host/src/commonTest/kotlin/app/cash/redwood/treehouse/FakeEventPublisher.kt @@ -26,12 +26,6 @@ class FakeEventPublisher : EventPublisher { override val widgetProtocolMismatchHandler = ProtocolMismatchHandler.Throwing - override fun appStart() { - } - - override fun appCanceled() { - } - override fun onUnknownEvent(widgetTag: WidgetTag, tag: EventTag) { } diff --git a/redwood-treehouse-host/src/commonTest/kotlin/app/cash/redwood/treehouse/TreehouseAppContentTest.kt b/redwood-treehouse-host/src/commonTest/kotlin/app/cash/redwood/treehouse/TreehouseAppContentTest.kt index 376805eead..bc7841bee1 100644 --- a/redwood-treehouse-host/src/commonTest/kotlin/app/cash/redwood/treehouse/TreehouseAppContentTest.kt +++ b/redwood-treehouse-host/src/commonTest/kotlin/app/cash/redwood/treehouse/TreehouseAppContentTest.kt @@ -33,9 +33,9 @@ class TreehouseAppContentTest { private val eventLog = EventLog() private val dispatcher = UnconfinedTestDispatcher() - private val codeHost = FakeCodeHost(eventLog) - private val dispatchers = FakeDispatchers(dispatcher, dispatcher) private val eventPublisher = FakeEventPublisher() + private val codeHost = FakeCodeHost(eventLog, eventPublisher) + private val dispatchers = FakeDispatchers(dispatcher, dispatcher) private val codeListener = FakeCodeListener(eventLog) private val uiConfiguration = UiConfiguration() @@ -388,7 +388,6 @@ class TreehouseAppContentTest { codeHost = codeHost, dispatchers = dispatchers, appScope = CoroutineScope(coroutineContext), - eventPublisher = eventPublisher, codeListener = codeListener, source = { app -> app.newUi() }, ) diff --git a/redwood-treehouse-host/src/iosMain/kotlin/app/cash/redwood/treehouse/treehouseAppFactoryIos.kt b/redwood-treehouse-host/src/iosMain/kotlin/app/cash/redwood/treehouse/treehouseAppFactoryIos.kt index 5563e49f56..193576b0d6 100644 --- a/redwood-treehouse-host/src/iosMain/kotlin/app/cash/redwood/treehouse/treehouseAppFactoryIos.kt +++ b/redwood-treehouse-host/src/iosMain/kotlin/app/cash/redwood/treehouse/treehouseAppFactoryIos.kt @@ -23,7 +23,7 @@ import okio.Path public fun TreehouseAppFactory( httpClient: ZiplineHttpClient, manifestVerifier: ManifestVerifier, - eventListener: EventListener = EventListener(), + eventListenerFactory: EventListener.Factory = EventListener.NONE, embeddedDir: Path? = null, embeddedFileSystem: FileSystem? = null, cacheName: String = "zipline", @@ -33,7 +33,7 @@ public fun TreehouseAppFactory( ): TreehouseApp.Factory = TreehouseApp.Factory( platform = IosTreehousePlatform(), dispatchers = IosTreehouseDispatchers(), - eventListener = eventListener, + eventListenerFactory = eventListenerFactory, httpClient = httpClient, frameClockFactory = IosDisplayLinkClock, manifestVerifier = manifestVerifier, diff --git a/samples/emoji-search/android-composeui/src/main/kotlin/com/example/redwood/emojisearch/android/composeui/EmojiSearchActivity.kt b/samples/emoji-search/android-composeui/src/main/kotlin/com/example/redwood/emojisearch/android/composeui/EmojiSearchActivity.kt index b8f1cebc53..ebcd73a384 100644 --- a/samples/emoji-search/android-composeui/src/main/kotlin/com/example/redwood/emojisearch/android/composeui/EmojiSearchActivity.kt +++ b/samples/emoji-search/android-composeui/src/main/kotlin/com/example/redwood/emojisearch/android/composeui/EmojiSearchActivity.kt @@ -99,7 +99,7 @@ class EmojiSearchActivity : ComponentActivity() { private var success = true private var snackbarJob: Job? = null - override fun codeLoadFailed(app: TreehouseApp<*>, manifestUrl: String?, exception: Exception, startValue: Any?) { + override fun codeLoadFailed(exception: Exception, startValue: Any?) { Log.w("Treehouse", "codeLoadFailed", exception) if (success) { // Only show the Snackbar on the first transition from success. @@ -114,7 +114,7 @@ class EmojiSearchActivity : ComponentActivity() { } } - override fun codeLoadSuccess(app: TreehouseApp<*>, manifestUrl: String?, manifest: ZiplineManifest, zipline: Zipline, startValue: Any?) { + override fun codeLoadSuccess(manifest: ZiplineManifest, zipline: Zipline, startValue: Any?) { Log.i("Treehouse", "codeLoadSuccess") success = true snackbarJob?.cancel() @@ -129,7 +129,7 @@ class EmojiSearchActivity : ComponentActivity() { context = applicationContext, httpClient = httpClient, manifestVerifier = ManifestVerifier.Companion.NO_SIGNATURE_CHECKS, - eventListener = appEventListener, + eventListenerFactory = { app, manifestUrl -> appEventListener }, embeddedDir = "/".toPath(), embeddedFileSystem = applicationContext.assets.asFileSystem(), ) diff --git a/samples/emoji-search/android-views/src/main/kotlin/com/example/redwood/emojisearch/android/views/EmojiSearchActivity.kt b/samples/emoji-search/android-views/src/main/kotlin/com/example/redwood/emojisearch/android/views/EmojiSearchActivity.kt index 2bae8565e8..ffa7338dfd 100644 --- a/samples/emoji-search/android-views/src/main/kotlin/com/example/redwood/emojisearch/android/views/EmojiSearchActivity.kt +++ b/samples/emoji-search/android-views/src/main/kotlin/com/example/redwood/emojisearch/android/views/EmojiSearchActivity.kt @@ -100,7 +100,7 @@ class EmojiSearchActivity : ComponentActivity() { private var success = true private var snackbar: Snackbar? = null - override fun codeLoadFailed(app: TreehouseApp<*>, manifestUrl: String?, exception: Exception, startValue: Any?) { + override fun codeLoadFailed(exception: Exception, startValue: Any?) { Log.w("Treehouse", "codeLoadFailed", exception) if (success) { // Only show the Snackbar on the first transition from success. @@ -112,7 +112,7 @@ class EmojiSearchActivity : ComponentActivity() { } } - override fun codeLoadSuccess(app: TreehouseApp<*>, manifestUrl: String?, manifest: ZiplineManifest, zipline: Zipline, startValue: Any?) { + override fun codeLoadSuccess(manifest: ZiplineManifest, zipline: Zipline, startValue: Any?) { Log.i("Treehouse", "codeLoadSuccess") success = true maybeDismissSnackbar() @@ -134,7 +134,7 @@ class EmojiSearchActivity : ComponentActivity() { context = applicationContext, httpClient = httpClient, manifestVerifier = ManifestVerifier.NO_SIGNATURE_CHECKS, - eventListener = appEventListener, + eventListenerFactory = { app, manifestUrl -> appEventListener }, embeddedDir = "/".toPath(), embeddedFileSystem = applicationContext.assets.asFileSystem(), stateStore = FileStateStore( diff --git a/samples/emoji-search/ios-shared/src/commonMain/kotlin/com/example/redwood/emojisearch/ios/EmojiSearchLauncher.kt b/samples/emoji-search/ios-shared/src/commonMain/kotlin/com/example/redwood/emojisearch/ios/EmojiSearchLauncher.kt index 93eebdcd2a..fcf03dde65 100644 --- a/samples/emoji-search/ios-shared/src/commonMain/kotlin/com/example/redwood/emojisearch/ios/EmojiSearchLauncher.kt +++ b/samples/emoji-search/ios-shared/src/commonMain/kotlin/com/example/redwood/emojisearch/ios/EmojiSearchLauncher.kt @@ -44,24 +44,26 @@ class EmojiSearchLauncher( fun createTreehouseApp(listener: EmojiSearchEventListener): TreehouseApp { val ziplineHttpClient = nsurlSession.asZiplineHttpClient() - val treehouseAppFactory = TreehouseAppFactory( - httpClient = ziplineHttpClient, - manifestVerifier = ManifestVerifier.Companion.NO_SIGNATURE_CHECKS, - eventListener = object : EventListener() { - override fun codeLoadFailed(app: TreehouseApp<*>, manifestUrl: String?, exception: Exception, startValue: Any?) { - NSLog("Treehouse: codeLoadFailed: $exception") - NSOperationQueue.mainQueue.addOperationWithBlock { - listener.codeLoadFailed() - } + val eventListener = object : EventListener() { + override fun codeLoadFailed(exception: Exception, startValue: Any?) { + NSLog("Treehouse: codeLoadFailed: $exception") + NSOperationQueue.mainQueue.addOperationWithBlock { + listener.codeLoadFailed() } + } - override fun codeLoadSuccess(app: TreehouseApp<*>, manifestUrl: String?, manifest: ZiplineManifest, zipline: Zipline, startValue: Any?) { - NSLog("Treehouse: codeLoadSuccess") - NSOperationQueue.mainQueue.addOperationWithBlock { - listener.codeLoadSuccess() - } + override fun codeLoadSuccess(manifest: ZiplineManifest, zipline: Zipline, startValue: Any?) { + NSLog("Treehouse: codeLoadSuccess") + NSOperationQueue.mainQueue.addOperationWithBlock { + listener.codeLoadSuccess() } - }, + } + } + + val treehouseAppFactory = TreehouseAppFactory( + httpClient = ziplineHttpClient, + manifestVerifier = ManifestVerifier.Companion.NO_SIGNATURE_CHECKS, + eventListenerFactory = { app, manifestUrl -> eventListener }, ) val manifestUrlFlow = flowOf(manifestUrl) diff --git a/test-app/ios-shared/src/commonMain/kotlin/com/example/redwood/testing/ios/TestAppLauncher.kt b/test-app/ios-shared/src/commonMain/kotlin/com/example/redwood/testing/ios/TestAppLauncher.kt index 56e14cb0ba..858b9d3687 100644 --- a/test-app/ios-shared/src/commonMain/kotlin/com/example/redwood/testing/ios/TestAppLauncher.kt +++ b/test-app/ios-shared/src/commonMain/kotlin/com/example/redwood/testing/ios/TestAppLauncher.kt @@ -43,18 +43,20 @@ class TestAppLauncher( fun createTreehouseApp(): TreehouseApp { val ziplineHttpClient = nsurlSession.asZiplineHttpClient() + val eventListener = object : EventListener() { + override fun codeLoadFailed(exception: Exception, startValue: Any?) { + NSLog("Treehouse: codeLoadFailed: $exception") + } + + override fun codeLoadSuccess(manifest: ZiplineManifest, zipline: Zipline, startValue: Any?) { + NSLog("Treehouse: codeLoadSuccess") + } + } + val treehouseAppFactory = TreehouseAppFactory( httpClient = ziplineHttpClient, manifestVerifier = NO_SIGNATURE_CHECKS, - eventListener = object : EventListener() { - override fun codeLoadFailed(app: TreehouseApp<*>, manifestUrl: String?, exception: Exception, startValue: Any?) { - NSLog("Treehouse: codeLoadFailed: $exception") - } - - override fun codeLoadSuccess(app: TreehouseApp<*>, manifestUrl: String?, manifest: ZiplineManifest, zipline: Zipline, startValue: Any?) { - NSLog("Treehouse: codeLoadSuccess") - } - }, + eventListenerFactory = { app, manifestUrl -> eventListener }, ) val manifestUrlFlow = flowOf(manifestUrl)