Skip to content

Conversation

@vegaro
Copy link
Contributor

@vegaro vegaro commented Oct 6, 2025

We realized the current version wasn't correct since the functions are not available from the Editor. Meaning that if you try to link a Button's onClick event to PresentPaywall, it's not possible because of the parameters, and becuase it doesn't return void.

This PR adds proper configuration options and refactors the functions so they can be worked directly from the Editor.

Here's an example of the component with a handler for the result events attached to it:

Screenshot 2025-10-07 at 10 08 07

And then a Button can be configured to present the paywall:

Screenshot 2025-10-07 at 10 09 08

@vegaro vegaro added pr:other Changes to our CI configuration files and scripts pr:RevenueCatUI pr:changelog_ignore labels Oct 6, 2025
@vegaro vegaro marked this pull request as ready for review October 7, 2025 08:09
@vegaro vegaro requested a review from a team as a code owner October 7, 2025 08:09

[Header("Events")]
[Tooltip("Invoked when the user completes a purchase.")]
public UnityEvent OnPurchased = new UnityEvent();
Copy link
Contributor Author

@vegaro vegaro Oct 7, 2025

Choose a reason for hiding this comment

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

These UnityEvents can accept generics, but won't work with a custom class like PaywallResult, so I decided to split it into multiple events, that way they can be set in the editor. The alternative is to use a primitive type (string), but I think that limits us more if we ever want to send something in the events:

[Serializable]
public class StringEvent : UnityEvent<string> { }

[Header("Events")]
public StringEvent OnPaywallResult = new StringEvent();

private void HandleResult(PaywallResult result)
{
    OnPaywallResult?.Invoke(result.Result.ToString());
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If we ever need to send something like UnityEvent<CustomerInfo>, it's still possible but devs need to hook to it via code (it doesn't show up in the Editor's dropdown):

[Serializable]
public class CustomerInfoEvent : UnityEvent<CustomerInfo> { }

[Header("Events")]
public CustomerInfoEvent OnCustomerInfoUpdated = new CustomerInfoEvent();
using UnityEngine;

public class CustomerInfoHandler : MonoBehaviour
{
    [SerializeField] private Purchases purchases;

    void Start()
    {
        // Subscribe to the event
        purchases.OnCustomerInfoUpdated.AddListener(HandleCustomerInfo);
    }

    void OnDestroy()
    {
        // Unsubscribe
        purchases.OnCustomerInfoUpdated.RemoveListener(HandleCustomerInfo);
    }

    private void HandleCustomerInfo(Purchases.CustomerInfo customerInfo)
    {
        Debug.Log($"Customer info updated: {customerInfo.ActiveSubscriptions.Count} active subscriptions");
        
        foreach (var entitlement in customerInfo.Entitlements.Active)
        {
            Debug.Log($"Active entitlement: {entitlement.Key}");
        }
    }
}

Or we could remove the parameter and inform developers to fetch the CustomerInfo themselves which I believe is the Unity standard since it works in the Editor:

[Header("Events")]
[Tooltip("Invoked when customer info is updated. Use GetCustomerInfo() to fetch the latest data.")]
public UnityEvent OnCustomerInfoUpdated = new UnityEvent();

private void NotifyCustomerInfoUpdate()
{
    OnCustomerInfoUpdated?.Invoke();
}

Copy link
Contributor

@tonidero tonidero left a comment

Choose a reason for hiding this comment

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

Just a couple comments, but looking great!! Excited to get this out!

@vegaro vegaro requested a review from facumenzella October 7, 2025 13:42
@vegaro vegaro requested a review from tonidero October 7, 2025 13:43
Copy link
Contributor

@tonidero tonidero left a comment

Choose a reason for hiding this comment

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

LGTM as far as I can tell 🙌

@vegaro
Copy link
Contributor Author

vegaro commented Oct 9, 2025

@tonidero @facumenzella
I am a bit doubtful about my last commit that adapts PaywallOptions to the changes from #710

In the last commit I added a purchases.GetOfferings call to get the Offering via the identifier. But I am not completely convinced because of the async calls and because it feels useless having to do that if we are actually converting it to offering identifier later on.

The alternative is to add an internal constructor to PaywallOptions and do this:

        internal string OfferingIdentifier => _offeringIdentifier ?? Offering?.Identifier;

The problem that has is that _offeringIdentifier will be not null, and Offering null, which is kinda inconsistent and could be weird.

What do you think?

@facumenzella
Copy link
Contributor

facumenzella commented Oct 9, 2025

I am thinking that if we add async methods to the MonoBehaviour, we need to expose a OnPaywallPresentedChanged or something like that to allow hooking to state changes right?
I am thinking about loading states for example

nothing 🙃

@vegaro
Copy link
Contributor Author

vegaro commented Oct 9, 2025

Actually, I was looking at Android's implementation and there's a sealed class OfferingSelection to solve the offeringIdentifier vs offering problem in PaywallOptions. I will have a go at that, because I think that's the correct solution

@vegaro
Copy link
Contributor Author

vegaro commented Oct 9, 2025

ok finally! I think the last commit is what I like the most 2c0e358 (#706) @facumenzella @tonidero

@vegaro vegaro requested a review from tonidero October 9, 2025 15:34
Copy link
Contributor

@tonidero tonidero left a comment

Choose a reason for hiding this comment

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

This looks good!

@vegaro vegaro merged commit 9af685b into main Oct 9, 2025
7 checks passed
@vegaro vegaro deleted the proper-behaviour branch October 9, 2025 15:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr:changelog_ignore pr:other Changes to our CI configuration files and scripts pr:RevenueCatUI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants