Skip to content

2.7.10#392

Merged
ianrumac merged 14 commits intomainfrom
develop
Apr 6, 2026
Merged

2.7.10#392
ianrumac merged 14 commits intomainfrom
develop

Conversation

@ianrumac
Copy link
Copy Markdown
Collaborator

@ianrumac ianrumac commented Apr 6, 2026

Changes in this pull request

2.7.10

Enhancements

  • Adds onboarding analytics
  • Adds prioritized preloading support
  • Improves error messages for billing errors
  • Improved error handling

Fixes

  • Prevents paywalls from dismissing on return from deep link
  • Fixes deadlock in SerialTaskManager
  • Fix issues with bottom sheet on certain Samsung devices

Checklist

  • All unit tests pass.
  • All UI tests pass.
  • Demo project builds and runs.
  • I added/updated tests or detailed why my change isn't tested.
  • I added an entry to the CHANGELOG.md for any breaking changes, enhancements, or bug fixes.
  • I have run ktlint in the main directory and fixed any issues.
  • I have updated the SDK documentation as well as the online docs.
  • I have reviewed the contributing guide

Greptile Summary

This PR (2.7.10) introduces onboarding analytics (preload and page-view events), prioritized paywall preloading, improved billing error messages, a deadlock fix in SerialTaskManager, a fix preventing paywall dismissal on deep-link return, and a Samsung bottom-sheet fix.

Key changes:

  • SerialTaskManager – Deadlock fixed by replacing a mutex with a Channel.UNLIMITED + single-consumer coroutine pattern; clean and correct.
  • PaywallPreload – New prioritizedCampaignId support preloads high-priority paywalls first, then waits 5 s before preloading the rest.
  • GetPaywallVCBillingErrors are now wrapped in SubscriptionStatusTimeout to surface a better user-facing message.
  • SuperwallPaywallActivity – Deep-link dismissal fixed via onStart state update; Samsung bottom-sheet animation fixed via doOnLayout/post sequencing.
  • AnalyticsPaywallPreloadStart, PaywallPreloadComplete, and PaywallPageView events added end-to-end (enum → sealed class → internal event → message handler).

Important Files Changed

Filename Overview
superwall/src/main/java/com/superwall/sdk/config/PaywallPreload.kt Adds prioritized preloading support but contains a duplicate-preloading bug — the second pass reuses all triggers including already-prioritized ones
superwall/src/main/java/com/superwall/sdk/misc/SerialTaskManager.kt Fixes deadlock by replacing mutex with Channel.UNLIMITED + single consumer coroutine; clean and correct
superwall/src/main/java/com/superwall/sdk/paywall/presentation/internal/operators/GetPaywallVC.kt Wraps BillingErrors in SubscriptionStatusTimeout causing analytics mismatch; also has minor Kotlin style violations
superwall/src/main/java/com/superwall/sdk/paywall/view/SuperwallPaywallActivity.kt Fixes paywall dismissal on deep-link return via onStart state update; fixes Samsung bottom-sheet animation via doOnLayout/post
superwall/src/main/java/com/superwall/sdk/paywall/presentation/internal/PaywallPresentationRequestStatus.kt Adds custom message to SubscriptionStatusTimeout; contains typo in DebuggerPresented comment
superwall/src/main/java/com/superwall/sdk/analytics/internal/trackable/TrackableSuperwallEvent.kt Adds PaywallPreload and PaywallPageView internal events with correct parameter collection
superwall/src/main/java/com/superwall/sdk/analytics/superwall/SuperwallEvent.kt Adds PaywallPreloadStart, PaywallPreloadComplete, and PaywallPageView public sealed-class entries
superwall/src/main/java/com/superwall/sdk/analytics/superwall/SuperwallEvents.kt Adds PaywallPreloadStart, PaywallPreloadComplete, and PaywallPageView enum entries
superwall/src/main/java/com/superwall/sdk/paywall/view/webview/messaging/PaywallMessageHandler.kt Handles new PageView message type by emitting a PaywallPageView analytics event
superwall/src/main/java/com/superwall/sdk/paywall/view/webview/messaging/PaywallMessage.kt Adds PageView and HapticFeedback sealed-class message types with their parsers
superwall/src/main/java/com/superwall/sdk/paywall/view/webview/messaging/PageViewData.kt New data class capturing page-view analytics fields for multi-page paywalls
superwall/src/main/java/com/superwall/sdk/models/config/Config.kt Adds optional prioritizedCampaignId field for prioritized preloading
superwall-compose/src/main/java/com/superwall/sdk/compose/PaywallComposable.kt Adds onRelease cleanup calling beforeOnDestroy and destroyed lifecycle methods

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[preloadAllPaywalls called] --> B{currentPreloadingTask != null?}
    B -- Yes --> C[Return early — skip]
    B -- No --> D[Filter triggers via ConfigLogic]
    D --> E{prioritizedCampaignId set?}
    E -- Yes --> F[Filter prioritized triggers]
    F --> G[getAllActiveTreatmentPaywallIds — prioritized only]
    G --> H[preloadPaywalls — prioritized IDs]
    H --> I[delay 5000ms]
    I --> J[getAllActiveTreatmentPaywallIds — ALL triggers BUG]
    E -- No --> J
    J --> K[preloadPaywalls — all IDs]
    K --> L[currentPreloadingTask = null]

    style J fill:#ffcccc,stroke:#cc0000
    style H fill:#ffffcc,stroke:#cccc00
Loading

Comments Outside Diff (1)

  1. superwall/src/main/java/com/superwall/sdk/config/PaywallPreload.kt, line 79-88 (link)

    P1 Prioritized paywalls preloaded twice

    The comment says "preload all remaining paywalls", but paywallIds is computed from the full triggers set, which already includes the prioritized triggers that were preloaded above. As a result, every prioritized paywall will be fetched a second time — defeating the purpose of the 5-second delay meant to avoid resource contention.

    To only preload non-prioritized paywalls in the second pass, filter them out:

    // Then preload all remaining paywalls.
    val remainingTriggers = if (prioritizedCampaignId != null) {
        triggers.filter { trigger ->
            trigger.rules.none { it.experimentGroupId == prioritizedCampaignId }
        }.toSet()
    } else {
        triggers
    }
    val paywallIds =
        ConfigLogic.getAllActiveTreatmentPaywallIds(
            triggers = remainingTriggers,
            confirmedAssignments = confirmedAssignments,
            unconfirmedAssignments = assignments.unconfirmedAssignments,
            expressionEvaluator = expressionEvaluator,
        )
    preloadPaywalls(paywallIdentifiers = paywallIds)
    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: superwall/src/main/java/com/superwall/sdk/config/PaywallPreload.kt
    Line: 79-88
    
    Comment:
    **Prioritized paywalls preloaded twice**
    
    The comment says "preload all *remaining* paywalls", but `paywallIds` is computed from the full `triggers` set, which already includes the prioritized triggers that were preloaded above. As a result, every prioritized paywall will be fetched a second time — defeating the purpose of the 5-second delay meant to avoid resource contention.
    
    To only preload non-prioritized paywalls in the second pass, filter them out:
    
    ```kotlin
    // Then preload all remaining paywalls.
    val remainingTriggers = if (prioritizedCampaignId != null) {
        triggers.filter { trigger ->
            trigger.rules.none { it.experimentGroupId == prioritizedCampaignId }
        }.toSet()
    } else {
        triggers
    }
    val paywallIds =
        ConfigLogic.getAllActiveTreatmentPaywallIds(
            triggers = remainingTriggers,
            confirmedAssignments = confirmedAssignments,
            unconfirmedAssignments = assignments.unconfirmedAssignments,
            expressionEvaluator = expressionEvaluator,
        )
    preloadPaywalls(paywallIdentifiers = paywallIds)
    ```
    
    How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "Fix changelog message" | Re-trigger Greptile

Greptile also left 3 inline comments on this PR.

Context used:

  • Context used - CLAUDE.md (source)

@ianrumac ianrumac merged commit 2e6eb99 into main Apr 6, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant