Skip to content

[PW-148] Add PaywallPresentationConfiguration for per-platform presentation style#1623

Merged
facumenzella merged 23 commits intomainfrom
facundo/pw-148-flutter-landscape-exit-offer-shows-white-area-with
Mar 20, 2026
Merged

[PW-148] Add PaywallPresentationConfiguration for per-platform presentation style#1623
facumenzella merged 23 commits intomainfrom
facundo/pw-148-flutter-landscape-exit-offer-shows-white-area-with

Conversation

@facumenzella
Copy link
Copy Markdown
Member

@facumenzella facumenzella commented Feb 11, 2026

Summary

Fixes landscape white-area issue (PW-148) by adding an explicit opt-in API for controlling paywall presentation style, matching the approach in purchases-unity PR #839.

  • Adds `PaywallPresentationConfiguration` with per-platform style types (`IOSPaywallPresentationStyle`, `AndroidPaywallPresentationStyle`)
  • Adds optional `presentationConfiguration` parameter to `presentPaywall()` and `presentPaywallIfNeeded()`
  • iOS plugin passes `useFullScreenPresentation` only when explicitly set — default behavior unchanged (sheet on iOS)
  • No device filtering — if the dev passes `fullScreen`, it applies on any device (iPhone or iPad)
  • Purchase tester shows a `CupertinoActionSheet` to choose Sheet or Full Screen before presenting

Usage

// Full screen on iOS (fixes landscape white-area bug PW-148)
final result = await RevenueCatUI.presentPaywall(
  presentationConfiguration: PaywallPresentationConfiguration(
    ios: IOSPaywallPresentationStyle.fullScreen,
  ),
);

// Default behavior (sheet on iOS)
final result = await RevenueCatUI.presentPaywall();

Related

Test plan

  • All unit tests pass
  • API tester (`flutter analyze`) clean — no breaking changes
  • Tests cover `fullScreen` and `sheet` configurations
  • Tests verify `useFullScreenPresentation` is not sent when no config is passed
  • Purchase tester builds on iOS
  • Manual test: present paywall without config → sheet on iOS
  • Manual test: present paywall with `ios: fullScreen` → full screen on iOS

Note

Medium Risk
Adds a new public API knob that changes iOS paywall presentation behavior and updates the iOS plugin call path; incorrect wiring could affect paywall UX on iOS. Changes are scoped and covered by new unit/API tests, reducing regression risk.

Overview
Adds an opt-in PaywallPresentationConfiguration API (with IOSPaywallPresentationStyle/AndroidPaywallPresentationStyle) and exports it from purchases_ui_flutter.

RevenueCatUI.presentPaywall() and presentPaywallIfNeeded() now accept an optional presentationConfiguration and only send the native useFullScreenPresentation flag when iOS full-screen is explicitly requested (omitting the key preserves the native default sheet behavior).

Updates the iOS plugin to accept/pass through useFullScreenPresentation instead of always forcing full-screen on iPhone, expands unit tests/API tester coverage for the new argument behavior, and updates the purchase tester example UI to let users choose sheet vs full-screen before presenting a paywall.

Written by Cursor Bugbot for commit 35fb97d. This will update automatically on new commits. Configure here.

…e white area

Enables `useFullScreenPresentation` option when presenting paywalls on iOS.
This fixes an issue where paywalls (especially exit offers) in landscape
orientation show a white area on the sides due to `.pageSheet` modal
presentation style not covering the full screen.

Requires purchases-hybrid-common with `useFullScreenPresentation` support.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@facumenzella facumenzella marked this pull request as ready for review February 16, 2026 10:00
@facumenzella facumenzella requested a review from a team as a code owner February 16, 2026 10:00
@facumenzella
Copy link
Copy Markdown
Member Author

This PR depends on RevenueCat/purchases-hybrid-common#1472 which adds the useFullScreenPresentation option to the PaywallProxy.

Updated approach: Instead of hardcoding useFullScreenPresentation: true, we now expose it as an optional parameter that defaults to false. This preserves existing behavior while letting developers opt-in to full screen presentation when needed (e.g., to fix landscape layout issues).

@facumenzella
Copy link
Copy Markdown
Member Author

@rickvdl can you take another look please? :)

facumenzella and others added 2 commits February 27, 2026 16:55
…resentation control

Replace hardcoded full-screen presentation with an explicit opt-in API,
matching the approach in purchases-unity PR #839. Developers can now
choose full-screen or sheet presentation per platform instead of having
it forced.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@facumenzella facumenzella changed the title fix: Use full screen presentation for paywalls on iOS to fix landscape white area feat: Add PaywallPresentationConfiguration API for per-platform presentation control Mar 3, 2026
…shows-white-area-with

Resolve conflicts: adopt main's formatting while keeping
useFullScreenPresentation additions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
facumenzella and others added 4 commits March 19, 2026 15:14
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds fullScreen and defaultConfiguration static constants to
PaywallPresentationConfiguration. Adds ==, hashCode, and toString
to all three configuration classes. Updates doc comments on style
classes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Only send useFullScreenPresentation when iOS presentation style is
fullScreen, instead of always sending false on Android. Adds tests
for android-only config, sheet config, and presentation config
class coverage.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…r-landscape-exit-offer-shows-white-area-with

# Conflicts:
#	purchases_ui_flutter/ios/purchases_ui_flutter/Sources/purchases_ui_flutter/PurchasesUiFlutterPlugin.swift
#	purchases_ui_flutter/lib/purchases_ui_flutter.dart
facumenzella and others added 3 commits March 19, 2026 17:55
Co-authored-by: Cesar de la Vega <664544+vegaro@users.noreply.github.com>
Co-authored-by: Cesar de la Vega <664544+vegaro@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… useFullScreenPresentation when true

- Add CupertinoActionSheet to purchase tester letting you choose Sheet or Full Screen before presenting a paywall
- Only include useFullScreenPresentation in iOS plugin options when explicitly provided (never send false)
- Add Podfile with platform :ios declaration to fix pod install
- Update SKConfig.storekit and wire it to the Xcode scheme

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@facumenzella facumenzella changed the title feat: Add PaywallPresentationConfiguration API for per-platform presentation control feat: Add PaywallPresentationConfiguration API for per-platform presentation style Mar 20, 2026
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@facumenzella facumenzella enabled auto-merge (squash) March 20, 2026 06:43
@facumenzella
Copy link
Copy Markdown
Member Author

@rickvdl this is ready to go!! :)

@facumenzella facumenzella disabled auto-merge March 20, 2026 06:44
@facumenzella facumenzella requested a review from rickvdl March 20, 2026 06:44
- Swift: when useFullScreenPresentation is explicitly passed from Dart, use
  that value; otherwise default to true on iPhone (PW-149 behavior)
- Dart: send useFullScreenPresentation: false when IOSPaywallPresentationStyle.sheet
  is explicitly set, so the iPhone default is not applied when sheet is requested
- Update tests to expect useFullScreenPresentation: false for sheet configuration

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When no presentationConfiguration is passed, the native default (sheet)
applies. Users opt in to full-screen via IOSPaywallPresentationStyle.fullScreen.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@facumenzella facumenzella requested a review from vegaro March 20, 2026 07:12
Copy link
Copy Markdown
Member

@rickvdl rickvdl left a comment

Choose a reason for hiding this comment

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

Nice work, looks good! Couple of points.

Also; I think there are some formatting changes. We could split it to keep the diff smaller, but fine to leave it as well by me.

} else if UIDevice.current.userInterfaceIdiom == .phone {
// Default: present paywalls full-screen on iPhone to avoid side white areas
// in landscape orientation. Keep iPad behavior unchanged.
options[PaywallProxy.PaywallOptionsKeys.useFullScreenPresentation] = true
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Here we default to fullscreen on iPhone, but in defaultConfiguration in flutter we set the iOS default to sheet. Maybe we should document a bit better at the default configuration?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

hmm. Does this mean we are changing the default from modal to sheet for people not using the new options?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The goal is to leave the default as it used to be, and add the options to go fullscreen. It should be like that now. I'll re-test the safe area fix from #1631 and that should be it

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes — this PR intentionally changes the default back to sheet (the native SDK default). The previous code had useFullScreenPresentation: true hardcoded, which was the fix for the landscape white-area issue but had the side effect of forcing full-screen everywhere (including iPad). Now it's opt-in: devs who want full screen pass PaywallPresentationConfiguration(ios: IOSPaywallPresentationStyle.fullScreen), and everyone else gets sheet as before.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I see, then we should be fine

facumenzella and others added 4 commits March 20, 2026 08:27
Remove accidentally committed Podfile (auto-generated), revert
Debug.xcconfig extra include line, and restore SKConfig.storekit
to the original content.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…files

- Gate useFullScreenPresentation to UIDevice.userInterfaceIdiom == .phone
  so iPad always uses the default sheet presentation
- Revert unintended macOS Flutter-Debug/Release.xcconfig changes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove iPhone-only guard: devs can pass fullScreen for any device
- Revert CocoaPods changes to Release.xcconfig, contents.xcworkspacedata,
  and project.pbxproj

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@facumenzella facumenzella changed the title feat: Add PaywallPresentationConfiguration API for per-platform presentation style [PW-148] Add PaywallPresentationConfiguration for per-platform presentation style Mar 20, 2026
…uested

Avoids sending false when sheet is explicitly set, making it
indistinguishable from the default (key absent). Now the key is only
sent as true when fullScreen is opted into.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@facumenzella facumenzella merged commit 582a5ed into main Mar 20, 2026
14 checks passed
@facumenzella facumenzella deleted the facundo/pw-148-flutter-landscape-exit-offer-shows-white-area-with branch March 20, 2026 09:20
facumenzella pushed a commit that referenced this pull request Mar 23, 2026
**This is an automatic release.**

## RevenueCat SDK
### 🐞 Bugfixes
* [PW-148] Add PaywallPresentationConfiguration for per-platform
presentation style (#1623) via Facundo Menzella (@facumenzella)
### 📦 Dependency Updates
* [AUTOMATIC BUMP] Updates purchases-hybrid-common to 17.53.0 (#1692)
via RevenueCat Git Bot (@RCGitBot)
* [Android
9.27.0](https://github.com/RevenueCat/purchases-android/releases/tag/9.27.0)
* [iOS
5.66.0](https://github.com/RevenueCat/purchases-ios/releases/tag/5.66.0)

## RevenueCatUI SDK
### 🐞 Bugfixes
* [PW-149] Fix PaywallView landscape issue (#1631) via Facundo Menzella
(@facumenzella)

### 🔄 Other Changes
* Bump json from 2.18.1 to 2.19.2 (#1691) via dependabot[bot]
(@dependabot[bot])

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Primarily a versioned release bump across metadata/changelogs with no
functional code changes beyond updating reported plugin version strings
and dependency versions.
> 
> **Overview**
> Bumps the Flutter Purchases and Purchases UI plugins to **`9.15.1`**
across `pubspec.yaml`, Gradle, CocoaPods specs, and the runtime-reported
plugin version constants (Android/iOS/Web).
> 
> Updates release documentation (`CHANGELOG.md`, `CHANGELOG-LATEST.md`,
`VERSIONS.md`) to record the included bugfixes and dependency changes,
including `purchases-hybrid-common` **`17.53.0`** (Android `9.27.0`, iOS
`5.66.0`) and a `json` dependency bump.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
59eaab9. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants