Skip to content

Commit

Permalink
Split Treehouse lifecycle out of RedwoodView
Browse files Browse the repository at this point in the history
  • Loading branch information
squarejesse committed Oct 30, 2024
1 parent 591b963 commit 1c91bee
Show file tree
Hide file tree
Showing 37 changed files with 665 additions and 459 deletions.
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[Unreleased]: https://github.com/cashapp/redwood/compare/0.15.0...HEAD

New:
- Nothing yet!
- Redwood publishes what's happening in bound content through the new `Content.State` type.

Changed:
- Drop support for non-incremental layouts in `Row` and `Column`.
Expand All @@ -17,7 +17,7 @@ Fixed:
- Fix a layout bug where children of `Box` containers were not measured properly.

Breaking:
- Replace `CodeListener` with new functions in `RedwoodView`. This puts the loading/error/ready state with the UI that displays that state.
- Replace `CodeListener` with a new `DynamicContentWidgetFactory` API. Now loading and crashed views work like all other child widgets.


## [0.15.0] - 2024-09-30
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ private class RootProtocolNode<W : Any>(
}

override fun detach() {
children.detach()
// Do nothing because 'children' is owned by the host's TreehouseView.
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
public class app/cash/redwood/treehouse/composeui/DynamicContent {
public static final field $stable I
public final class app/cash/redwood/treehouse/composeui/ComposableSingletons$EmptyDynamicContentWidgetFactoryKt {
public static final field INSTANCE Lapp/cash/redwood/treehouse/composeui/ComposableSingletons$EmptyDynamicContentWidgetFactoryKt;
public static field lambda-1 Lkotlin/jvm/functions/Function2;
public static field lambda-2 Lkotlin/jvm/functions/Function2;
public fun <init> ()V
public fun Render (Lapp/cash/redwood/widget/compose/ComposeWidgetChildren;Landroidx/compose/runtime/Composer;I)V
public fun contentState (Lkotlinx/coroutines/CoroutineScope;IZLjava/lang/Throwable;)V
public final fun getAttached ()Z
public final fun getLoadCount ()I
public final fun getRestart ()Lkotlin/jvm/functions/Function0;
public final fun getUncaughtException ()Ljava/lang/Throwable;
public final fun restart (Lkotlin/jvm/functions/Function0;)V
public final fun getLambda-1$redwood_treehouse_host_composeui_release ()Lkotlin/jvm/functions/Function2;
public final fun getLambda-2$redwood_treehouse_host_composeui_release ()Lkotlin/jvm/functions/Function2;
}

public final class app/cash/redwood/treehouse/composeui/TreehouseContentKt {
public static final fun TreehouseContent (Lapp/cash/redwood/treehouse/TreehouseApp;Lapp/cash/redwood/treehouse/TreehouseView$WidgetSystem;Lapp/cash/redwood/treehouse/TreehouseContentSource;Landroidx/compose/ui/Modifier;Lapp/cash/redwood/treehouse/composeui/DynamicContent;Landroidx/compose/runtime/Composer;II)V
public static final fun TreehouseContent (Lapp/cash/redwood/treehouse/TreehouseApp;Lapp/cash/redwood/treehouse/TreehouseView$WidgetSystem;Lapp/cash/redwood/treehouse/TreehouseContentSource;Landroidx/compose/ui/Modifier;Lapp/cash/redwood/treehouse/DynamicContentWidgetFactory;Landroidx/compose/runtime/Composer;II)V
}

Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
public class app/cash/redwood/treehouse/composeui/DynamicContent {
public static final field $stable I
public final class app/cash/redwood/treehouse/composeui/ComposableSingletons$EmptyDynamicContentWidgetFactoryKt {
public static final field INSTANCE Lapp/cash/redwood/treehouse/composeui/ComposableSingletons$EmptyDynamicContentWidgetFactoryKt;
public static field lambda-1 Lkotlin/jvm/functions/Function2;
public static field lambda-2 Lkotlin/jvm/functions/Function2;
public fun <init> ()V
public fun Render (Lapp/cash/redwood/widget/compose/ComposeWidgetChildren;Landroidx/compose/runtime/Composer;I)V
public fun contentState (Lkotlinx/coroutines/CoroutineScope;IZLjava/lang/Throwable;)V
public final fun getAttached ()Z
public final fun getLoadCount ()I
public final fun getRestart ()Lkotlin/jvm/functions/Function0;
public final fun getUncaughtException ()Ljava/lang/Throwable;
public final fun restart (Lkotlin/jvm/functions/Function0;)V
public final fun getLambda-1$redwood_treehouse_host_composeui ()Lkotlin/jvm/functions/Function2;
public final fun getLambda-2$redwood_treehouse_host_composeui ()Lkotlin/jvm/functions/Function2;
}

public final class app/cash/redwood/treehouse/composeui/TreehouseContentKt {
public static final fun TreehouseContent (Lapp/cash/redwood/treehouse/TreehouseApp;Lapp/cash/redwood/treehouse/TreehouseView$WidgetSystem;Lapp/cash/redwood/treehouse/TreehouseContentSource;Landroidx/compose/ui/Modifier;Lapp/cash/redwood/treehouse/composeui/DynamicContent;Landroidx/compose/runtime/Composer;II)V
public static final fun TreehouseContent (Lapp/cash/redwood/treehouse/TreehouseApp;Lapp/cash/redwood/treehouse/TreehouseView$WidgetSystem;Lapp/cash/redwood/treehouse/TreehouseContentSource;Landroidx/compose/ui/Modifier;Lapp/cash/redwood/treehouse/DynamicContentWidgetFactory;Landroidx/compose/runtime/Composer;II)V
}

Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,11 @@
// - Show declarations: true

// Library unique name: <app.cash.redwood:redwood-treehouse-host-composeui>
open class app.cash.redwood.treehouse.composeui/DynamicContent { // app.cash.redwood.treehouse.composeui/DynamicContent|null[0]
constructor <init>() // app.cash.redwood.treehouse.composeui/DynamicContent.<init>|<init>(){}[0]
final val app.cash.redwood.treehouse.composeui/app_cash_redwood_treehouse_composeui_EmptyDynamicContentWidgetFactory$stableprop // app.cash.redwood.treehouse.composeui/app_cash_redwood_treehouse_composeui_EmptyDynamicContentWidgetFactory$stableprop|#static{}app_cash_redwood_treehouse_composeui_EmptyDynamicContentWidgetFactory$stableprop[0]
final val app.cash.redwood.treehouse.composeui/app_cash_redwood_treehouse_composeui_EmptyDynamicContentWidgetFactory_EmptyCrashed$stableprop // app.cash.redwood.treehouse.composeui/app_cash_redwood_treehouse_composeui_EmptyDynamicContentWidgetFactory_EmptyCrashed$stableprop|#static{}app_cash_redwood_treehouse_composeui_EmptyDynamicContentWidgetFactory_EmptyCrashed$stableprop[0]
final val app.cash.redwood.treehouse.composeui/app_cash_redwood_treehouse_composeui_EmptyDynamicContentWidgetFactory_EmptyLoading$stableprop // app.cash.redwood.treehouse.composeui/app_cash_redwood_treehouse_composeui_EmptyDynamicContentWidgetFactory_EmptyLoading$stableprop|#static{}app_cash_redwood_treehouse_composeui_EmptyDynamicContentWidgetFactory_EmptyLoading$stableprop[0]

final var attached // app.cash.redwood.treehouse.composeui/DynamicContent.attached|{}attached[0]
final fun <get-attached>(): kotlin/Boolean // app.cash.redwood.treehouse.composeui/DynamicContent.attached.<get-attached>|<get-attached>(){}[0]
final var loadCount // app.cash.redwood.treehouse.composeui/DynamicContent.loadCount|{}loadCount[0]
final fun <get-loadCount>(): kotlin/Int // app.cash.redwood.treehouse.composeui/DynamicContent.loadCount.<get-loadCount>|<get-loadCount>(){}[0]
final var restart // app.cash.redwood.treehouse.composeui/DynamicContent.restart|{}restart[0]
final fun <get-restart>(): kotlin/Function0<kotlin/Unit>? // app.cash.redwood.treehouse.composeui/DynamicContent.restart.<get-restart>|<get-restart>(){}[0]
final var uncaughtException // app.cash.redwood.treehouse.composeui/DynamicContent.uncaughtException|{}uncaughtException[0]
final fun <get-uncaughtException>(): kotlin/Throwable? // app.cash.redwood.treehouse.composeui/DynamicContent.uncaughtException.<get-uncaughtException>|<get-uncaughtException>(){}[0]

final fun restart(kotlin/Function0<kotlin/Unit>?) // app.cash.redwood.treehouse.composeui/DynamicContent.restart|restart(kotlin.Function0<kotlin.Unit>?){}[0]
open fun Render(app.cash.redwood.widget.compose/ComposeWidgetChildren, androidx.compose.runtime/Composer?, kotlin/Int) // app.cash.redwood.treehouse.composeui/DynamicContent.Render|Render(app.cash.redwood.widget.compose.ComposeWidgetChildren;androidx.compose.runtime.Composer?;kotlin.Int){}[0]
open fun contentState(kotlinx.coroutines/CoroutineScope, kotlin/Int, kotlin/Boolean, kotlin/Throwable?) // app.cash.redwood.treehouse.composeui/DynamicContent.contentState|contentState(kotlinx.coroutines.CoroutineScope;kotlin.Int;kotlin.Boolean;kotlin.Throwable?){}[0]
}

final val app.cash.redwood.treehouse.composeui/app_cash_redwood_treehouse_composeui_DynamicContent$stableprop // app.cash.redwood.treehouse.composeui/app_cash_redwood_treehouse_composeui_DynamicContent$stableprop|#static{}app_cash_redwood_treehouse_composeui_DynamicContent$stableprop[0]

final fun <#A: app.cash.redwood.treehouse/AppService> app.cash.redwood.treehouse.composeui/TreehouseContent(app.cash.redwood.treehouse/TreehouseApp<#A>, app.cash.redwood.treehouse/TreehouseView.WidgetSystem<kotlin/Function2<androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>>, app.cash.redwood.treehouse/TreehouseContentSource<#A>, androidx.compose.ui/Modifier?, app.cash.redwood.treehouse.composeui/DynamicContent?, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // app.cash.redwood.treehouse.composeui/TreehouseContent|TreehouseContent(app.cash.redwood.treehouse.TreehouseApp<0:0>;app.cash.redwood.treehouse.TreehouseView.WidgetSystem<kotlin.Function2<androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>>;app.cash.redwood.treehouse.TreehouseContentSource<0:0>;androidx.compose.ui.Modifier?;app.cash.redwood.treehouse.composeui.DynamicContent?;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){0§<app.cash.redwood.treehouse.AppService>}[0]
final fun app.cash.redwood.treehouse.composeui/app_cash_redwood_treehouse_composeui_DynamicContent$stableprop_getter(): kotlin/Int // app.cash.redwood.treehouse.composeui/app_cash_redwood_treehouse_composeui_DynamicContent$stableprop_getter|app_cash_redwood_treehouse_composeui_DynamicContent$stableprop_getter(){}[0]
final fun <#A: app.cash.redwood.treehouse/AppService> app.cash.redwood.treehouse.composeui/TreehouseContent(app.cash.redwood.treehouse/TreehouseApp<#A>, app.cash.redwood.treehouse/TreehouseView.WidgetSystem<kotlin/Function2<androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>>, app.cash.redwood.treehouse/TreehouseContentSource<#A>, androidx.compose.ui/Modifier?, app.cash.redwood.treehouse/DynamicContentWidgetFactory<kotlin/Function2<androidx.compose.runtime/Composer, kotlin/Int, kotlin/Unit>>?, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // app.cash.redwood.treehouse.composeui/TreehouseContent|TreehouseContent(app.cash.redwood.treehouse.TreehouseApp<0:0>;app.cash.redwood.treehouse.TreehouseView.WidgetSystem<kotlin.Function2<androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>>;app.cash.redwood.treehouse.TreehouseContentSource<0:0>;androidx.compose.ui.Modifier?;app.cash.redwood.treehouse.DynamicContentWidgetFactory<kotlin.Function2<androidx.compose.runtime.Composer,kotlin.Int,kotlin.Unit>>?;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){0§<app.cash.redwood.treehouse.AppService>}[0]
final fun app.cash.redwood.treehouse.composeui/app_cash_redwood_treehouse_composeui_EmptyDynamicContentWidgetFactory$stableprop_getter(): kotlin/Int // app.cash.redwood.treehouse.composeui/app_cash_redwood_treehouse_composeui_EmptyDynamicContentWidgetFactory$stableprop_getter|app_cash_redwood_treehouse_composeui_EmptyDynamicContentWidgetFactory$stableprop_getter(){}[0]
final fun app.cash.redwood.treehouse.composeui/app_cash_redwood_treehouse_composeui_EmptyDynamicContentWidgetFactory_EmptyCrashed$stableprop_getter(): kotlin/Int // app.cash.redwood.treehouse.composeui/app_cash_redwood_treehouse_composeui_EmptyDynamicContentWidgetFactory_EmptyCrashed$stableprop_getter|app_cash_redwood_treehouse_composeui_EmptyDynamicContentWidgetFactory_EmptyCrashed$stableprop_getter(){}[0]
final fun app.cash.redwood.treehouse.composeui/app_cash_redwood_treehouse_composeui_EmptyDynamicContentWidgetFactory_EmptyLoading$stableprop_getter(): kotlin/Int // app.cash.redwood.treehouse.composeui/app_cash_redwood_treehouse_composeui_EmptyDynamicContentWidgetFactory_EmptyLoading$stableprop_getter|app_cash_redwood_treehouse_composeui_EmptyDynamicContentWidgetFactory_EmptyLoading$stableprop_getter(){}[0]

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright (C) 2024 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package app.cash.redwood.treehouse.composeui

import androidx.compose.runtime.Composable
import app.cash.redwood.Modifier
import app.cash.redwood.treehouse.Crashed
import app.cash.redwood.treehouse.DynamicContentWidgetFactory
import app.cash.redwood.treehouse.Loading

/** Don't show anything for loading or error screens. */
internal object EmptyDynamicContentWidgetFactory :
DynamicContentWidgetFactory<@Composable () -> Unit> {
override fun Loading() = EmptyLoading()

override fun Crashed() = EmptyCrashed()

internal class EmptyCrashed : Crashed<@Composable () -> Unit> {
override var modifier: Modifier = Modifier
override val value = @Composable {
}

override fun uncaughtException(uncaughtException: Throwable) {
}

override fun restart(restart: () -> Unit) {
}
}

internal class EmptyLoading : Loading<@Composable () -> Unit> {
override var modifier: Modifier = Modifier
override val value = @Composable {
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.onSizeChanged
Expand All @@ -32,6 +31,7 @@ import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.unit.LayoutDirection
import app.cash.redwood.composeui.safeAreaInsets
import app.cash.redwood.treehouse.AppService
import app.cash.redwood.treehouse.DynamicContentWidgetFactory
import app.cash.redwood.treehouse.StateSnapshot
import app.cash.redwood.treehouse.TreehouseApp
import app.cash.redwood.treehouse.TreehouseContentSource
Expand All @@ -55,10 +55,10 @@ public fun <A : AppService> TreehouseContent(
widgetSystem: WidgetSystem<@Composable () -> Unit>,
contentSource: TreehouseContentSource<A>,
modifier: Modifier = Modifier,
dynamicContent: DynamicContent = DynamicContent(),
dynamicContentWidgetFactory: DynamicContentWidgetFactory<@Composable () -> Unit> =
EmptyDynamicContentWidgetFactory,
) {
val onBackPressedDispatcher = platformOnBackPressedDispatcher()
val scope = rememberCoroutineScope()

var viewportSize: Size? by remember { mutableStateOf(null) }
val density = LocalDensity.current
Expand All @@ -77,17 +77,10 @@ public fun <A : AppService> TreehouseContent(
override val children: ComposeWidgetChildren = ComposeWidgetChildren()

override val value: @Composable () -> Unit = {
dynamicContent.Render(children)
}

override fun contentState(loadCount: Int, attached: Boolean, uncaughtException: Throwable?) {
dynamicContent.contentState(scope, loadCount, attached, uncaughtException)
}

override fun restart(restart: (() -> Unit)?) {
dynamicContent.restart(restart)
children.Render()
}

override val dynamicContentWidgetFactory = dynamicContentWidgetFactory
override val onBackPressedDispatcher = onBackPressedDispatcher
override val uiConfiguration = MutableStateFlow(uiConfiguration)

Expand Down
Loading

0 comments on commit 1c91bee

Please sign in to comment.