RevenueCat / react-native-purchases

React Native in-app purchases and subscriptions made easy. Support for iOS and Android.
https://www.revenuecat.com
MIT License
726 stars 81 forks source link

Paywall Template 7 (Siamese) not recognized (react-native-purchases-ui 7.28.1) #1044

Open Tom-Standen opened 1 month ago

Tom-Standen commented 1 month ago

Describe the bug I have moved to using Paywall 7 - Siamese from Paywall 5 - Bengal as it is the perfect use for our application. However, when I run the same code as before but with the new paywall I see an error that makes it look like the sdk isn't prepared for 7 - Siamese yet.

However, I am receiving the following error:

ERROR TEXT: Template not recognized: 7. You can fix this by editing the paywall in the RevenueCat dashboard The displayed paywall contains default configuration This error will be hidden in production.

  1. Environment
    1. Platform: React Native with Expo managed
    2. SDK version: 7.28.1
    3. OS version: MacOS Sonoma 14.5
    4. Xcode/Android Studio version:
    5. React Native version: 0.74.3
    6. SDK installation (CocoaPods + version or manual): Via Expo
    7. How widespread is the issue. Percentage of devices affected.
  2. Debug logs that reproduce the issue
  3. Steps to reproduce, with a description of expected vs. actual behavior
  4. Other information (e.g. stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow, etc.)

Additional context Here is a screenshot of the error: IMG_07B94B658520-1

Here is the function that is causing the error:

export const presentPaywallIfNeeded = async (entitlementIdString, offering = null) => {
    const premiumEnabled = getRemoteConfigFeatureFlags()?.premium_enabled ?? false;
    if (!premiumEnabled) return true;

    console.log("DEBUG ** presentPaywallIfNeeded()", entitlementIdString, offering);
    const paywallOptions = {
        requiredEntitlementIdentifier: entitlementIdString,
        displayCloseButton: true,
        offering: offering,
        onPurchaseStarted: () => {
            console.log("Purchase started");
        },
        onPurchaseCompleted: ({ customerInfo }) => {
            console.log("Purchase completed:", customerInfo);
            updateSubscriptionState();
        },
        onPurchaseError: (error) => {
            console.error("Purchase error:", error);
        },
        onRestoreStarted: () => {
            console.log("Restore started");
        },
        onRestoreCompleted: ({ customerInfo }) => {
            console.log("Restore completed:", customerInfo);
            updateSubscriptionState();
        },
        onRestoreError: (error) => {
            console.error("Restore error:", error);
        },
        onDismiss: () => {
            console.log("Paywall dismissed");
        }
    };

    // Add offering to paywallOptions if it's provided
    if (offering !== null) {
        console.log("DEBUG ** adding offering to paywallOptions")
        paywallOptions.offering = offering;
    }
    console.log("DEBUG ** paywallOptions:", paywallOptions);

    const paywallResult = await RevenueCatUI.presentPaywallIfNeeded(paywallOptions);

    console.log("paywallResult:", paywallResult);
    switch (paywallResult) {
        case PAYWALL_RESULT.ERROR:
        case PAYWALL_RESULT.CANCELLED:
            return false;
        case PAYWALL_RESULT.NOT_PRESENTED:
        case PAYWALL_RESULT.PURCHASED:
        case PAYWALL_RESULT.RESTORED:
            return true;
        default:
            return false;
    }
}
RCGitBot commented 1 month ago

👀 We've just linked this issue to our internal tracker and notified the team. Thank you for reporting, we're checking this out!

mshmoustafa commented 1 month ago

Hi @Tom-Standen, I think you have a couple of support tickets open about this but this error is due to the fact that this specific template has not yet been implemented for our React Native SDK. We plan on implementing it soon, on the next major version update. If you watch the releases page you'll be notified of every new release so you can update as soon as it's available.

Tom-Standen commented 1 month ago

Hey @mshmoustafa, thanks for the heads up. My mistake for sounding the alarm, I thought it was a bug!

Best, Tom

mshmoustafa commented 1 month ago

No worries, you wouldn't have known without asking!

geoffcfchen commented 1 month ago

I got exactly the same issue. Hopefully it will be fixed soon. IMG_4559

mshmoustafa commented 3 weeks ago

@geoffcfchen what version of our SDK are you using? You should be on 8.0.1

geoffcfchen commented 3 weeks ago

Hi, @mshmoustafa

After updating to 8.0.1, ios version does work. However, android does not work.

when I use the following code to print out offerings.all

  useEffect(() => {
    setLoading(true);
    const fetchOfferings = async () => {
      // console.log("test");
      try {
        const offerings = await Purchases.getOfferings();
        if (Platform.OS === "android") {
          console.log("android offerings", offerings.all);
        }
        if (Platform.OS === "ios") {
          console.log("ios offerings", offerings.all);
        }

        if (offerings) {
          // console.log("offering", offerings.all["onboarding"]);
          if (Platform.OS === "ios") {
            setOffering(offerings.all["Standard"]);
          } else {
            setOffering(offerings.all["Standard"]);
          }
        }
      } catch (e) {
        console.error(e);
      } finally {
        setLoading(false);
      }
    };

    fetchOfferings();
  }, []);

for ios, I got

  {
  "Default": {
    "annual": { "identifier": "$rc_annual", "offeringIdentifier": "Default", "packageType": "ANNUAL", "presentedOfferingContext": [Object], "product": [Object] },
    "availablePackages": [[Object], [Object]],
    "identifier": "Default",
    "metadata": {},
    "monthly": { "identifier": "$rc_monthly", "offeringIdentifier": "Default", "packageType": "MONTHLY", "presentedOfferingContext": [Object], "product": [Object] },
    "serverDescription": "The standard set of products"
  },
  "Standard": {
    "availablePackages": [[Object], [Object], [Object], [Object]],
    "identifier": "Standard",
    "metadata": {},
    "serverDescription": "Standard package"
  },
  "onboarding": {
    "annual": { "identifier": "$rc_annual", "offeringIdentifier": "onboarding", "packageType": "ANNUAL", "presentedOfferingContext": [Object], "product": [Object] },
    "availablePackages": [[Object]],
    "identifier": "onboarding",
    "metadata": {},
    "serverDescription": "Offering for the onboarding flow"
  }
}

But for android, I got

{
  "Default": {
    "annual": { "identifier": "$rc_annual", "offeringIdentifier": "Default", "packageType": "ANNUAL", "presentedOfferingContext": [Object], "product": [Object] },
    "availablePackages": [[Object], [Object]],
    "identifier": "Default",
    "lifetime": null,
    "metadata": {},
    "monthly": { "identifier": "$rc_monthly", "offeringIdentifier": "Default", "packageType": "MONTHLY", "presentedOfferingContext": [Object], "product": [Object] },
    "serverDescription": "The standard set of products",
    "sixMonth": null,
    "threeMonth": null,
    "twoMonth": null,
    "weekly": null
  },
  "onboarding": {
    "annual": { "identifier": "$rc_annual", "offeringIdentifier": "onboarding", "packageType": "ANNUAL", "presentedOfferingContext": [Object], "product": [Object] },
    "availablePackages": [[Object]],
    "identifier": "onboarding",
    "lifetime": null,
    "metadata": {},
    "monthly": null,
    "serverDescription": "Offering for the onboarding flow",
    "sixMonth": null,
    "threeMonth": null,
    "twoMonth": null,
    "weekly": null
  }
}

You can see obviously "Standard" is missing in android, which I use it for template 7.

mshmoustafa commented 2 weeks ago

@geoffcfchen I think this issue is separate from paywalls, from what I understand getOfferings doesn't depend on your paywall template. Can you run this curl request with the same app user ID and API key that you use in your code and let me know what the response is?

curl -X GET \
  https://api.revenuecat.com/v1/subscribers/{app_user_id}/offerings \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "X-Platform: android"
geoffcfchen commented 2 weeks ago

Hi @mshmoustafa

Thank you for helping out. here is the output

{
  "current_offering_id": "Standard",
  "offerings": [
    {
      "description": "The standard set of products",
      "identifier": "Default",
      "metadata": null,
      "packages": [
        {
          "identifier": "$rc_monthly",
          "platform_product_identifier": "rc_premium_900_1m"
        },
        {
          "identifier": "$rc_annual",
          "platform_product_identifier": "rc_premium_9399_1y"
        }
      ],
      "paywall": {
        "asset_base_url": "https://assets.pawwalls.com",
        "config": {
          "colors": {
            "dark": {
              "accent_1": "#24D8AD",
              "accent_2": "#24D8AD",
              "accent_3": "#606463",
              "background": "#000000",
              "call_to_action_background": "#24D8AD",
              "call_to_action_foreground": "#FFFFFF",
              "text_1": "#FFFFFF",
              "text_2": "#000000",
              "text_3": "#FFFFFF"
            },
            "light": {
              "accent_1": "#008575",
              "accent_2": "#008575",
              "accent_3": "#DFDFDF",
              "background": "#43FDD8",
              "call_to_action_background": "#2A2A2A",
              "call_to_action_foreground": "#FFFFFF",
              "text_1": "#000000",
              "text_2": "#FFFFFF",
              "text_3": "#000000"
            }
          },
          "default_package": "$rc_annual",
          "display_restore_purchases": true,
          "images": {
            "header": "1138866_1723875881.png"
          },
          "images_heic": {
            "header": "1138866_1723875881.heic"
          },
          "images_webp": {
            "header": "1138866_1723875881.webp"
          },
          "packages": ["$rc_monthly", "$rc_annual"],
          "privacy_url": "https://vetcation.com/#/privacy-policy",
          "tos_url": "https://vetcation.com/#/SMSTerms"
        },
        "default_locale": null,
        "localized_strings": {
          "en_US": {
            "call_to_action": "Support the Community Today",
            "features": [
              {
                "icon_id": "tick",
                "title": "Post unlimited questions"
              },
              {
                "icon_id": "tick",
                "title": "Support the Community"
              },
              {
                "icon_id": "tick",
                "title": "Earn a premium badge"
              }
            ],
            "offer_details": "Learn from the experts for just {{ total_price_and_per_month }}",
            "offer_name": "{{ sub_period }}",
            "title": "Learn from the Veterinary Expert"
          }
        },
        "localized_strings_by_tier": {},
        "revision": 1,
        "template_name": "5",
        "zero_decimal_place_countries": {
          "apple": ["TWN", "KAZ", "MEX", "PHL", "THA"],
          "google": ["TW", "KZ", "MX", "PH", "TH"]
        }
      }
    },
    {
      "description": "Offering for the onboarding flow",
      "identifier": "onboarding",
      "metadata": null,
      "packages": [
        {
          "identifier": "$rc_annual",
          "platform_product_identifier": "rc_11499_1y"
        }
      ]
    },
    {
      "description": "Standard package",
      "identifier": "Standard",
      "metadata": null,
      "packages": [
        {
          "identifier": "Basic Monthly",
          "platform_product_identifier": "rc_basic_400_1m"
        },
        {
          "identifier": "Premium Monthly",
          "platform_product_identifier": "rc_premium_900_1m"
        },
        {
          "identifier": "Basic Yearly",
          "platform_product_identifier": "rc_basic_4200_1y"
        },
        {
          "identifier": "Premium Yearly",
          "platform_product_identifier": "rc_premium_9399_1y"
        }
      ],
      "paywall": {
        "asset_base_url": "https://assets.pawwalls.com",
        "config": {
          "colors": {
            "dark": {
              "accent_1": "#24D8AD",
              "accent_2": "#24D8AD",
              "accent_3": "#606463",
              "background": "#000000",
              "call_to_action_background": "#24D8AD",
              "call_to_action_foreground": "#FFFFFF",
              "text_1": "#FFFFFF",
              "text_2": "#000000",
              "text_3": "#FFFFFF",
              "tier_control_background": "#606463",
              "tier_control_foreground": "#000000",
              "tier_control_selected_background": "#008575",
              "tier_control_selected_foreground": "#FFFFFF"
            },
            "light": {
              "accent_1": "#30A0F8",
              "accent_2": "#30A0F8",
              "accent_3": "#DFDFDF",
              "background": "#FFFFFF",
              "call_to_action_background": "#A8EE76",
              "call_to_action_foreground": "#000000",
              "text_1": "#000000",
              "text_2": "#FFFFFF",
              "text_3": "#000000",
              "tier_control_background": "#EFEFF0",
              "tier_control_foreground": "#000000",
              "tier_control_selected_background": "#A8EE76",
              "tier_control_selected_foreground": "#000000"
            }
          },
          "colors_by_tier": {
            "68w4WLNkAL": {
              "dark": {
                "accent_1": "#24D8AD",
                "accent_2": "#24D8AD",
                "accent_3": "#606463",
                "background": "#000000",
                "call_to_action_background": "#24D8AD",
                "call_to_action_foreground": "#FFFFFF",
                "text_1": "#FFFFFF",
                "text_2": "#000000",
                "text_3": "#FFFFFF",
                "tier_control_background": "#606463",
                "tier_control_foreground": "#000000",
                "tier_control_selected_background": "#008575",
                "tier_control_selected_foreground": "#FFFFFF"
              },
              "light": {
                "accent_1": "#30A0F8",
                "accent_2": "#30A0F8",
                "accent_3": "#DFDFDF",
                "background": "#43fdd8",
                "call_to_action_background": "#2a2a2a",
                "call_to_action_foreground": "#ffffff",
                "text_1": "#000000",
                "text_2": "#FFFFFF",
                "text_3": "#000000",
                "tier_control_background": "#EFEFF0",
                "tier_control_foreground": "#000000",
                "tier_control_selected_background": "#2a2a2a",
                "tier_control_selected_foreground": "#ffffff"
              }
            },
            "zDnM0sI2PS": {
              "dark": {
                "accent_1": "#24D8AD",
                "accent_2": "#24D8AD",
                "accent_3": "#606463",
                "background": "#000000",
                "call_to_action_background": "#24D8AD",
                "call_to_action_foreground": "#FFFFFF",
                "text_1": "#FFFFFF",
                "text_2": "#000000",
                "text_3": "#FFFFFF",
                "tier_control_background": "#606463",
                "tier_control_foreground": "#000000",
                "tier_control_selected_background": "#008575",
                "tier_control_selected_foreground": "#FFFFFF"
              },
              "light": {
                "accent_1": "#30A0F8",
                "accent_2": "#30A0F8",
                "accent_3": "#DFDFDF",
                "background": "#43fdd8",
                "call_to_action_background": "#2a2a2a",
                "call_to_action_foreground": "#ffffff",
                "close_button": "#2A2A2A",
                "text_1": "#000000",
                "text_2": "#FFFFFF",
                "text_3": "#000000",
                "tier_control_background": "#EFEFF0",
                "tier_control_foreground": "#000000",
                "tier_control_selected_background": "#2a2a2a",
                "tier_control_selected_foreground": "#ffffff"
              }
            }
          },
          "display_restore_purchases": true,
          "images": {
            "header": null
          },
          "images_by_tier": {
            "68w4WLNkAL": {
              "header": "1138866_1722750780.png"
            },
            "zDnM0sI2PS": {
              "header": "1138866_1722750780.png"
            }
          },
          "images_heic": {
            "header": null
          },
          "images_heic_by_tier": {
            "68w4WLNkAL": {
              "header": "1138866_1722750780.heic"
            },
            "zDnM0sI2PS": {
              "header": "1138866_1722750780.heic"
            }
          },
          "images_webp": {
            "header": null
          },
          "images_webp_by_tier": {
            "68w4WLNkAL": {
              "header": "1138866_1722750780.webp"
            },
            "zDnM0sI2PS": {
              "header": "1138866_1722750780.webp"
            }
          },
          "packages": [],
          "privacy_url": "https://vetcation.com/#/privacy-policy",
          "tiers": [
            {
              "default_package": "Basic Yearly",
              "id": "zDnM0sI2PS",
              "packages": ["Basic Monthly", "Basic Yearly"]
            },
            {
              "default_package": "Basic Yearly",
              "id": "68w4WLNkAL",
              "packages": ["Premium Monthly", "Premium Yearly"]
            }
          ],
          "tos_url": "https://vetcation.com/#/SMSTerms"
        },
        "default_locale": null,
        "localized_strings": {},
        "localized_strings_by_tier": {
          "en_US": {
            "68w4WLNkAL": {
              "call_to_action": "Support the Community Today",
              "features": [
                {
                  "icon_id": "tick",
                  "title": "3x visibility for posted questions"
                },
                {
                  "icon_id": "tick",
                  "title": "2x Support the Community"
                },
                {
                  "icon_id": "stars",
                  "title": "Earn a premium badge"
                }
              ],
              "offer_details": "Join the community for just {{ price_per_period }}",
              "offer_name": "{{ sub_period }}",
              "tier_name": "Premium",
              "title": "Learn from the Veterinary Expert"
            },
            "zDnM0sI2PS": {
              "call_to_action": "Support the Community Today",
              "features": [
                {
                  "icon_id": "tick",
                  "title": "Post unlimited questions"
                },
                {
                  "icon_id": "tick",
                  "title": "Support the Community"
                }
              ],
              "offer_details": "Join the community for just {{ price_per_period }}",
              "offer_name": "{{ sub_period }}",
              "tier_name": "Basic",
              "title": "Learn from the Veterinary Expert"
            }
          }
        },
        "revision": 2,
        "template_name": "7",
        "zero_decimal_place_countries": {
          "apple": ["TWN", "KAZ", "MEX", "PHL", "THA"],
          "google": ["TW", "KZ", "MX", "PH", "TH"]
        }
      }
    }
  ],
  "placements": {
    "fallback_offering_id": "Standard"
  }
}
geoffcfchen commented 2 weeks ago

Hi @mshmoustafa

I found that Android returned the correct offerings without missing any objects today. Maybe you guys have fixed it? thanks.

for ios, I got

{
  "Default": {
    "annual": {
      "identifier": "$rc_annual",
      "offeringIdentifier": "Default",
      "packageType": "ANNUAL",
      "presentedOfferingContext": [Object],
      "product": [Object]
    },
    "availablePackages": [
      [Object],
      [Object]
    ],
    "identifier": "Default",
    "metadata": {},
    "monthly": {
      "identifier": "$rc_monthly",
      "offeringIdentifier": "Default",
      "packageType": "MONTHLY",
      "presentedOfferingContext": [Object],
      "product": [Object]
    },
    "serverDescription": "The standard set of products"
  },
  "Standard": {
    "availablePackages": [
      [Object],
      [Object],
      [Object],
      [Object]
    ],
    "identifier": "Standard",
    "metadata": {},
    "serverDescription": "Standard package"
  },
  "onboarding": {
    "annual": {
      "identifier": "$rc_annual",
      "offeringIdentifier": "onboarding",
      "packageType": "ANNUAL",
      "presentedOfferingContext": [Object],
      "product": [Object]
    },
    "availablePackages": [
      [Object]
    ],
    "identifier": "onboarding",
    "metadata": {},
    "serverDescription": "Offering for the onboarding flow"
  }
}

For Android, NOW I got

{
  "Default": {
    "annual": {
      "identifier": "$rc_annual",
      "offeringIdentifier": "Default",
      "packageType": "ANNUAL",
      "presentedOfferingContext": [Object],
      "product": [Object]
    },
    "availablePackages": [
      [Object],
      [Object]
    ],
    "identifier": "Default",
    "lifetime": null,
    "metadata": {},
    "monthly": {
      "identifier": "$rc_monthly",
      "offeringIdentifier": "Default",
      "packageType": "MONTHLY",
      "presentedOfferingContext": [Object],
      "product": [Object]
    },
    "serverDescription": "The standard set of products",
    "sixMonth": null,
    "threeMonth": null,
    "twoMonth": null,
    "weekly": null
  },
  "Standard": {
    "annual": null,
    "availablePackages": [
      [Object],
      [Object],
      [Object],
      [Object]
    ],
    "identifier": "Standard",
    "lifetime": null,
    "metadata": {},
    "monthly": null,
    "serverDescription": "Standard package",
    "sixMonth": null,
    "threeMonth": null,
    "twoMonth": null,
    "weekly": null
  },
  "onboarding": {
    "annual": {
      "identifier": "$rc_annual",
      "offeringIdentifier": "onboarding",
      "packageType": "ANNUAL",
      "presentedOfferingContext": [Object],
      "product": [Object]
    },
    "availablePackages": [
      [Object]
    ],
    "identifier": "onboarding",
    "lifetime": null,
    "metadata": {},
    "monthly": null,
    "serverDescription": "Offering for the onboarding flow",
    "sixMonth": null,
    "threeMonth": null,
    "twoMonth": null,
    "weekly": null
  }
}

So the first problem was fixed.

However, although Android works fine when I use offerings.all["Default"] (template 5), Android shows the following error when I switch to offerings.all["Standard"] (template 7). Just to let you know that both offerings.all["Default"] and offerings.all["Standard"] work fine in ios.

**ERROR Your app just crashed. See the error below. java.lang.NoSuchMethodError: No static method AnimatedContent(Ljava/lang/Object;Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function1;Landroidx/compose/ui/Alignment;Ljava/lang/String;Lkotlin/jvm/functions/Function4;Landroidx/compose/runtime/Composer;II)V in class Landroidx/compose/animation/AnimatedContentKt; or its super classes (declaration of 'androidx.compose.animation.AnimatedContentKt' appears in /data/app/~~FRNKVyHv5Fekcv4FW77qpg==/com.vetcation.vetcationapp-h0czD6WpDbhLxKthOtl3Aw==/base.apk) com.revenuecat.purchases.ui.revenuecatui.templates.Template7Kt.Features(Template7.kt:370) com.revenuecat.purchases.ui.revenuecatui.templates.Template7Kt.Template7PortraitContent(Template7.kt:216) com.revenuecat.purchases.ui.revenuecatui.templates.Template7Kt.Template7(Template7.kt:131) com.revenuecat.purchases.ui.revenuecatui.InternalPaywallKt.TemplatePaywall(InternalPaywall.kt:167) com.revenuecat.purchases.ui.revenuecatui.InternalPaywallKt.access$TemplatePaywall(InternalPaywall.kt:1) com.revenuecat.purchases.ui.revenuecatui.InternalPaywallKt$LoadedPaywall$3$1.invoke(InternalPaywall.kt:148) com.revenuecat.purchases.ui.revenuecatui.InternalPaywallKt$LoadedPaywall$3$1.invoke(InternalPaywall.kt:147) androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108) androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35) androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228) com.revenuecat.purchases.ui.revenuecatui.InternalPaywallKt.LoadedPaywall(InternalPaywall.kt:143) com.revenuecat.purchases.ui.revenuecatui.InternalPaywallKt.access$LoadedPaywall(InternalPaywall.kt:1) com.revenuecat.purchases.ui.revenuecatui.InternalPaywallKt$InternalPaywall$2$2.invoke(InternalPaywall.kt:88) com.revenuecat.purchases.ui.revenuecatui.InternalPaywallKt$InternalPaywall$2$2.invoke(InternalPaywall.kt:86) androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:117) androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35) androidx.compose.animation.AnimatedVisibilityKt.AnimatedEnterExitImpl(AnimatedVisibility.kt:941) androidx.compose.animation.AnimatedVisibilityKt.AnimatedVisibility(AnimatedVisibility.kt:129) com.revenuecat.purchases.ui.revenuecatui.InternalPaywallKt$InternalPaywall$2.invoke(InternalPaywall.kt:82) com.revenuecat.purchases.ui.revenuecatui.InternalPaywallKt$InternalPaywall$2.invoke(InternalPaywall.kt:64) androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108) androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35) com.revenuecat.purchases.ui.revenuecatui.fonts.PaywallThemeKt.PaywallTheme(PaywallTheme.kt:13) com.revenuecat.purchases.ui.revenuecatui.InternalPaywallKt.InternalPaywall(InternalPaywall.kt:64) com.revenuecat.purchases.ui.revenuecatui.PaywallKt.Paywall(Paywall.kt:11) com.revenuecat.purchases.ui.revenuecatui.views.PaywallView.Content(PaywallView.kt:151) androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:252) androidx.compose.ui.platform.AbstractComposeView$ensureCompositionCreated$1.invoke(ComposeView.android.kt:251) androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108) androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35) androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228) androidx.compose.ui.platform.CompositionLocalsKt.ProvideCommonCompositionLocals(CompositionLocals.kt:195) androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:119) androidx.compose.ui.platform.AndroidCompositionLocals_androidKt$ProvideAndroidCompositionLocals$3.invoke(AndroidCompositionLocals.android.kt:118) androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108) androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35) androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228) androidx.compose.ui.platform.AndroidCompositionLocals_androidKt.ProvideAndroidCompositionLocals(AndroidCompositionLocals.android.kt:110) androidx.compose.ui.platform.WrappedComposition$setContent$1$1$2.invoke(Wrapper.android.kt:158) androidx.compose.ui.platform.WrappedComposition$setContent$1$1$2.invoke(Wrapper.android.kt:157) androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108) androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35) androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:228) androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:157) androidx.compose.ui.platform.WrappedComposition$setContent$1$1.invoke(Wrapper.android.kt:142) androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:108) androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:35) androidx.compose.runtime.ActualJvm_jvmKt.invokeComposable(ActualJvm.jvm.kt:78) androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:3340) androidx.compose.runtime.ComposerImpl.composeContent$runtime_release(Composer.kt:3273) androidx.compose.runtime.CompositionImpl.composeContent(Composition.kt:588) androidx.compose.runtime.Recomposer.composeInitial$runtime_release(Recomposer.kt:1013) androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:520) androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:142) androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:133) androidx.compose.ui.platform.AndroidComposeView.setOnViewTreeOwnersAvailable(AndroidComposeView.android.kt:1191) androidx.compose.ui.platform.WrappedComposition.setContent(Wrapper.android.kt:133) androidx.compose.ui.platform.WrappedComposition.onStateChanged(Wrapper.android.kt:183) androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.kt:314) androidx.lifecycle.LifecycleRegistry.addObserver(LifecycleRegistry.kt:192) androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:140) androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:133) androidx.compose.ui.platform.AndroidComposeView.onAttachedToWindow(AndroidComposeView.android.kt:1266) android.view.View.dispatchAttachedToWindow(View.java:22010) android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:4291) android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:4298) android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:4298) android.view.ViewGroup.addViewInner(ViewGroup.java:6108) android.view.ViewGroup.addView(ViewGroup.java:5884) com.facebook.react.views.view.ReactViewGroup.addView(ReactViewGroup.java:514) android.view.ViewGroup.addView(ViewGroup.java:5824) com.facebook.react.views.view.ReactClippingViewManager.addView(ReactClippingViewManager.java:38) com.facebook.react.views.view.ReactClippingViewManager.addView(ReactClippingViewManager.java:19) com.facebook.react.uimanager.NativeViewHierarchyManager.manageChildren(NativeViewHierarchyManager.java:533) com.swmansion.reanimated.layoutReanimation.ReanimatedNativeHierarchyManager.manageChildren(ReanimatedNativeHierarchyManager.java:300) com.facebook.react.uimanager.UIViewOperationQueue$ManageChildrenOperation.execute(UIViewOperationQueue.java:217) com.facebook.react.uimanager.UIViewOperationQueue$1.run(UIViewOperationQueue.java:926) com.facebook.react.uimanager.UIViewOperationQueue.flushPendingBatches(UIViewOperationQueue.java:1037) com.facebook.react.uimanager.UIViewOperationQueue.-$$Nest$mflushPendingBatches(Unknown Source:0) com.facebook.react.uimanager.UIViewOperationQueue$DispatchUIFrameCallback.doFrameGuarded(UIViewOperationQueue.java:1097) com.facebook.react.uimanager.GuardedFrameCallback.doFrame(GuardedFrameCallback.java:29) com.facebook.react.modules.core.ReactChoreographer$ReactChoreographerDispatcher.doFrame(ReactChoreographer.java:175) com.facebook.react.modules.core.ChoreographerCompat$FrameCallback$1.doFrame(ChoreographerCompat.java:85) android.view.Choreographer$CallbackRecord.run(Choreographer.java:1008) android.view.Choreographer.doCallbacks(Choreographer.java:809) android.view.Choreographer.doFrame(Choreographer.java:740) android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:995) android.os.Handler.handleCallback(Handler.java:938) android.os.Handler.dispatchMessage(Handler.java:99) android.os.Looper.loop(Looper.java:246) android.app.ActivityThread.main(ActivityThread.java:8550) java.lang.reflect.Method.invoke(Native Method) com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602) com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)**

mshmoustafa commented 2 weeks ago

@geoffcfchen we didn't fix anything related to this so I think it was just a broken cache, sandbox glitches, etc. It's common for that to happen in testing. I'll ask the mobile engineering team to look into that crash and report back what they say

joshdholtz commented 2 weeks ago

@geoffcfchen Hey! The multi-tier paywall isn't available until React Native version 8.0.0. Sorry about that! We will make it more clear in the dashboard and docs what SDK versions paywalls are available on.

geoffcfchen commented 2 weeks ago

@joshdholtz, Hey. Thanks for the information. Just to note that I am using "react-native-purchases": "8.0.1", "react-native-purchases-ui": "8.0.1" and although template 7 works on iOS, it does not work on Android (see the above crash log).

joshdholtz commented 2 weeks ago

@joshdholtz, Hey. Thanks for the information. Just to note that I am using "react-native-purchases": "8.0.1", "react-native-purchases-ui": "8.0.1" and although template 7 works on iOS, it does not work on Android (see the above crash log).

Ah, sorry! Coming back from being sick this weekend so not fully in it yet 🫠 Looking harder this time and will come back with something actually useful 😇

joshdholtz commented 2 weeks ago

@geoffcfchen Okay, now after really looking at the crash, it seems like you might not have the correct version of androidx.compose.animation 🤔 Template 7 uses androidx.compose.animation.AnimatedContent but its not able to find that...

Do you happen to know if you have this dependency pinned at a lower version? This should be found in Jetpack Compose version 1.3.0 and up

geoffcfchen commented 2 weeks ago

@joshdholtz, we are using Expo Managed Workflow right now (we do not have a plan to eject from Expo Managed Workflow yet), so we're somewhat restricted in how we can use native Android dependencies like androidx directly due to the managed workflow...

Follow up: Given this limitation, could you suggest a way to ensure compatibility with the Jetpack Compose version used in Expo? If not, are there specific versions of your SDK that might work better with Expo's setup? Or, if there's a way to bundle the correct version of androidx.compose.animation through a custom development client without fully ejecting, I'd appreciate any guidance on that.

geoffcfchen commented 1 week ago

Just to report here. After updating to the 8.1.0, the Android version works now.