Replies: 1 comment 1 reply
-
I don't think this proposal is one we would accept. Each of the scenarios you describe actually have better existing patterns in Circuit. Smart Buttons This should be solved at your data layer. Your button UIs should not maintain the state themselves, they should derive it from your underlying data layer (such as a repository). Assuming all buttons read from the same data source, they should all update accordingly. Scroll tabs contents There's different ways to solve this but the key point is that scrolling UI isn't a presenter concern. It's a UI state thing. I've solved this by exposing a composition local that scrollable UIs can observe to get signals to scroll to top. Deeplink as an Action If this is an expected scenario, I would expose new intents as an observable source and collect this in your presenter. I think your proposal tries to solve these cases by pushing more state across presenter boundaries through presenters themselves, but in an untyped and fairly limited way. Circuit really wants you to use a good data layer and to focus on deriving your state from that. Presenters aren't the source of truth, they're just translators. |
Beta Was this translation helpful? Give feedback.
-
I keep wanting to use Circuit for reusable, nested sub-"screen" components, a la React Components, but I feel like the current API is mostly (exclusively?) designed around "screens" and navigation between them. And I think there's a "simple" (but quite breaking) API change that could add a lot of the flexibility I am wanting.
Proposal
CircuitPresenterState
, mirroringCircuitUiState
Presenter.present
to take a (type-argument-ed)CircuitPresenterState
CircuitPresenterState
type argument toScreen
Saver
too?)CircuitPresenterState
argument toCircuitContent
CircuitPresenterState
property toBackStack.Record
(and expose fromNavigator
?)Motivating Examples
Smart Buttons
Say my app is a social one, and "add as friend" buttons are plastered everywhere, especially in list items! I'm a lazy developer and don't want to wire all of the boilerplate for these on every screen. I could use a Screen, but Product wants different "already friends" behavior for different screens! I wish I could pass in an an enum and an event sink to easily customize behavior.
Scroll Tab's Content on Second Click
A nice UX is scrolling to the top of a tab if you click on the tab again. But if my tabs are each just
CircuitContent()
(orNavigableCircuitContent
), I don't have access to the scroll state. I could maybe have the host Presenter be an aggregating Presenter, but that would Compose all the off-screen presenters too! I wish I could just hoist out the scroll states:Deeplink as an Action
Say the app is warm and cozy in the background and wakes up with
onNewIntent()
from a push notification. The user just got a reply to one of their comments! Due to crazy Product reasons, the comments are an integrated "sheet" within the main content Screen. So for a really nice UX, not only do we need to modify the back stack to go to the right screen, we also want to open the comments "sheet", and even scroll down the list to see the new reply.Migration Path
The changes don't have to be that invasive to existing code beyond some lower-level API breaking. I've been hacking at this a bit today, and if we don't want to completely break downstream
Screen
can takeComponent<T>
and aT
defaulted to theComponent.newPresenterState()
Conclusion
I'm opening this for discussion because I was half-way down the road of reimplementing Circuit but with this change, and I thought I should see if upstream and the community was interested or had better ideas.
I think the main argument against is that there are other ways to accomplish my examples, with CompositionLocal or some other kind of injected side channel. But I feel like this is more elegant, and more in line with Compose state hoisting.
Also, if the proposal is acceptable in some form, I would be willing to contribute the work for it 💪
edit: minor fixes after rereading
Beta Was this translation helpful? Give feedback.
All reactions