| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'dart:ui' show hashValues; |
| import 'package:collection/collection.dart'; |
| import 'package:json_annotation/json_annotation.dart'; |
| import 'enum_converters.dart'; |
| |
| // WARNING: Changes to `@JsonSerializable` classes need to be reflected in the |
| // below generated file. Run `flutter packages pub run build_runner watch` to |
| // rebuild and watch for further changes. |
| part 'sk_product_wrapper.g.dart'; |
| |
| /// Dart wrapper around StoreKit's [SKProductsResponse](https://developer.apple.com/documentation/storekit/skproductsresponse?language=objc). |
| /// |
| /// Represents the response object returned by [SKRequestMaker.startProductRequest]. |
| /// Contains information about a list of products and a list of invalid product identifiers. |
| @JsonSerializable() |
| class SkProductResponseWrapper { |
| /// Creates an [SkProductResponseWrapper] with the given product details. |
| SkProductResponseWrapper( |
| {required this.products, required this.invalidProductIdentifiers}); |
| |
| /// Constructing an instance from a map from the Objective-C layer. |
| /// |
| /// This method should only be used with `map` values returned by [SKRequestMaker.startProductRequest]. |
| factory SkProductResponseWrapper.fromJson(Map<String, dynamic> map) { |
| return _$SkProductResponseWrapperFromJson(map); |
| } |
| |
| /// Stores all matching successfully found products. |
| /// |
| /// One product in this list matches one valid product identifier passed to the [SKRequestMaker.startProductRequest]. |
| /// Will be empty if the [SKRequestMaker.startProductRequest] method does not pass any correct product identifier. |
| @JsonKey(defaultValue: <SKProductWrapper>[]) |
| final List<SKProductWrapper> products; |
| |
| /// Stores product identifiers in the `productIdentifiers` from [SKRequestMaker.startProductRequest] that are not recognized by the App Store. |
| /// |
| /// The App Store will not recognize a product identifier unless certain criteria are met. A detailed list of the criteria can be |
| /// found here https://developer.apple.com/documentation/storekit/skproductsresponse/1505985-invalidproductidentifiers?language=objc. |
| /// Will be empty if all the product identifiers are valid. |
| @JsonKey(defaultValue: <String>[]) |
| final List<String> invalidProductIdentifiers; |
| |
| @override |
| bool operator ==(Object other) { |
| if (identical(other, this)) { |
| return true; |
| } |
| if (other.runtimeType != runtimeType) { |
| return false; |
| } |
| final SkProductResponseWrapper typedOther = |
| other as SkProductResponseWrapper; |
| return DeepCollectionEquality().equals(typedOther.products, products) && |
| DeepCollectionEquality().equals( |
| typedOther.invalidProductIdentifiers, invalidProductIdentifiers); |
| } |
| |
| @override |
| int get hashCode => hashValues(this.products, this.invalidProductIdentifiers); |
| } |
| |
| /// Dart wrapper around StoreKit's [SKProductPeriodUnit](https://developer.apple.com/documentation/storekit/skproductperiodunit?language=objc). |
| /// |
| /// Used as a property in the [SKProductSubscriptionPeriodWrapper]. Minimum is a day and maximum is a year. |
| // The values of the enum options are matching the [SKProductPeriodUnit]'s values. Should there be an update or addition |
| // in the [SKProductPeriodUnit], this need to be updated to match. |
| enum SKSubscriptionPeriodUnit { |
| /// An interval lasting one day. |
| @JsonValue(0) |
| day, |
| |
| /// An interval lasting one month. |
| @JsonValue(1) |
| |
| /// An interval lasting one week. |
| week, |
| @JsonValue(2) |
| |
| /// An interval lasting one month. |
| month, |
| |
| /// An interval lasting one year. |
| @JsonValue(3) |
| year, |
| } |
| |
| /// Dart wrapper around StoreKit's [SKProductSubscriptionPeriod](https://developer.apple.com/documentation/storekit/skproductsubscriptionperiod?language=objc). |
| /// |
| /// A period is defined by a [numberOfUnits] and a [unit], e.g for a 3 months period [numberOfUnits] is 3 and [unit] is a month. |
| /// It is used as a property in [SKProductDiscountWrapper] and [SKProductWrapper]. |
| @JsonSerializable() |
| class SKProductSubscriptionPeriodWrapper { |
| /// Creates an [SKProductSubscriptionPeriodWrapper] for a `numberOfUnits`x`unit` period. |
| SKProductSubscriptionPeriodWrapper( |
| {required this.numberOfUnits, required this.unit}); |
| |
| /// Constructing an instance from a map from the Objective-C layer. |
| /// |
| /// This method should only be used with `map` values returned by [SKProductDiscountWrapper.fromJson] or [SKProductWrapper.fromJson]. |
| factory SKProductSubscriptionPeriodWrapper.fromJson( |
| Map<String, dynamic>? map) { |
| if (map == null) { |
| return SKProductSubscriptionPeriodWrapper( |
| numberOfUnits: 0, unit: SKSubscriptionPeriodUnit.day); |
| } |
| return _$SKProductSubscriptionPeriodWrapperFromJson(map); |
| } |
| |
| /// The number of [unit] units in this period. |
| /// |
| /// Must be greater than 0 if the object is valid. |
| @JsonKey(defaultValue: 0) |
| final int numberOfUnits; |
| |
| /// The time unit used to specify the length of this period. |
| @SKSubscriptionPeriodUnitConverter() |
| final SKSubscriptionPeriodUnit unit; |
| |
| @override |
| bool operator ==(Object other) { |
| if (identical(other, this)) { |
| return true; |
| } |
| if (other.runtimeType != runtimeType) { |
| return false; |
| } |
| final SKProductSubscriptionPeriodWrapper typedOther = |
| other as SKProductSubscriptionPeriodWrapper; |
| return typedOther.numberOfUnits == numberOfUnits && typedOther.unit == unit; |
| } |
| |
| @override |
| int get hashCode => hashValues(this.numberOfUnits, this.unit); |
| } |
| |
| /// Dart wrapper around StoreKit's [SKProductDiscountPaymentMode](https://developer.apple.com/documentation/storekit/skproductdiscountpaymentmode?language=objc). |
| /// |
| /// This is used as a property in the [SKProductDiscountWrapper]. |
| // The values of the enum options are matching the [SKProductDiscountPaymentMode]'s values. Should there be an update or addition |
| // in the [SKProductDiscountPaymentMode], this need to be updated to match. |
| enum SKProductDiscountPaymentMode { |
| /// Allows user to pay the discounted price at each payment period. |
| @JsonValue(0) |
| payAsYouGo, |
| |
| /// Allows user to pay the discounted price upfront and receive the product for the rest of time that was paid for. |
| @JsonValue(1) |
| payUpFront, |
| |
| /// User pays nothing during the discounted period. |
| @JsonValue(2) |
| freeTrail, |
| |
| /// Unspecified mode. |
| @JsonValue(-1) |
| unspecified, |
| } |
| |
| /// Dart wrapper around StoreKit's [SKProductDiscount](https://developer.apple.com/documentation/storekit/skproductdiscount?language=objc). |
| /// |
| /// It is used as a property in [SKProductWrapper]. |
| @JsonSerializable() |
| class SKProductDiscountWrapper { |
| /// Creates an [SKProductDiscountWrapper] with the given discount details. |
| SKProductDiscountWrapper( |
| {required this.price, |
| required this.priceLocale, |
| required this.numberOfPeriods, |
| required this.paymentMode, |
| required this.subscriptionPeriod}); |
| |
| /// Constructing an instance from a map from the Objective-C layer. |
| /// |
| /// This method should only be used with `map` values returned by [SKProductWrapper.fromJson]. |
| factory SKProductDiscountWrapper.fromJson(Map<String, dynamic> map) { |
| return _$SKProductDiscountWrapperFromJson(map); |
| } |
| |
| /// The discounted price, in the currency that is defined in [priceLocale]. |
| @JsonKey(defaultValue: '') |
| final String price; |
| |
| /// Includes locale information about the price, e.g. `$` as the currency symbol for US locale. |
| final SKPriceLocaleWrapper priceLocale; |
| |
| /// The object represent the discount period length. |
| /// |
| /// The value must be >= 0 if the object is valid. |
| @JsonKey(defaultValue: 0) |
| final int numberOfPeriods; |
| |
| /// The object indicates how the discount price is charged. |
| @SKProductDiscountPaymentModeConverter() |
| final SKProductDiscountPaymentMode paymentMode; |
| |
| /// The object represents the duration of single subscription period for the discount. |
| /// |
| /// The [subscriptionPeriod] of the discount is independent of the product's [subscriptionPeriod], |
| /// and their units and duration do not have to be matched. |
| final SKProductSubscriptionPeriodWrapper subscriptionPeriod; |
| |
| @override |
| bool operator ==(Object other) { |
| if (identical(other, this)) { |
| return true; |
| } |
| if (other.runtimeType != runtimeType) { |
| return false; |
| } |
| final SKProductDiscountWrapper typedOther = |
| other as SKProductDiscountWrapper; |
| return typedOther.price == price && |
| typedOther.priceLocale == priceLocale && |
| typedOther.numberOfPeriods == numberOfPeriods && |
| typedOther.paymentMode == paymentMode && |
| typedOther.subscriptionPeriod == subscriptionPeriod; |
| } |
| |
| @override |
| int get hashCode => hashValues(this.price, this.priceLocale, |
| this.numberOfPeriods, this.paymentMode, this.subscriptionPeriod); |
| } |
| |
| /// Dart wrapper around StoreKit's [SKProduct](https://developer.apple.com/documentation/storekit/skproduct?language=objc). |
| /// |
| /// A list of [SKProductWrapper] is returned in the [SKRequestMaker.startProductRequest] method, and |
| /// should be stored for use when making a payment. |
| @JsonSerializable() |
| class SKProductWrapper { |
| /// Creates an [SKProductWrapper] with the given product details. |
| SKProductWrapper({ |
| required this.productIdentifier, |
| required this.localizedTitle, |
| required this.localizedDescription, |
| required this.priceLocale, |
| this.subscriptionGroupIdentifier, |
| required this.price, |
| this.subscriptionPeriod, |
| this.introductoryPrice, |
| }); |
| |
| /// Constructing an instance from a map from the Objective-C layer. |
| /// |
| /// This method should only be used with `map` values returned by [SkProductResponseWrapper.fromJson]. |
| factory SKProductWrapper.fromJson(Map<String, dynamic> map) { |
| return _$SKProductWrapperFromJson(map); |
| } |
| |
| /// The unique identifier of the product. |
| @JsonKey(defaultValue: '') |
| final String productIdentifier; |
| |
| /// The localizedTitle of the product. |
| /// |
| /// It is localized based on the current locale. |
| @JsonKey(defaultValue: '') |
| final String localizedTitle; |
| |
| /// The localized description of the product. |
| /// |
| /// It is localized based on the current locale. |
| @JsonKey(defaultValue: '') |
| final String localizedDescription; |
| |
| /// Includes locale information about the price, e.g. `$` as the currency symbol for US locale. |
| final SKPriceLocaleWrapper priceLocale; |
| |
| /// The subscription group identifier. |
| /// |
| /// If the product is not a subscription, the value is `null`. |
| /// |
| /// A subscription group is a collection of subscription products. |
| /// Check [SubscriptionGroup](https://developer.apple.com/app-store/subscriptions/) for more details about subscription group. |
| final String? subscriptionGroupIdentifier; |
| |
| /// The price of the product, in the currency that is defined in [priceLocale]. |
| @JsonKey(defaultValue: '') |
| final String price; |
| |
| /// The object represents the subscription period of the product. |
| /// |
| /// Can be [null] is the product is not a subscription. |
| final SKProductSubscriptionPeriodWrapper? subscriptionPeriod; |
| |
| /// The object represents the duration of single subscription period. |
| /// |
| /// This is only available if you set up the introductory price in the App Store Connect, otherwise the value is `null`. |
| /// Programmer is also responsible to determine if the user is eligible to receive it. See https://developer.apple.com/documentation/storekit/in-app_purchase/offering_introductory_pricing_in_your_app?language=objc |
| /// for more details. |
| /// The [subscriptionPeriod] of the discount is independent of the product's [subscriptionPeriod], |
| /// and their units and duration do not have to be matched. |
| final SKProductDiscountWrapper? introductoryPrice; |
| |
| @override |
| bool operator ==(Object other) { |
| if (identical(other, this)) { |
| return true; |
| } |
| if (other.runtimeType != runtimeType) { |
| return false; |
| } |
| final SKProductWrapper typedOther = other as SKProductWrapper; |
| return typedOther.productIdentifier == productIdentifier && |
| typedOther.localizedTitle == localizedTitle && |
| typedOther.localizedDescription == localizedDescription && |
| typedOther.priceLocale == priceLocale && |
| typedOther.subscriptionGroupIdentifier == subscriptionGroupIdentifier && |
| typedOther.price == price && |
| typedOther.subscriptionPeriod == subscriptionPeriod && |
| typedOther.introductoryPrice == introductoryPrice; |
| } |
| |
| @override |
| int get hashCode => hashValues( |
| this.productIdentifier, |
| this.localizedTitle, |
| this.localizedDescription, |
| this.priceLocale, |
| this.subscriptionGroupIdentifier, |
| this.price, |
| this.subscriptionPeriod, |
| this.introductoryPrice); |
| } |
| |
| /// Object that indicates the locale of the price |
| /// |
| /// It is a thin wrapper of [NSLocale](https://developer.apple.com/documentation/foundation/nslocale?language=objc). |
| @JsonSerializable() |
| class SKPriceLocaleWrapper { |
| /// Creates a new price locale for `currencySymbol` and `currencyCode`. |
| SKPriceLocaleWrapper({ |
| required this.localeIdentifier, |
| required this.countryCode, |
| required this.languageCode, |
| required this.scriptCode, |
| required this.variantCode, |
| required this.collationIdentifier, |
| required this.collatorIdentifier, |
| required this.usesMetricSystem, |
| required this.measurementSystem, |
| required this.decimalSeparator, |
| required this.groupingSeparator, |
| required this.currencySymbol, |
| required this.currencyCode, |
| required this.endDelimiterKey, |
| required this.beginDelimiterKey, |
| required this.alternateQuotationEndDelimiterKey, |
| required this.alternateQuotationBeginDelimiterKey, |
| }); |
| |
| /// Constructing an instance from a map from the Objective-C layer. |
| /// |
| /// This method should only be used with `map` values returned by [SKProductWrapper.fromJson] and [SKProductDiscountWrapper.fromJson]. |
| factory SKPriceLocaleWrapper.fromJson(Map<String, dynamic>? map) { |
| if (map == null) { |
| return SKPriceLocaleWrapper( |
| localeIdentifier: '', |
| countryCode: '', |
| languageCode: '', |
| scriptCode: '', |
| variantCode: '', |
| collationIdentifier: '', |
| collatorIdentifier: '', |
| usesMetricSystem: true, |
| measurementSystem: '', |
| decimalSeparator: '', |
| groupingSeparator: '', |
| currencySymbol: '', |
| currencyCode: '', |
| endDelimiterKey: '', |
| beginDelimiterKey: '', |
| alternateQuotationEndDelimiterKey: '', |
| alternateQuotationBeginDelimiterKey: '', |
| ); |
| } |
| return _$SKPriceLocaleWrapperFromJson(map); |
| } |
| |
| ///The identifier for the locale, e.g. "en_US" for US locale. |
| @JsonKey(defaultValue: '') |
| final String localeIdentifier; |
| |
| ///The country or region code for the locale, e.g. "US" for en_US locale. |
| @JsonKey(defaultValue: '') |
| final String countryCode; |
| |
| ///The language code for the locale, e.g. "en" for en_US locale. |
| @JsonKey(defaultValue: '') |
| final String languageCode; |
| |
| ///The script code for the locale, e.g. "Latn" for en_US locale. |
| @JsonKey(defaultValue: '') |
| final String scriptCode; |
| |
| ///The variant code for the locale, e.g. "POSIX". |
| @JsonKey(defaultValue: '') |
| final String variantCode; |
| |
| ///The collation associated with the locale, e.g. "pinyin". |
| @JsonKey(defaultValue: '') |
| final String collationIdentifier; |
| |
| ///The collation identifier for the locale, e.g. "en". |
| @JsonKey(defaultValue: '') |
| final String collatorIdentifier; |
| |
| ///A flag whether the locale uses the metric system. |
| ///If the value is false, you can typically assume American measurement units (e.g. miles). |
| @JsonKey(defaultValue: true) |
| final bool usesMetricSystem; |
| |
| ///The measurement associated with the locale, e.g. "Metric" or "U.S.". |
| @JsonKey(defaultValue: '') |
| final String measurementSystem; |
| |
| ///The decimal separator associated with the locale, e.g. "." or ",". |
| @JsonKey(defaultValue: '') |
| final String decimalSeparator; |
| |
| ///The numeric grouping separator associated with the locale, e.g. "," or " ". |
| @JsonKey(defaultValue: '') |
| final String groupingSeparator; |
| |
| ///The currency symbol for the locale, e.g. $ for US locale. |
| @JsonKey(defaultValue: '') |
| final String currencySymbol; |
| |
| ///The currency code for the locale, e.g. USD for US locale. |
| @JsonKey(defaultValue: '') |
| final String currencyCode; |
| |
| ///The end quotation symbol associated with the locale, e.g. "”", "“", "»", or "」". |
| @JsonKey(defaultValue: '') |
| final String endDelimiterKey; |
| |
| ///The begin quotation symbol associated with the locale, e.g. "“", "„", "«", or "「". |
| @JsonKey(defaultValue: '') |
| final String beginDelimiterKey; |
| |
| ///The alternate end quotation symbol associated with the locale, e.g. "“", "„", "«", or "「". |
| @JsonKey(defaultValue: '') |
| final String alternateQuotationEndDelimiterKey; |
| |
| ///The alternating begin quotation symbol associated with the locale, e.g. "“", "„", "«", or "「". |
| @JsonKey(defaultValue: '') |
| final String alternateQuotationBeginDelimiterKey; |
| |
| @override |
| bool operator ==(Object other) => |
| identical(this, other) || |
| other is SKPriceLocaleWrapper && |
| runtimeType == other.runtimeType && |
| localeIdentifier == other.localeIdentifier && |
| countryCode == other.countryCode && |
| languageCode == other.languageCode && |
| scriptCode == other.scriptCode && |
| variantCode == other.variantCode && |
| collationIdentifier == other.collationIdentifier && |
| collatorIdentifier == other.collatorIdentifier && |
| usesMetricSystem == other.usesMetricSystem && |
| measurementSystem == other.measurementSystem && |
| decimalSeparator == other.decimalSeparator && |
| groupingSeparator == other.groupingSeparator && |
| currencySymbol == other.currencySymbol && |
| currencyCode == other.currencyCode && |
| endDelimiterKey == other.endDelimiterKey && |
| beginDelimiterKey == other.beginDelimiterKey && |
| alternateQuotationEndDelimiterKey == |
| other.alternateQuotationEndDelimiterKey && |
| alternateQuotationBeginDelimiterKey == |
| other.alternateQuotationBeginDelimiterKey; |
| |
| @override |
| int get hashCode => |
| localeIdentifier.hashCode ^ |
| countryCode.hashCode ^ |
| languageCode.hashCode ^ |
| scriptCode.hashCode ^ |
| variantCode.hashCode ^ |
| collationIdentifier.hashCode ^ |
| collatorIdentifier.hashCode ^ |
| usesMetricSystem.hashCode ^ |
| measurementSystem.hashCode ^ |
| decimalSeparator.hashCode ^ |
| groupingSeparator.hashCode ^ |
| currencySymbol.hashCode ^ |
| currencyCode.hashCode ^ |
| endDelimiterKey.hashCode ^ |
| beginDelimiterKey.hashCode ^ |
| alternateQuotationEndDelimiterKey.hashCode ^ |
| alternateQuotationBeginDelimiterKey.hashCode; |
| } |