Skip to content

feat(RevenueCatUI): add presentation-session state store (PWENG-57)#3660

Open
AlvaroBrey wants to merge 13 commits into
mainfrom
alvarobrey/pweng-57-state-store
Open

feat(RevenueCatUI): add presentation-session state store (PWENG-57)#3660
AlvaroBrey wants to merge 13 commits into
mainfrom
alvarobrey/pweng-57-state-store

Conversation

@AlvaroBrey

@AlvaroBrey AlvaroBrey commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Introduces PaywallStateStore, the runtime state container. Seeded from state_declarations defaults; applyUpdates writes to it and currentValueOrDefault reads 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 invalidates derivedStateOf blocks reading that key, not every component. declaredTypes is a plain ConcurrentHashMap (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 from state_declarations, exposes currentValueOrDefault, and applies typed StateUpdate writes (including payload references) with per-key MutableState so updates don’t over-invalidate UI.

state_declarations now flows through components validation into PaywallState.Loaded.Components.stateStore. PaywallViewModel owns session scoping: one reused store per standalone presentation (survives color/full refresh, cleared on dismiss) and one shared store per workflow impression (each step registerDeclarations without 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.

AlvaroBrey commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

@AlvaroBrey AlvaroBrey self-assigned this Jun 26, 2026
@AlvaroBrey AlvaroBrey changed the title feat(RevenueCatUI): add presentation-session PaywallStateStore feat(RevenueCatUI): add presentation-session state store (PWENG-57) Jun 26, 2026
@AlvaroBrey

Copy link
Copy Markdown
Contributor Author

@cursor review

@codecov

codecov Bot commented Jun 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 80.49%. Comparing base (eefa145) to head (f23a15e).
⚠️ Report is 1 commits behind head on main.

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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@AlvaroBrey AlvaroBrey force-pushed the alvarobrey/pweng-57-data-layer branch from a970520 to f3d0360 Compare June 29, 2026 10:36
@AlvaroBrey AlvaroBrey force-pushed the alvarobrey/pweng-57-state-store branch from a932631 to d4d7399 Compare June 29, 2026 10:36
@AlvaroBrey AlvaroBrey force-pushed the alvarobrey/pweng-57-data-layer branch from f3d0360 to f1f5b18 Compare June 29, 2026 14:54
@AlvaroBrey AlvaroBrey force-pushed the alvarobrey/pweng-57-state-store branch from 3eebd7d to 3cb75e6 Compare June 29, 2026 14:54
@emerge-tools

emerge-tools Bot commented Jun 29, 2026

Copy link
Copy Markdown

📸 Snapshot Test

593 unchanged

Name Added Removed Modified Renamed Unchanged Errored Approval
TestPurchasesUIAndroidCompatibility Paparazzi
com.revenuecat.testpurchasesuiandroidcompatibility.paparazzi
0 0 0 0 258 0 N/A
TestPurchasesUIAndroidCompatibility
com.revenuecat.testpurchasesuiandroidcompatibility
0 0 0 0 335 0 N/A

🛸 Powered by Emerge Tools

@AlvaroBrey AlvaroBrey requested a review from MonikaMateska June 30, 2026 10:18
@AlvaroBrey AlvaroBrey marked this pull request as ready for review June 30, 2026 10:19
@AlvaroBrey AlvaroBrey requested a review from a team as a code owner June 30, 2026 10:19
@AlvaroBrey AlvaroBrey removed the request for review from a team June 30, 2026 10:19
@AlvaroBrey AlvaroBrey requested a review from a team July 1, 2026 07:45
@AlvaroBrey AlvaroBrey force-pushed the alvarobrey/pweng-57-state-store branch from 5827123 to a5cf50f Compare July 1, 2026 13:14
@AlvaroBrey AlvaroBrey force-pushed the alvarobrey/pweng-57-data-layer branch from f1f5b18 to e7fc9f5 Compare July 1, 2026 13:14
@AlvaroBrey AlvaroBrey force-pushed the alvarobrey/pweng-57-state-store branch from be9d0f7 to eeb9508 Compare July 1, 2026 13:46
@AlvaroBrey

Copy link
Copy Markdown
Contributor Author

@cursor review

@AlvaroBrey

Copy link
Copy Markdown
Contributor Author

bugbot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ 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.

@AlvaroBrey AlvaroBrey force-pushed the alvarobrey/pweng-57-state-store branch 2 times, most recently from df99d4f to 375a5f2 Compare July 2, 2026 07:43
@AlvaroBrey AlvaroBrey force-pushed the alvarobrey/pweng-57-data-layer branch from 4b937cb to 063cf7e Compare July 3, 2026 08:55
@AlvaroBrey AlvaroBrey requested a review from a team as a code owner July 3, 2026 08:55
@AlvaroBrey AlvaroBrey force-pushed the alvarobrey/pweng-57-data-layer branch 2 times, most recently from ca60e26 to 6936733 Compare July 3, 2026 10:14
@AlvaroBrey AlvaroBrey force-pushed the alvarobrey/pweng-57-state-store branch from 375a5f2 to cb01277 Compare July 3, 2026 10:14
@AlvaroBrey AlvaroBrey force-pushed the alvarobrey/pweng-57-data-layer branch from 6936733 to cc087cd Compare July 3, 2026 13:40
@AlvaroBrey AlvaroBrey force-pushed the alvarobrey/pweng-57-state-store branch from cb01277 to dee70ca Compare July 3, 2026 13:40
@AlvaroBrey AlvaroBrey changed the base branch from alvarobrey/pweng-57-data-layer to graphite-base/3660 July 3, 2026 14:04
@AlvaroBrey AlvaroBrey force-pushed the graphite-base/3660 branch from cc087cd to 9100066 Compare July 6, 2026 06:18
@AlvaroBrey AlvaroBrey force-pushed the alvarobrey/pweng-57-state-store branch from dee70ca to 9c51ba7 Compare July 6, 2026 06:18
@AlvaroBrey AlvaroBrey changed the base branch from graphite-base/3660 to main July 6, 2026 06:18
@AlvaroBrey AlvaroBrey force-pushed the alvarobrey/pweng-57-state-store branch from 9c51ba7 to e04c671 Compare July 6, 2026 13:58
AlvaroBrey and others added 12 commits July 7, 2026 15:07
… 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.
@AlvaroBrey AlvaroBrey force-pushed the alvarobrey/pweng-57-state-store branch from e04c671 to 9598d8d Compare July 7, 2026 13:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant