Skip to content

Release/8.25.0#2737

Closed
vegaro wants to merge 38 commits intoprevious-majorfrom
release/8.25.0
Closed

Release/8.25.0#2737
vegaro wants to merge 38 commits intoprevious-majorfrom
release/8.25.0

Conversation

@vegaro
Copy link
Copy Markdown
Member

@vegaro vegaro commented Oct 15, 2025

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

🐞 Bugfixes

RevenueCatUI SDK

Paywallv2

✨ New Features

🐞 Bugfixes

Customer Center

✨ New Features

🐞 Bugfixes

🔄 Other Changes

@RevenueCat-Danger-Bot
Copy link
Copy Markdown

1 Error
🚫 Label the PR using one of the change type labels. If you are not sure which label to use, choose pr:other.
Label Description
pr:feat A new feature. Use along with pr:breaking to force a major release.
pr:fix A bug fix. Use along with pr:force_minor to force a minor release.
pr:other Other changes. Catch-all for anything that doesn't fit the above categories. Releases that only contain this label will not be released. Use along with pr:force_patch, or pr:force_minor to force a patch or minor release.
pr:RevenueCatUI Use along any other tag to mark a PR that only contains RevenueCatUI changes
pr:next_release Preparing a new release
pr:dependencies Updating a dependency
pr:phc_dependencies Updating purchases-hybrid-common dependency
pr:changelog_ignore The PR will not be included in the changelog. This label doesn't determine the type of bump of the version and must be combined with pr:feat, pr:fix or pr:other.

Generated by 🚫 Danger

fire-at-will and others added 29 commits October 15, 2025 15:59
### 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 (&amp;.) 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 &amp; 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 (&amp;.) 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 &amp; 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 &amp; <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 &amp; 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 (&amp;.) 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 />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=rexml&package-manager=bundler&previous-version=3.4.1&new-version=3.4.2)](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:


![screenshot](https://github.com/user-attachments/assets/795424ec-723b-4c17-b281-bd7b54363269)

---------

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.
dependabot bot and others added 9 commits October 15, 2025 16:29
…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
…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
…rial 1.4.0 (#2732)

#2727 fixed some Icons, but I somehow missed some other `Icons` being
used in other parts of the code. This PR adds the missing ones:

```
java.lang.NoClassDefFoundError: Failed resolution of: Landroidx/compose/material/icons/Icons$Rounded;
```
@vegaro vegaro closed this Oct 15, 2025
@vegaro vegaro deleted the release/8.25.0 branch October 15, 2025 14:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants