Skip to content

Commit

Permalink
WIP persist tab state
Browse files Browse the repository at this point in the history
This is just some tinkering to resolve #116 and after talking with @bryanstern. Wanna iterate on this more and see if we can make this simpler, and also possibly explore implementing an analogous `RetainedStateHolder`.

Another thing this highlights is the fact that we always initially show a progress indicator even when restoring from a loaded state, wonder what we can do to improve that.
  • Loading branch information
ZacSweers committed Jan 31, 2024
1 parent e428463 commit a8544ae
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,25 +39,7 @@ public fun CircuitContent(
) {
val navigator =
remember(onNavEvent) {
object : Navigator {
override fun goTo(screen: Screen) {
onNavEvent(NavEvent.GoTo(screen))
}

override fun resetRoot(newRoot: Screen): List<Screen> {
onNavEvent(NavEvent.ResetRoot(newRoot))
return emptyList()
}

override fun pop(): Screen? {
onNavEvent(NavEvent.Pop)
return null
}

override fun peek(): Screen {
return screen
}
}
Navigator.navEventNavigator(screen, onNavEvent)
}
CircuitContent(screen, navigator, modifier, circuit, unavailableContent)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,31 @@ public fun Navigator.onNavEvent(event: NavEvent) {
}
}

public fun Navigator.Companion.navEventNavigator(
screen: Screen,
onNavEvent: (event: NavEvent) -> Unit,
): Navigator {
return object : Navigator {
override fun goTo(screen: Screen) {
onNavEvent(NavEvent.GoTo(screen))
}

override fun resetRoot(newRoot: Screen): List<Screen> {
onNavEvent(NavEvent.ResetRoot(newRoot))
return emptyList()
}

override fun pop(): Screen? {
onNavEvent(NavEvent.Pop)
return null
}

override fun peek(): Screen {
return screen
}
}
}

/** A sealed navigation interface intended to be used when making a navigation callback. */
public sealed interface NavEvent : CircuitUiEvent {
/** Corresponds to [Navigator.pop]. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ public interface Navigator {

override fun resetRoot(newRoot: Screen): List<Screen> = emptyList()
}

public companion object
}

/** Calls [Navigator.pop] until the given [predicate] is matched or it pops the root. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,14 @@ import androidx.compose.runtime.saveable.rememberSaveableStateHolder
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import com.slack.circuit.backstack.rememberSaveableBackStack
import com.slack.circuit.codegen.annotations.CircuitInject
import com.slack.circuit.foundation.CircuitContent
import com.slack.circuit.foundation.LocalCircuit
import com.slack.circuit.foundation.NavEvent
import com.slack.circuit.foundation.navEventNavigator
import com.slack.circuit.foundation.onNavEvent
import com.slack.circuit.foundation.rememberPresenter
import com.slack.circuit.foundation.rememberUi
import com.slack.circuit.retained.rememberRetained
import com.slack.circuit.runtime.CircuitUiEvent
import com.slack.circuit.runtime.CircuitUiState
Expand Down Expand Up @@ -85,12 +88,28 @@ fun HomeContent(state: HomeScreen.State, modifier: Modifier = Modifier) {
}
},
) { paddingValues ->
val screen = state.navItems[state.selectedIndex].screen
CircuitContent(
screen,
modifier = Modifier.padding(paddingValues),
onNavEvent = { event -> state.eventSink(ChildNav(event)) },
)
val saveableStateHolder = rememberSaveableStateHolder()
val currentScreen = state.navItems[state.selectedIndex].screen
saveableStateHolder.SaveableStateProvider(currentScreen) {
val circuit = requireNotNull(LocalCircuit.current)
val ui = rememberUi(currentScreen, factory = circuit::ui)
val presenter =
rememberPresenter(
currentScreen,
navigator =
Navigator.navEventNavigator(currentScreen) { event ->
state.eventSink(ChildNav(event))
},
factory = circuit::presenter,
)

CircuitContent(
screen = currentScreen,
modifier = Modifier.padding(paddingValues),
presenter = presenter!!,
ui = ui!!,
)
}
contentComposed = true
}
Platform.ReportDrawnWhen { contentComposed }
Expand Down

0 comments on commit a8544ae

Please sign in to comment.