### Motivation
Get more context with targeting information
### Description
- Parse targeting information into `Offerings`
- Add targeting context into `Offerings.current`
- Add targeting context into `getCurrentOffering(forPlacement: String)`
- Post targeting context in post receipts
---------
Co-authored-by: RevenueCat Git Bot <72824662+RCGitBot@users.noreply.github.com>
### Motivation
New function to get `Offering` by a placement identifier
### Description
New `currentOffering(forPlacement: String): Offering?` method on
`Offerings`
- Added demo button for this in purchase tester app
```swift
// Example usage
if let offering = offerings.currentOffering(forPlacement: "onboarding") {
showPaywall(offering)
}
```
#### Logic flow
- If a placement identifier explicitly exists within the
`placements.offeringIdsByPlacement` dictionary, the method attempts to
fetch the corresponding `Offering` without resorting to a fallback
- Example: when there is a `nil` / null value for a placement, we don't
want to use the fallback
- If the placement identifier does not exist, the method then attempts
to fetch a fallback offering defined by `placements.fallbackOfferingId`
#### New placements object in offerings response
```js
{
// other offerings stuff
"placements": {
"fallback_offering_id": "offering_a", // can be null
"offering_ids_by_placement": {
"onboarding_start": null,
"onboarding_end": "offering_b",
}
}
}
```
---------
Co-authored-by: Guido Torres <guido@revenuecat.com>
Co-authored-by: Josh Holtz <me@joshholtz.com>
Co-authored-by: RevenueCat Git Bot <72824662+RCGitBot@users.noreply.github.com>
This was already approved and merged into `5.0-dev` but bringing this
into `4.x` (see #3690)
### Motivation
Allow for storing of other presented offering context on a `Package`
### Description
- Replaced `offeringIdentifier: String` on `Package` with new
`presentedOfferingContext: PresentedOfferingContext`
- Currently it only has a `offeringIdentifier: String`
- Eventually this will add new optional properties for targeting and
placements
### Changes:
- Exposed `internal`-only `Purchases.cachePresentedOfferingIdentifier`
- Changed `SwiftUI` extensions to `static` methods: this is required to
be able to call an instance method on them
- Added integration test to verify this offering identifier is used
Technically this is an API change, but these APIs are implicitly beta
because they're only available in Xcode 15 beta.
Not sure why I didn't notice this when compiling through Xcode, but just
noticed this on CI in #2591.
Fixes:
```
❌ /Users/distiller/purchases-ios/Sources/Support/PaywallExtensions.swift:106:27: 'some' return types are only available in application extensions for iOS 13.0.0 or newer
private var products: some Sequence<StoreProduct> {
```
### Description
This adds overloads, but there's still a few things pending for the SDK
to fully support these:
- Set `presentedOfferingIdentifier` when displaying StoreKit2 paywalls:
SDK-3176
- Fix `preventPurchasePopupCallFromTriggeringCacheRefresh`: SDK-3172
- Always initialize `StoreKit2TransactionListener` even on SK1 mode:
SDK-3170
### Example:
```swift
struct App: View {
var offering: Offering
var body: some View {
Content()
.sheet(isPresented: self.$showingSubscriptionSheet) {
SubscriptionStoreView(offering: self.offering)
}
}
}
```