blob: 8518cc0ac193907dc660b4422c57fe818ae7ad4e [file] [log] [blame]
// 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;
}