Closed
Conversation
Generated by 🚫 Danger |
### Description Adds support for displaying virtual currency balances in the Customer Center. This mimics the design found in the iOS Customer Center as much as possible. It adds a list of virtual currency balances to the`RelevantPurchasesListView` and `NoActiveUserManagementView` views if: - The app has virtual currencies - The "Display virtual currency balances" toggle is enabled in the Customer Center configuration in the dashboard ### Changes - Adds `displayVirtualCurrencies` to the CustomerCenterConfig - Adds a list of virtual currency balances to the `RelevantPurchasesListView` and `NoActiveUserManagementView`. It displays a max of 4 virtual currencies. If there are >4 virtual currencies, it will display the 3 VCs with the highest balance, and show a "See all in-app currencies" button that navigates to a full VC balances screen - Adds a screen that displays all virtual currency balances. It refreshes the VC balances when this screen is loaded in case the balances have changed since they were last loaded. ### Testing - Tested manually - Added automated tests for the new view model functions ### Screenshots On the `RelevantPurchasesListView`, with just 2 virtual currencies (no "see all" button): <img width="300" alt="Screenshot 2025-09-05 at 2 12 25 PM" src="https://github.com/user-attachments/assets/f1ca5fbc-1beb-4a77-9d0d-8f729fd853e0" /> On the `RelevantPurchasesListView`, with just 5 virtual currencies ("see all" button is visible): <img width="300" alt="Screenshot 2025-09-05 at 2 17 12 PM" src="https://github.com/user-attachments/assets/2ce98cb0-2317-4a24-b22c-239308383ee6" /> VC Balances screen (accessed by tapping "See all in-app currencies" button) <img width="300" alt="Screenshot 2025-09-05 at 2 18 03 PM" src="https://github.com/user-attachments/assets/185b57c4-5738-48a5-94b5-25eaf10d8320" /> On the `NoActiveUserManagementView` screen: <img width="300" alt="Screenshot 2025-09-05 at 2 19 20 PM" src="https://github.com/user-attachments/assets/e5f5cc8d-e4c4-496d-b6f1-ca694569678b" />
<!-- Thank you for contributing to Purchases! Before pressing the "Create Pull Request" button, please provide the following: --> ### Checklist - [x] If applicable, unit tests - [ ] If applicable, create follow-up issues for `purchases-ios` and hybrids ### Motivation We will be supporting Video components in the Paywalls soon, to do that we need a good way to cache the large files to the device. ### Description This PR is a carbon copy of what I did in the iOS sdk recently. There are 2 cache mechanisms. 1. A deferred value cache—This essentially allows us to reuse the same coroutine job across multiple call-sites. That way we can prefetch and move on. When the paywall is launched the same download can be awaited when it's partially completed. Until it finishes, we can show the fallback image that should download far faster. 2. The file repository—This knows when to fetch the data from the web or when to read it from the file system. There are likely things I've missed here. But there are a couple of important things to note. a. We are not currently hosting the videos in our ecosystem so a checksum isn't realistic in our v1 b. I'm good at Kotlin, but not at all experienced with Android SDK development . Totally open to feedback.
…2671) Bumps [fastlane-plugin-revenuecat_internal](https://github.com/RevenueCat/fastlane-plugin-revenuecat_internal) from `7d97553` to `489faef`. <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/RevenueCat/fastlane-plugin-revenuecat_internal/commit/489faef4846f2a2fa8fc13f79f94631c6dda95a1"><code>489faef</code></a> Add OTP warning to changelogs (<a href="https://redirect.github.com/RevenueCat/fastlane-plugin-revenuecat_internal/issues/81">#81</a>)</li> <li>See full diff in <a href="https://github.com/RevenueCat/fastlane-plugin-revenuecat_internal/compare/7d97553e9c5baabcd18286f03d8034797a27dd64...489faef4846f2a2fa8fc13f79f94631c6dda95a1">compare view</a></li> </ul> </details> <br /> Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…2673) Bumps [fastlane-plugin-revenuecat_internal](https://github.com/RevenueCat/fastlane-plugin-revenuecat_internal) from `489faef` to `a6dc551`. <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/RevenueCat/fastlane-plugin-revenuecat_internal/commit/a6dc5513a0e81217913b32778cd627821b06e2b8"><code>a6dc551</code></a> Strips new lines from versions (<a href="https://redirect.github.com/RevenueCat/fastlane-plugin-revenuecat_internal/issues/82">#82</a>)</li> <li>See full diff in <a href="https://github.com/RevenueCat/fastlane-plugin-revenuecat_internal/compare/489faef4846f2a2fa8fc13f79f94631c6dda95a1...a6dc5513a0e81217913b32778cd627821b06e2b8">compare view</a></li> </ul> </details> <br /> Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
### Description As a follow-up from #2624. That PR fixed embedded font families when they were in the resources folder, as it's common in android. However, that didn't fix the issue when fonts are in the assets folder. For example, when being added in React native when using `npx react-native-asset`. This will fix that so font families load correctly when using the assets folder.
Bumps [rexml](https://github.com/ruby/rexml) from 3.4.1 to 3.4.2. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/ruby/rexml/releases">rexml's releases</a>.</em></p> <blockquote> <h2>REXML 3.4.2 - 2025-08-26</h2> <h3>Improvement</h3> <ul> <li> <p>Improved performance.</p> <ul> <li><a href="https://redirect.github.com/ruby/rexml/issues/244">GH-244</a></li> <li><a href="https://redirect.github.com/ruby/rexml/issues/245">GH-245</a></li> <li><a href="https://redirect.github.com/ruby/rexml/issues/246">GH-246</a></li> <li><a href="https://redirect.github.com/ruby/rexml/issues/249">GH-249</a></li> <li><a href="https://redirect.github.com/ruby/rexml/issues/256">GH-256</a></li> <li>Patch by NAITOH Jun</li> </ul> </li> <li> <p>Raise appropriate exception when failing to match start tag in DOCTYPE</p> <ul> <li><a href="https://redirect.github.com/ruby/rexml/issues/247">GH-247</a></li> <li>Patch by NAITOH Jun</li> </ul> </li> <li> <p>Deprecate accepting array as an element in XPath.match, first and each</p> <ul> <li><a href="https://redirect.github.com/ruby/rexml/issues/252">GH-252</a></li> <li>Patch by tomoya ishida</li> </ul> </li> <li> <p>Don't call needless encoding_updated</p> <ul> <li><a href="https://redirect.github.com/ruby/rexml/issues/259">GH-259</a></li> <li>Patch by Sutou Kouhei</li> </ul> </li> <li> <p>Reuse XPath::match</p> <ul> <li><a href="https://redirect.github.com/ruby/rexml/issues/263">GH-263</a></li> <li>Patch by pboling</li> </ul> </li> <li> <p>Cache redundant calls for doctype</p> <ul> <li><a href="https://redirect.github.com/ruby/rexml/issues/264">GH-264</a></li> <li>Patch by pboling</li> </ul> </li> <li> <p>Use Safe Navigation (&.) from Ruby 2.3</p> <ul> <li><a href="https://redirect.github.com/ruby/rexml/issues/265">GH-265</a></li> <li>Patch by pboling</li> </ul> </li> <li> <p>Remove redundant return statements</p> <ul> <li><a href="https://redirect.github.com/ruby/rexml/issues/266">GH-266</a></li> <li>Patch by pboling</li> </ul> </li> <li> <p>Added XML declaration check & Source#skip_spaces method</p> <ul> <li><a href="https://redirect.github.com/ruby/rexml/issues/282">GH-282</a></li> <li>Patch by NAITOH Jun</li> <li>Reported by Sofi Aberegg</li> </ul> </li> </ul> <h3>Fixes</h3> <ul> <li>Fix docs typo <ul> <li><a href="https://redirect.github.com/ruby/rexml/issues/248">GH-248</a></li> <li>Patch by James Coleman</li> </ul> </li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/ruby/rexml/blob/master/NEWS.md">rexml's changelog</a>.</em></p> <blockquote> <h2>3.4.2 - 2025-08-26 {#version-3-4-2}</h2> <h3>Improvement</h3> <ul> <li> <p>Improved performance.</p> <ul> <li><a href="https://redirect.github.com/ruby/rexml/issues/244">GH-244</a></li> <li><a href="https://redirect.github.com/ruby/rexml/issues/245">GH-245</a></li> <li><a href="https://redirect.github.com/ruby/rexml/issues/246">GH-246</a></li> <li><a href="https://redirect.github.com/ruby/rexml/issues/249">GH-249</a></li> <li><a href="https://redirect.github.com/ruby/rexml/issues/256">GH-256</a></li> <li>Patch by NAITOH Jun</li> </ul> </li> <li> <p>Raise appropriate exception when failing to match start tag in DOCTYPE</p> <ul> <li><a href="https://redirect.github.com/ruby/rexml/issues/247">GH-247</a></li> <li>Patch by NAITOH Jun</li> </ul> </li> <li> <p>Deprecate accepting array as an element in XPath.match, first and each</p> <ul> <li><a href="https://redirect.github.com/ruby/rexml/issues/252">GH-252</a></li> <li>Patch by tomoya ishida</li> </ul> </li> <li> <p>Don't call needless encoding_updated</p> <ul> <li><a href="https://redirect.github.com/ruby/rexml/issues/259">GH-259</a></li> <li>Patch by Sutou Kouhei</li> </ul> </li> <li> <p>Reuse XPath::match</p> <ul> <li><a href="https://redirect.github.com/ruby/rexml/issues/263">GH-263</a></li> <li>Patch by pboling</li> </ul> </li> <li> <p>Cache redundant calls for doctype</p> <ul> <li><a href="https://redirect.github.com/ruby/rexml/issues/264">GH-264</a></li> <li>Patch by pboling</li> </ul> </li> <li> <p>Use Safe Navigation (&.) from Ruby 2.3</p> <ul> <li><a href="https://redirect.github.com/ruby/rexml/issues/265">GH-265</a></li> <li>Patch by pboling</li> </ul> </li> <li> <p>Remove redundant return statements</p> <ul> <li><a href="https://redirect.github.com/ruby/rexml/issues/266">GH-266</a></li> <li>Patch by pboling</li> </ul> </li> <li> <p>Added XML declaration check & Source#skip_spaces method</p> <ul> <li><a href="https://redirect.github.com/ruby/rexml/issues/282">GH-282</a></li> <li>Patch by NAITOH Jun</li> <li>Reported by Sofi Aberegg</li> </ul> </li> </ul> <h3>Fixes</h3> <ul> <li>Fix docs typo <ul> <li><a href="https://redirect.github.com/ruby/rexml/issues/248">GH-248</a></li> <li>Patch by James Coleman</li> </ul> </li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/ruby/rexml/commit/f36916fe1c66b8cdc1fe482263115625e084d8fe"><code>f36916f</code></a> Add 3.4.2 entry (<a href="https://redirect.github.com/ruby/rexml/issues/284">#284</a>)</li> <li><a href="https://github.com/ruby/rexml/commit/5859bdeac792687eaf93d8e8f0b7e3c1e2ed5c23"><code>5859bde</code></a> Added XML declaration check & <code>Source#skip_spaces</code> method (<a href="https://redirect.github.com/ruby/rexml/issues/282">#282</a>)</li> <li><a href="https://github.com/ruby/rexml/commit/1d876e3bf658b7b4ec7c3372867521695e8eb023"><code>1d876e3</code></a> Bump actions/checkout from 4 to 5 (<a href="https://redirect.github.com/ruby/rexml/issues/283">#283</a>)</li> <li><a href="https://github.com/ruby/rexml/commit/c87bda8bb8773da7e5a0faf9f16ff165eb052a35"><code>c87bda8</code></a> Remove ostruct from dev deps (<a href="https://redirect.github.com/ruby/rexml/issues/281">#281</a>)</li> <li><a href="https://github.com/ruby/rexml/commit/c60ae027a3c20f359fdf76fa41ae64d22313f482"><code>c60ae02</code></a> Remove bundler from dev deps (<a href="https://redirect.github.com/ruby/rexml/issues/277">#277</a>)</li> <li><a href="https://github.com/ruby/rexml/commit/9b084d78708638cedff54743edc0907c4bd6574a"><code>9b084d7</code></a> Fix & Deprecate REXML::Text#text_indent (<a href="https://redirect.github.com/ruby/rexml/issues/275">#275</a>)</li> <li><a href="https://github.com/ruby/rexml/commit/04a589a61bf4e366abee8764ee74b03f4aecc4aa"><code>04a589a</code></a> Fix a bug that XPath can't be used for no document element (<a href="https://redirect.github.com/ruby/rexml/issues/268">#268</a>)</li> <li><a href="https://github.com/ruby/rexml/commit/66232eaf680d0937ae59bea285cdb8e4d3d88a93"><code>66232ea</code></a> Remove redundant return statements (<a href="https://redirect.github.com/ruby/rexml/issues/266">#266</a>)</li> <li><a href="https://github.com/ruby/rexml/commit/63f3e9772595a64b036953f0ab026d2ea5560a3b"><code>63f3e97</code></a> Use Safe Navigation (&.) from Ruby 2.3 (<a href="https://redirect.github.com/ruby/rexml/issues/265">#265</a>)</li> <li><a href="https://github.com/ruby/rexml/commit/d427fc5914fcc17d7247c5ff9099ee38639d6702"><code>d427fc5</code></a> Avoid redundant calls for doctype (<a href="https://redirect.github.com/ruby/rexml/issues/264">#264</a>)</li> <li>Additional commits viewable in <a href="https://github.com/ruby/rexml/compare/v3.4.1...v3.4.2">compare view</a></li> </ul> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/RevenueCat/purchases-android/network/alerts). </details> Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…2683) Bumps [fastlane-plugin-revenuecat_internal](https://github.com/RevenueCat/fastlane-plugin-revenuecat_internal) from `a6dc551` to `401d148`. <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/RevenueCat/fastlane-plugin-revenuecat_internal/commit/401d1486a070907c8ecaac3fcaa10e8f2b8cc91b"><code>401d148</code></a> Add <code>CheckGithubAuthenticationAction</code> to check rate limits (<a href="https://redirect.github.com/RevenueCat/fastlane-plugin-revenuecat_internal/issues/83">#83</a>)</li> <li>See full diff in <a href="https://github.com/RevenueCat/fastlane-plugin-revenuecat_internal/compare/a6dc5513a0e81217913b32778cd627821b06e2b8...401d1486a070907c8ecaac3fcaa10e8f2b8cc91b">compare view</a></li> </ul> </details> <br /> Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Fix multiple cases: Broken trials when more than one period unit: **Before (P2M):** `First 1 month free, then $3.99/mth` **After:** `First 2 months free, then $3.99/mth` **Before (P3D):** `First 1 day free, then $3.99/mth` **After:** `First 3 days free, then $3.99/mth` Broken discounted recurring price : **Before (2 P6M):** `$0.99 during 2 months, then $3.99/6 mths` **After:** `$0.99/6 mths for 2 periods, then $3.99/6 mths` This case was not broken but it's more clear now: **Before (2 P1M):** `$0.99 during 2 months, then $3.99/mth` **After:** `$0.99/mth for 2 periods, then $3.99/mth` Single discounted payment when more than one period unit: **Before (P6M):** `1 month for $1.99, then $3.99/mth` **After:** `6 months for $1.99, then $3.99/mth` **Before (P6Y):** `1 year for $1.99, then $3.99/mth` **After:** `6 years for $1.99, then $3.99/mth` Three phases were broken as well. Some examples: **Before (P2M trial, 1M single payment):** `Try 1 month for free, then 1 month for $1.99, and $3.99/mth thereafter` **After:** `Try 2 months for free, then 1 month for $1.99, and $3.99/mth thereafter` **Before (P3D trial, 1M single payment):** `Try 1 day for free, then 1 month for $1.99, and $3.99/mth thereafter` **After:** `Try 3 days for free, then 1 month for $1.99, and $3.99/mth thereafter` **Before (P2M trial, 6M single payment):** `Try 1 month for free, then 1 month for $1.99, and $3.99/mth thereafter` **After:** `Try 2 months for free, then 6 months for $1.99, and $3.99/mth thereafter` **Before (P3D trial, 6M single payment):** `Try 1 day for free, then 1 month for $1.99, and $3.99/mth thereafter` **After:** `Try 3 days for free, then 6 months for $1.99, and $3.99/mth thereafter` **Before (P2M trial, 2 months discounted):** `Try 1 month for free, then $0.99 during 2 months, and $3.99/mth thereafter` **After:** `Try 2 months for free, then $0.99/mth for 2 periods, and $3.99/mth thereafter` **Before (P2M trial, 2 6-month discounted):** `Try 1 month for free, then $0.99 during 2 months, and $3.99/6 mths thereafter` **After:** `Try 2 months for free, then $0.99/6 mths for 2 periods, and $3.99/6 mths thereafter`
This PR removes the ENABLE_SIMULATED_STORE build config to enable the Test Store functionality in the SDK # Conflicts: # purchases/src/main/kotlin/com/revenuecat/purchases/PurchasesOrchestrator.kt
Since Kotlin version 2.0.0, the `kotlinCompilerExtensionVersion` is no longer required to be configured in composeOptions and can be removed: https://android-developers.googleblog.com/2024/04/jetpack-compose-compiler-moving-to-kotlin-repository.html
### Motivation Reimplement placeholder with `Modifier.Node` for better UI performance. ### Description As follows the [official documentation](https://developer.android.com/develop/ui/compose/custom-modifiers#implement-custom), the `composed` API isn't recommended anymore because of the performance issue. > Note: There is another API for creating custom modifiers, [composed {}](https://developer.android.com/reference/kotlin/androidx/compose/ui/Modifier#(androidx.compose.ui.Modifier).composed(kotlin.Function1,kotlin.Function1)). This API is no longer recommended due to the performance issues it created. Modifier.Node was designed from the ground up to be far more performant than composed modifiers. For more details on the problems with composed modifiers, see the Android Dev Summit talk [Compose Modifiers Deep Dive](https://www.youtube.com/watch?v=BjGX2RftXsU). The result:  --------- Co-authored-by: JayShortway <[email protected]>
Reported in #2681 - I added some opacity to the Expired badge, so it shows some contrast against the background, in case it's the same color as `onSurface`. This is the same for Cancelled and Active. - Added previews for dark mode. - Improved the border of lifetime, so it's based off the `onSurface` color with an opacity and not a hardcoded color <img width="310" height="99" alt="Screenshot 2025-09-29 at 16 33 14" src="https://github.com/user-attachments/assets/1cf97c1b-f9aa-47b7-ad5f-206df9f2241c" /> <img width="307" height="149" alt="Screenshot 2025-09-29 at 16 35 20" src="https://github.com/user-attachments/assets/16853aa1-d020-4ab4-8bc9-10b98cbf1d83" /> <img width="312" height="100" alt="Screenshot 2025-09-29 at 16 35 51" src="https://github.com/user-attachments/assets/55355c7f-8c19-434a-b62d-ba16b09707e0" />
…2697) Bumps [fastlane-plugin-revenuecat_internal](https://github.com/RevenueCat/fastlane-plugin-revenuecat_internal) from `401d148` to `7508f17`. <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/RevenueCat/fastlane-plugin-revenuecat_internal/commit/7508f173ab5224816b52fdfaf8efe5d433c471a1"><code>7508f17</code></a> Add missing GitHub auth in some actions (<a href="https://redirect.github.com/RevenueCat/fastlane-plugin-revenuecat_internal/issues/88">#88</a>)</li> <li><a href="https://github.com/RevenueCat/fastlane-plugin-revenuecat_internal/commit/1593f78d0b9b24b48238337666183e3ba82f848e"><code>1593f78</code></a> Add <code>current_version</code> parameter to <code>DetermineNextVersionUsingLabelsAction</code> (<a href="https://redirect.github.com/RevenueCat/fastlane-plugin-revenuecat_internal/issues/87">#87</a>)</li> <li><a href="https://github.com/RevenueCat/fastlane-plugin-revenuecat_internal/commit/e1c0e045dfef42a8a7c6a4abc6458ed1b228fd4a"><code>e1c0e04</code></a> Use correct <code>GITHUB_TOKEN</code> (<a href="https://redirect.github.com/RevenueCat/fastlane-plugin-revenuecat_internal/issues/86">#86</a>)</li> <li><a href="https://github.com/RevenueCat/fastlane-plugin-revenuecat_internal/commit/24d8edac49bf1f7e09ffe4c184038536938077e7"><code>24d8eda</code></a> Allow automatic bump in older majors (<a href="https://redirect.github.com/RevenueCat/fastlane-plugin-revenuecat_internal/issues/85">#85</a>)</li> <li><a href="https://github.com/RevenueCat/fastlane-plugin-revenuecat_internal/commit/6d539b31901a6e076d53e45de928f33582f994a2"><code>6d539b3</code></a> Consider <code>next_version</code> to create changelog (<a href="https://redirect.github.com/RevenueCat/fastlane-plugin-revenuecat_internal/issues/84">#84</a>)</li> <li>See full diff in <a href="https://github.com/RevenueCat/fastlane-plugin-revenuecat_internal/compare/401d1486a070907c8ecaac3fcaa10e8f2b8cc91b...7508f173ab5224816b52fdfaf8efe5d433c471a1">compare view</a></li> </ul> </details> <br /> Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
### Checklist - [x] If applicable, unit tests - [x] If applicable, create follow-up issues for `purchases-android` and hybrids ### Motivation We are adding a native RC <-> Airbridge integration. The backend and frontend changes for the integration have been released. On the SDK side, we need a method to set the airbridge device ID captured by [Airbridge SDK](https://help.airbridge.io/en/developers/fetching-guide-for-android-sdk). ### Description Expose a method so developers can set an Airbridge Device ID after capturing it from [Airbridge SDK](https://help.airbridge.io/en/developers/fetching-guide-for-android-sdk) This works exactly the same way as the existing Kochava integration && `setKochavaDeviceID`
## Description Adds the `tab_id`, `id` and `default_tab_id` properties to the `TabsComponent` model where necessary. These new properties are not used yet. This makes the same changes to the JSON models as these iOS PRs: - RevenueCat/purchases-ios#5209 - RevenueCat/purchases-ios#5430 --------- Co-authored-by: Franco Correa <[email protected]>
### Motivation It's useful to be notified when some changes happen. Follow-up of RevenueCat/purchases-ios#5541 ### Description - Add customer center to some paths
…2703) ### Checklist - [x] If applicable, unit tests - [ ] If applicable, create follow-up issues for `purchases-ios` and hybrids ### Motivation <!-- Why is this change required? What problem does it solve? --> Test named "GooglePlayServicesNotAvailableException when calling getDeviceIdentifiers" is testing GooglePlayServicesRepairableException instead of GooglePlayServicesNotAvailableException. GooglePlayServicesRepairableException is already tested in the next test. <!-- Please link to issues following this format: Resolves #999999 --> ### Description <!-- Describe your changes in detail --> Test named "GooglePlayServicesNotAvailableException when calling getDeviceIdentifiers" is testing GooglePlayServicesRepairableException instead of GooglePlayServicesNotAvailableException. GooglePlayServicesRepairableException is already tested in the next test. This was contributed by @nikit19 in #2674 Co-authored-by: Nikit Bhandari <[email protected]> Co-authored-by: Antonio Pallares <[email protected]>
…tomEntitlementComputationSample (#2701) Revert kotlinCompilerExtensionVersion for MagicWeatherCompose and CustomEntitlementComputationSample since they use Kotlin 1.9.x. Thanks for finding this out, @JayShortway 👍 #2691
## Summary - Updates fastlane-plugin-revenuecat_internal to revision e555afbcf227f82883e26d72c4386873e41dc56d 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude <[email protected]>
<!-- Thank you for contributing to Purchases! Before pressing the "Create Pull Request" button, please provide the following: --> > [!IMPORTANT] > This is behind a compiler flag. When it merges it will be dark code. There is a follow up PR planned to implement a > Checksum and more robust file storage to better handle the load on device memory https://github.com/user-attachments/assets/6a6fd861-e243-4216-a8e2-272e6c7d3e28 > [!TIP] > To test this, run PR 6173 in the revenue cat app ### Checklist - [ ] If applicable, unit tests - [ ] If applicable, create follow-up issues for `purchases-ios` and hybrids ### Motivation <!-- Why is this change required? What problem does it solve? --> <!-- Please link to issues following this format: Resolves #999999 --> We have requests for video support. ### Description <!-- Describe your changes in detail --> <!-- Please describe in detail how you tested your changes --> Creates a video component that uses the native MediaPlayer under the hood. It supports autoplay, looping, muting audio, showing playback controls, and content scale overrides like fill while retaining the aspect ratio _(which was surprisingly the hardest part)_ # Conflicts: # purchases/src/main/kotlin/com/revenuecat/purchases/paywalls/components/VideoComponent.kt # purchases/src/test/java/com/revenuecat/purchases/paywalls/components/VideoComponentTests.kt # ui/revenuecatui/src/main/kotlin/com/revenuecat/purchases/ui/revenuecatui/components/style/StyleFactory.kt
We believe this scenario can deadlock: - `Purchases.logOut()` , acquires `IdentityManager` lock - Calls `subscriberAttributesManager.synchronizeSubscriberAttributesForAllUsers()` which does some stuff and actually has a `waitUntilIdle()`. It may need `PurchasesOrchestrator` lock for the operations to complete, but it might be held by the next step (`onAppForegrounded`) - `onAppForegrounded` calls `allowSharingPlayStoreAccount` , acquires `PurchasesOrchestrator` lock - it tries to call `identityManager.currentUserIsAnonymous()` but `IdentityManager` is locked - at the same time `onBillingSetupFinished` and calls `PurchasesOrchestrator.getAllowSharingPlayStoreAccount` , which is locked on `PurchasesOrchestrator` So basically, both `PurchasesOrchestrator` and `IdentityManager` get locked and never complete because they depend on each other I think this nested lock situation (holds `PurchasesOrchestrator` then IdentityManager) can be problematic: ``` @synchronized get() = state.allowSharingPlayStoreAccount ?: identityManager.currentUserIsAnonymous() ``` This is the reported stacktrace: main (onBillingSetupFinished) ``` "main" tid=1 Blocked at com.revenuecat.purchases.PurchasesOrchestrator.getAllowSharingPlayStoreAccount (unavailable) at com.revenuecat.purchases.PurchasesOrchestrator$3.onConnected (PurchasesOrchestrator.kt:207) at com.revenuecat.purchases.google.BillingWrapper.onBillingSetupFinished$lambda$34 (BillingWrapper.kt:594) ``` pool-5-thread-1 (onAppForegrounded) ``` "pool-5-thread-1" tid=52 Blocked at com.revenuecat.purchases.identity.IdentityManager.currentUserIsAnonymous (unavailable) at com.revenuecat.purchases.PurchasesOrchestrator.getAllowSharingPlayStoreAccount (PurchasesOrchestrator.kt:189) at com.revenuecat.purchases.PurchasesOrchestrator$onAppForegrounded$3.invoke (PurchasesOrchestrator.kt:263) ``` CapacitorPlugins (logOut) ``` "CapacitorPlugins" tid=37 Blocked at com.revenuecat.purchases.PurchasesOrchestrator$logOut$1.invoke (PurchasesOrchestrator.kt:630) at com.revenuecat.purchases.PurchasesOrchestrator$logOut$1.invoke (PurchasesOrchestrator.kt:626) at com.revenuecat.purchases.identity.IdentityManager$logOut$2.invoke (IdentityManager.kt:161) at com.revenuecat.purchases.identity.IdentityManager$logOut$2.invoke (IdentityManager.kt:158) at com.revenuecat.purchases.subscriberattributes.SubscriberAttributesManager$synchronizeSubscriberAttributesForAllUsers$1.invoke (SubscriberAttributesManager.kt:69) at com.revenuecat.purchases.subscriberattributes.SubscriberAttributesManager$synchronizeSubscriberAttributesForAllUsers$1.invoke (SubscriberAttributesManager.kt:60) at com.revenuecat.purchases.subscriberattributes.SubscriberAttributesManager$ObtainDeviceIdentifiersObservable.waitUntilIdle (SubscriberAttributesManager.kt:233) at com.revenuecat.purchases.subscriberattributes.SubscriberAttributesManager.synchronizeSubscriberAttributesForAllUsers (SubscriberAttributesManager.kt:60) at com.revenuecat.purchases.identity.IdentityManager.logOut (IdentityManager.kt:158) ```
Before the next release is cut, correct the opt in so we don't show breaking changes when I finish up the video component work
…2708) Bumps [fastlane-plugin-revenuecat_internal](https://github.com/RevenueCat/fastlane-plugin-revenuecat_internal) from `e555afb` to `a8770fd`. <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/RevenueCat/fastlane-plugin-revenuecat_internal/commit/a8770fd8fde3263444bc2881812b6f737b6a705b"><code>a8770fd</code></a> nit: add only one newline when inserting changelog latest (<a href="https://redirect.github.com/RevenueCat/fastlane-plugin-revenuecat_internal/issues/94">#94</a>)</li> <li><a href="https://github.com/RevenueCat/fastlane-plugin-revenuecat_internal/commit/db640e8eec35ef25db152097dd737e0b36992682"><code>db640e8</code></a> Insert changelog of older version release in main (<a href="https://redirect.github.com/RevenueCat/fastlane-plugin-revenuecat_internal/issues/89">#89</a>)</li> <li>See full diff in <a href="https://github.com/RevenueCat/fastlane-plugin-revenuecat_internal/compare/e555afbcf227f82883e26d72c4386873e41dc56d...a8770fd8fde3263444bc2881812b6f737b6a705b">compare view</a></li> </ul> </details> <br /> Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…2712) Bumps [fastlane-plugin-revenuecat_internal](https://github.com/RevenueCat/fastlane-plugin-revenuecat_internal) from `a8770fd` to `3f7fffc`. <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/RevenueCat/fastlane-plugin-revenuecat_internal/commit/3f7fffc2e3111e92d2ad86e7c2644743bde69119"><code>3f7fffc</code></a> Use <code>pr:changelog_ignore</code> for old-major-changelog update PRs (<a href="https://redirect.github.com/RevenueCat/fastlane-plugin-revenuecat_internal/issues/96">#96</a>)</li> <li><a href="https://github.com/RevenueCat/fastlane-plugin-revenuecat_internal/commit/b35cae09e9be5e5272c41f7c5d8d24f246f697ad"><code>b35cae0</code></a> Add <code>pr:changelog_ignore</code> label (<a href="https://redirect.github.com/RevenueCat/fastlane-plugin-revenuecat_internal/issues/95">#95</a>)</li> <li>See full diff in <a href="https://github.com/RevenueCat/fastlane-plugin-revenuecat_internal/compare/a8770fd8fde3263444bc2881812b6f737b6a705b...3f7fffc2e3111e92d2ad86e7c2644743bde69119">compare view</a></li> </ul> </details> <br /> Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
### Description Added new test app to run E2E tests with the test store. I did the minimal to make it work, so no view models, and no great navigation system... but it's usable for automated testing. The screen/page structure looks like: - `MainPage` is the root/initial page, that has 2 tabs `CustomerInfoPage` and `OfferingsPage`. - From the `OfferingsPage`, you can navigate to `OfferingScreen`. - From the `OfferingScreen` you can navigate to `PackageScreen`. This is the first part to get #2711 in
### Description This adds a new value to the `Store` enum: `TEST_STORE`. This will be the value used when using RevenueCat's test store. # Conflicts: # purchases/src/main/kotlin/com/revenuecat/purchases/EntitlementInfo.kt
### Motivation - Add a per-view CustomerCenterListener hook so hybrid apps can override callbacks without relying solely on the global Purchases listener. - Ensure the non-Compose API mirrors PaywallView. - Provide a working sample and API coverage so partners can see and compile against the new surface. - Needed for RevenueCat/purchases-flutter#1476 and RevenueCat/react-native-purchases#1411 ### Description - CustomerCenterView now installs an internal proxy listener, accepts an optional listener via constructor or setter, and keeps the global listener as the fallback. - Updated the Paywall Tester app: the App Info screen launches a full-screen dialog that hosts CustomerCenterView, logging/toasting to differentiate the per-view listener from the global handler.
### Description We don't want to use offline entitlements for the test store, since the store in the client won't actually return any purchases, so it's kinda useless.
…2721) Bumps [fastlane-plugin-revenuecat_internal](https://github.com/RevenueCat/fastlane-plugin-revenuecat_internal) from `3f7fffc` to `25c7fb8`. <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/RevenueCat/fastlane-plugin-revenuecat_internal/commit/25c7fb83d3e6f590a7130547f75135abda9f86a2"><code>25c7fb8</code></a> Fix make_latest release logic (<a href="https://redirect.github.com/RevenueCat/fastlane-plugin-revenuecat_internal/issues/98">#98</a>)</li> <li>See full diff in <a href="https://github.com/RevenueCat/fastlane-plugin-revenuecat_internal/compare/3f7fffc2e3111e92d2ad86e7c2644743bde69119...25c7fb83d3e6f590a7130547f75135abda9f86a2">compare view</a></li> </ul> </details> <br /> Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
### Description Adds a new error code to be used when simulating purchase errors in the test store.
…sage for large file downloads (#2717) <!-- Thank you for contributing to Purchases! Before pressing the "Create Pull Request" button, please provide the following: --> ### Checklist - [x] If applicable, unit tests - [ ] If applicable, create follow-up issues for `purchases-ios` and hybrids ### Motivation <!-- Why is this change required? What problem does it solve? --> <!-- Please link to issues following this format: Resolves #999999 --> After getting the last video component PR up, the team had some great feedback, specifically that there was no way to prevent the corruption of a file before saving it and that storing the whole file in memory could be problematic when dealing with larger files like videos. So this PR sought to solve those issues. Description This PR does several things: - Stores the file using the checksum value if present -- ensuring that we get a cache miss if the checksum value changes - Streams the download into a temporary file to optimize memory usage for very large downloads (as opposed to keeping the whole thing in memory) - Only saves the data to the cache directory if the checksum matches the dowloaded content - Stops the cache warming of the videos to save on costs - we will be adding a flag in our backend to denote which paywalls can prewarm videos in the future - Removes the static object responsible for state management and replaces it with a view model to survive rotation ### Description <!-- Describe your changes in detail --> <!-- Please describe in detail how you tested your changes --> # Conflicts: # purchases/src/main/kotlin/com/revenuecat/purchases/paywalls/components/properties/VideoUrls.kt
### Description Add test store maestro test https://github.com/user-attachments/assets/11d3eafa-3498-4862-8354-e3744b079c5a
…material3 1.4.0 (#2727) It looks like material3 1.4.0 pulled the dependency from material-icons-core (release notes [here](https://developer.android.com/jetpack/androidx/releases/compose-material3#compose_material3_version_14_2)). We do depend transitively on version 1.3.0, which has the dependency, but if your app is overriding that to 1.4.0, the app will crash with: ``` Fatal Exception: java.lang.NoClassDefFoundError: Failed resolution of: Landroidx/compose/material/icons/Icons; at com.revenuecat.purchases.ui.revenuecatui.customercenter.InternalCustomerCenterKt$CustomerCenterNavigationIcon$2.invoke(InternalCustomerCenter.kt:355) ```
## Description Adds experimental APIs providing the storefront country as `Locale` instead of as 2-letter code. This allows developers more flexibility in handling this information. Relates to [SDK-4119](https://linear.app/revenuecat/issue/SDK-4119/consolidate-storefront-format-between-ios-and-android). # Conflicts: # purchases/src/defaults/kotlin/com/revenuecat/purchases/Purchases.kt
e20b23b to
187db29
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
RevenueCat SDK
Note
This release brings all non-breaking changes between SDK versions 9.6.0 and 9.11.0 to major 8, so developers that don't/can't use major 9, can still get the latest updates. meant to be bought only once, for example, lifetime subscriptions.
✨ New Features
storefrontLocaleAPIs. (Adds new experimentalstorefrontLocaleAPIs. #2726) via JayShortway (@JayShortway)🐞 Bugfixes
allowSharingPlayStoreAccount(Fix deadlock inallowSharingPlayStoreAccount#2707) via Cesar de la Vega (@vegaro)RevenueCatUI SDK
Paywallv2
✨ New Features
launchandlaunchIfNeededto Java (ExposelaunchandlaunchIfNeededto Java #2695) via Cesar de la Vega (@vegaro)🐞 Bugfixes
Customer Center
✨ New Features
🐞 Bugfixes
NoClassDefFoundErrorwhen using Material 1.4.0 (Fixes more Icons crashing withNoClassDefFoundErrorwhen using Material 1.4.0 #2732) via Cesar de la Vega (@vegaro)NoClassDefFoundErrorcrash findingIconscaused by material3 1.4.0 (Fix potentialNoClassDefFoundErrorcrash findingIconscaused by material3 1.4.0 #2727) via Cesar de la Vega (@vegaro)🔄 Other Changes
TestStoreSimulatedPurchaseErrorerror code (AddTestStoreSimulatedPurchaseErrorerror code #2716) via Toni Rico (@tonidero)3f7fffcto25c7fb8(Bump fastlane-plugin-revenuecat_internal from3f7fffcto25c7fb8#2721) via dependabot[bot] (@dependabot[bot])a8770fdto3f7fffc(Bump fastlane-plugin-revenuecat_internal froma8770fdto3f7fffc#2712) via dependabot[bot] (@dependabot[bot])e555afbtoa8770fd(Bump fastlane-plugin-revenuecat_internal frome555afbtoa8770fd#2708) via dependabot[bot] (@dependabot[bot])TabsComponent. (Adds new tab ID properties toTabsComponent. #2577) via JayShortway (@JayShortway)401d148to7508f17(Bump fastlane-plugin-revenuecat_internal from401d148to7508f17#2697) via dependabot[bot] (@dependabot[bot])a6dc551to401d148(Bump fastlane-plugin-revenuecat_internal froma6dc551to401d148#2683) via dependabot[bot] (@dependabot[bot])489faeftoa6dc551(Bump fastlane-plugin-revenuecat_internal from489faeftoa6dc551#2673) via dependabot[bot] (@dependabot[bot])7d97553to489faef(Bump fastlane-plugin-revenuecat_internal from7d97553to489faef#2671) via dependabot[bot] (@dependabot[bot])