feat(RevenueCatUI): add presentation-session state store (PWENG-57)#3660
Open
AlvaroBrey wants to merge 13 commits into
Open
feat(RevenueCatUI): add presentation-session state store (PWENG-57)#3660AlvaroBrey wants to merge 13 commits into
AlvaroBrey wants to merge 13 commits into
Conversation
Contributor
Author
This was referenced Jun 26, 2026
Contributor
Author
|
@cursor review |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3660 +/- ##
=======================================
Coverage 80.49% 80.49%
=======================================
Files 404 404
Lines 16771 16771
Branches 2397 2397
=======================================
Hits 13500 13500
Misses 2327 2327
Partials 944 944 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
a970520 to
f3d0360
Compare
a932631 to
d4d7399
Compare
f3d0360 to
f1f5b18
Compare
3eebd7d to
3cb75e6
Compare
📸 Snapshot Test593 unchanged
🛸 Powered by Emerge Tools |
5827123 to
a5cf50f
Compare
f1f5b18 to
e7fc9f5
Compare
be9d0f7 to
eeb9508
Compare
Contributor
Author
|
@cursor review |
Contributor
Author
|
bugbot run |
Contributor
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit bca6976. Configure here.
df99d4f to
375a5f2
Compare
4b937cb to
063cf7e
Compare
ca60e26 to
6936733
Compare
375a5f2 to
cb01277
Compare
6936733 to
cc087cd
Compare
cb01277 to
dee70ca
Compare
cc087cd to
9100066
Compare
dee70ca to
9c51ba7
Compare
9c51ba7 to
e04c671
Compare
…eset(), clear standalone on close
… fine-grained recomposition Replace flat mutableStateMapOf<String, JsonPrimitive> with mutableStateMapOf<String, MutableState<JsonPrimitive>>. Mutating a value touches only that key's MutableState, so derivedStateOf blocks reading other keys are not invalidated. declaredTypes -> ConcurrentHashMap (never snapshot-read).
Prewarm registers step declarations on a background dispatcher while navigation can register/apply updates on the caller's thread.
Cooperative cancellation can't stop an in-flight computeStateForStep on the background dispatcher, so reading currentWorkflowStateStore live let a stale prewarm leak the old session's declarations into a new session's store. Capture the store at launch and thread it through instead.
…ate store Follows the data-layer change from String to enum; the type check is now an exhaustive when over ValueType.
…is swapped If a newer presentation swaps in a different PaywallStateStore while a prewarm is computing, skip caching its result so a step is never bound to the old store.
e04c671 to
9598d8d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Introduces
PaywallStateStore, the runtime state container. Seeded fromstate_declarationsdefaults;applyUpdateswrites to it andcurrentValueOrDefaultreads with default fallback.Scoping: standalone paywalls own one store for the duration of the presentation; workflow paywalls share one store across all screens. Re-registering a screen's declarations (on navigation) preserves any values already written by other screens.
Internally uses
mutableStateMapOf<String, MutableState<JsonPrimitive>>so a write to one key only invalidatesderivedStateOfblocks reading that key, not every component.declaredTypesis a plainConcurrentHashMap(never snapshot-read).Note
Medium Risk
Touches core paywall/workflow state lifecycle and background prewarm concurrency; incorrect store scoping could leak or drop user-driven state across steps or sessions, though behavior is guarded and tested.
Overview
Adds
PaywallStateStore, an in-memory, Compose-friendly container for dashboard state-driven paywall keys: it seeds fromstate_declarations, exposescurrentValueOrDefault, and applies typedStateUpdatewrites (including payload references) with per-keyMutableStateso updates don’t over-invalidate UI.state_declarationsnow flows through components validation intoPaywallState.Loaded.Components.stateStore.PaywallViewModelowns session scoping: one reused store per standalone presentation (survives color/full refresh, cleared on dismiss) and one shared store per workflow impression (each stepregisterDeclarationswithout resetting existing keys; navigation/rebuild keeps values). Workflow prewarm captures the store on the main thread and drops stale results if the session store changes.Unit tests cover seeding, updates, type checks, and re-registration behavior.
Reviewed by Cursor Bugbot for commit f23a15e. Bugbot is set up for automated code reviews on this repo. Configure here.