Skip to content

[PoC] Checkpoints sample app - #4166

Closed
tonidero wants to merge 8 commits into
toni/checkpoints-offering-presenterfrom
toni/checkpoints-sample-app
Closed

[PoC] Checkpoints sample app#4166
tonidero wants to merge 8 commits into
toni/checkpoints-offering-presenterfrom
toni/checkpoints-sample-app

Conversation

@tonidero

@tonidero tonidero commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Description

This is a PoC to test the gate-focused checkpoints API in a realistic integration.

Adds examples/checkpoints-sample, a minimal app shaped like a real integration rather than a feature-by-feature exerciser (that's examples/checkpointtester):

  • Onboarding (2 steps): finishing runs the onboarding_complete checkpoint and continues to home once the callback fires, whatever was served. Mimics a post-onboarding soft paywall.
  • Home: a "Tapper game" card, locked until any entitlement is active (loaded via awaitCustomerInfo(FETCH_CURRENT)). Tapping play while locked runs the play_game checkpoint with a games_played custom variable. The callback firing means the gate let the user through, so the game opens whatever was served: a null result (nothing presented) or a result whose grants are merged into the card. If the user backs out of the flow, the callback never fires and they stay on home with the card still locked.
  • Game: dummy tap-counter screen.
  • Subscriber attribute: a small floating button on every screen opens a dialog to set or unset one attribute, to exercise rules that target attributes.

The checkpoint calls are not modelled as pending operations (no spinner): the callback may legitimately never fire.

The app exercises both ways of supplying a PaywallPresenter. ParkedPaywallPresenter parks a request in a StateFlow and the app root renders a paywall while one is set; there are two instances:

  • Global, registered on Purchases in MainApplication: renders SamplePaywall, a full-screen paywall (packages as selectable cards, purchase through awaitPurchase, restore, close).
  • Call-site, passed through CheckpointParams.paywallPresenter by the play_game call: renders PlayGamePaywall, a bottom sheet with one purchase button per package, restore and "Not now". A "Use call-site paywall" switch on home (on by default) controls whether it is passed, so turning it off falls back to the global paywall.

In both, a purchase or a restore that leaves an active entitlement reports Purchased, closing reports Closed, and system back NavigatedBack. Only play_game resolves to an offering, so onboarding still shows the SDK's workflow.

The app reuses the paywall tester's applicationId and defaults to the checkpoint tester's API key (then PAYWALL_TESTER_API_KEY_A), so the onboarding_complete checkpoint id is shared with checkpointtester; override with CHECKPOINTS_SAMPLE_API_KEY in local.properties.

Testing

  • :examples:checkpoints-sample:assembleDebug and detektAll pass.
  • Manual: walk onboarding → home → play against a project with onboarding_complete / play_game checkpoints configured; with the switch on the play paywall is the bottom sheet, with it off the full-screen one. Back out of either and confirm nothing advances, close it and confirm it does.

🤖 Generated with Claude Code

@tonidero tonidero changed the title Add a checkpoints sample app gating onboarding and a game [PoC] Checkpoints sample app Sep 3, 2026
@RevenueCat-Danger-Bot

RevenueCat-Danger-Bot commented Sep 3, 2026

Copy link
Copy Markdown
1 Message
📖 This PR changes 1068 lines of production Kotlin/Java (limit 300); skipped via skip-pr-lines-changed-check label.

Generated by 🚫 Danger

@tonidero
tonidero force-pushed the toni/checkpoints-sample-app branch from 5597ef7 to 96c488f Compare September 3, 2026 14:44
@tonidero
tonidero force-pushed the toni/checkpoints-offering-presenter branch 2 times, most recently from 3cb5225 to b6a6c62 Compare September 3, 2026 15:39
@tonidero
tonidero force-pushed the toni/checkpoints-sample-app branch from 96c488f to 3c1c830 Compare September 3, 2026 15:39
@tonidero
tonidero force-pushed the toni/checkpoints-offering-presenter branch from b6a6c62 to 9aace09 Compare September 4, 2026 07:32
@tonidero
tonidero force-pushed the toni/checkpoints-sample-app branch from 3c1c830 to 4a4f15f Compare September 4, 2026 07:32
@tonidero
tonidero force-pushed the toni/checkpoints-offering-presenter branch from 9aace09 to 7f7e443 Compare September 4, 2026 08:59
@tonidero
tonidero force-pushed the toni/checkpoints-sample-app branch 2 times, most recently from 273a4a0 to 09a8100 Compare September 4, 2026 09:58
@tonidero
tonidero force-pushed the toni/checkpoints-offering-presenter branch from 7f7e443 to 3cc2efd Compare September 4, 2026 09:58
@tonidero
tonidero force-pushed the toni/checkpoints-sample-app branch from 09a8100 to 2057b55 Compare September 4, 2026 10:25
@tonidero
tonidero force-pushed the toni/checkpoints-offering-presenter branch from f28e814 to 7c93e66 Compare September 4, 2026 10:55
@tonidero
tonidero force-pushed the toni/checkpoints-sample-app branch from 2057b55 to 47cb582 Compare September 4, 2026 10:55
@tonidero
tonidero force-pushed the toni/checkpoints-offering-presenter branch from 7c93e66 to d909efe Compare September 4, 2026 11:32
@tonidero
tonidero force-pushed the toni/checkpoints-sample-app branch from 47cb582 to 672e63c Compare September 4, 2026 11:32
@tonidero
tonidero force-pushed the toni/checkpoints-offering-presenter branch from d909efe to 7af56e5 Compare September 4, 2026 11:57
@tonidero
tonidero force-pushed the toni/checkpoints-sample-app branch 2 times, most recently from 58b426a to fa6c832 Compare September 4, 2026 12:03
@tonidero
tonidero force-pushed the toni/checkpoints-offering-presenter branch 2 times, most recently from a2ea116 to f8efc83 Compare September 4, 2026 12:51
@tonidero
tonidero force-pushed the toni/checkpoints-sample-app branch from fa6c832 to 8e25068 Compare September 4, 2026 12:51
@tonidero
tonidero force-pushed the toni/checkpoints-offering-presenter branch from f8efc83 to d97c975 Compare September 4, 2026 13:16
@tonidero
tonidero force-pushed the toni/checkpoints-sample-app branch from 8e25068 to 13eeb7c Compare September 4, 2026 13:16
@tonidero
tonidero force-pushed the toni/checkpoints-offering-presenter branch from d97c975 to 9316660 Compare September 4, 2026 13:40
@tonidero
tonidero force-pushed the toni/checkpoints-sample-app branch from 5a19dd1 to 4b6c26b Compare September 4, 2026 13:40
@tonidero
tonidero force-pushed the toni/checkpoints-sample-app branch from 14faab3 to 944135a Compare September 7, 2026 17:00
@tonidero
tonidero force-pushed the toni/checkpoints-offering-presenter branch from 0bc4a42 to b411893 Compare September 7, 2026 17:04
@tonidero
tonidero force-pushed the toni/checkpoints-sample-app branch from 944135a to 70eda62 Compare September 7, 2026 17:04
@tonidero
tonidero force-pushed the toni/checkpoints-offering-presenter branch from b411893 to 78ceb14 Compare September 8, 2026 09:44
@tonidero
tonidero force-pushed the toni/checkpoints-sample-app branch 2 times, most recently from 97bc07b to 67cafbf Compare September 8, 2026 10:58
@tonidero
tonidero force-pushed the toni/checkpoints-offering-presenter branch from 78ceb14 to 7ae209e Compare September 8, 2026 10:58
@tonidero
tonidero force-pushed the toni/checkpoints-sample-app branch from 67cafbf to adeac9a Compare September 8, 2026 14:14
@tonidero
tonidero force-pushed the toni/checkpoints-offering-presenter branch from 7ae209e to 195cfc6 Compare September 8, 2026 14:14
@tonidero
tonidero force-pushed the toni/checkpoints-sample-app branch from adeac9a to 6f10d22 Compare September 8, 2026 15:11
@tonidero
tonidero force-pushed the toni/checkpoints-offering-presenter branch from 195cfc6 to 138469b Compare September 8, 2026 15:11
@tonidero
tonidero force-pushed the toni/checkpoints-sample-app branch from 6f10d22 to c32d9c6 Compare September 8, 2026 15:25
@tonidero
tonidero force-pushed the toni/checkpoints-offering-presenter branch 2 times, most recently from e83b62e to 98a4b55 Compare September 9, 2026 09:30
@tonidero
tonidero force-pushed the toni/checkpoints-sample-app branch from c32d9c6 to 2fb073d Compare September 9, 2026 09:30
@tonidero
tonidero removed this pull request from stack #4189 September 9, 2026 11:20
@tonidero
tonidero force-pushed the toni/checkpoints-offering-presenter branch from 98a4b55 to 3907a11 Compare September 9, 2026 11:21
@tonidero
tonidero force-pushed the toni/checkpoints-sample-app branch from 2fb073d to 18fb6f7 Compare September 9, 2026 11:21
@tonidero
tonidero added this pull request to stack #4205 September 9, 2026 11:21
@tonidero
tonidero force-pushed the toni/checkpoints-sample-app branch from 18fb6f7 to 4c7876c Compare September 9, 2026 12:13
@tonidero
tonidero force-pushed the toni/checkpoints-offering-presenter branch from 3907a11 to 89a4dd4 Compare September 9, 2026 12:13
tonidero and others added 8 commits September 11, 2026 10:31
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The checkpoint callback may never fire (hard gate, no entitlement), so
modelling the call as a pending operation would strand the user on a
spinner with no way forward.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The gate callback only fires when the user goes through the checkpoint,
so the sample no longer re-checks entitlements client-side; the grants
are merged into the card for inspection.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The play checkpoint's callback now receives null when nothing was
presented; the game starts either way and only the grants are merged in.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The sample registers SamplePaywallPresenter on Purchases; the app root
renders SamplePaywall, a simple full-screen paywall with package cards,
purchase, restore and close, whenever a checkpoint resolves to an
offering.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A small floating button on every screen opens a dialog with key and
value fields, so rules that target attributes can be exercised without
leaving the app.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…heckpoint

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@tonidero

Copy link
Copy Markdown
Contributor Author

Closing this one since we do have the checkpoint tester app already

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.

2 participants