diff --git a/packages/in_app_purchase/in_app_purchase_ios/CHANGELOG.md b/packages/in_app_purchase/in_app_purchase_ios/CHANGELOG.md index d46c124b9011..d9fdfeccc1f7 100644 --- a/packages/in_app_purchase/in_app_purchase_ios/CHANGELOG.md +++ b/packages/in_app_purchase/in_app_purchase_ios/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.1 + +* Exposed most of the NSLocale object via the SKProductWrapper class. + ## 0.1.0 * Initial open-source release. \ No newline at end of file diff --git a/packages/in_app_purchase/in_app_purchase_ios/ios/Classes/FIAObjectTranslator.m b/packages/in_app_purchase/in_app_purchase_ios/ios/Classes/FIAObjectTranslator.m index 5d6e0a244a96..e03a9a72a766 100644 --- a/packages/in_app_purchase/in_app_purchase_ios/ios/Classes/FIAObjectTranslator.m +++ b/packages/in_app_purchase/in_app_purchase_ios/ios/Classes/FIAObjectTranslator.m @@ -107,10 +107,38 @@ + (NSDictionary *)getMapFromNSLocale:(NSLocale *)locale { return nil; } NSMutableDictionary *map = [[NSMutableDictionary alloc] init]; + + [map setObject:[locale objectForKey:NSLocaleIdentifier] ?: [NSNull null] + forKey:@"localeIdentifier"]; + [map setObject:[locale objectForKey:NSLocaleCountryCode] ?: [NSNull null] forKey:@"countryCode"]; + [map setObject:[locale objectForKey:NSLocaleLanguageCode] ?: [NSNull null] + forKey:@"languageCode"]; + [map setObject:[locale objectForKey:NSLocaleScriptCode] ?: [NSNull null] forKey:@"scriptCode"]; + [map setObject:[locale objectForKey:NSLocaleVariantCode] ?: [NSNull null] forKey:@"variantCode"]; + [map setObject:[locale objectForKey:NSLocaleCollationIdentifier] ?: [NSNull null] + forKey:@"collationIdentifier"]; + [map setObject:[locale objectForKey:NSLocaleCollatorIdentifier] ?: [NSNull null] + forKey:@"collatorIdentifier"]; + [map setObject:[locale objectForKey:NSLocaleUsesMetricSystem] ?: [NSNull null] + forKey:@"usesMetricSystem"]; + [map setObject:[locale objectForKey:NSLocaleMeasurementSystem] ?: [NSNull null] + forKey:@"measurementSystem"]; + [map setObject:[locale objectForKey:NSLocaleDecimalSeparator] ?: [NSNull null] + forKey:@"decimalSeparator"]; + [map setObject:[locale objectForKey:NSLocaleGroupingSeparator] ?: [NSNull null] + forKey:@"groupingSeparator"]; [map setObject:[locale objectForKey:NSLocaleCurrencySymbol] ?: [NSNull null] forKey:@"currencySymbol"]; [map setObject:[locale objectForKey:NSLocaleCurrencyCode] ?: [NSNull null] forKey:@"currencyCode"]; + [map setObject:[locale objectForKey:NSLocaleQuotationEndDelimiterKey] ?: [NSNull null] + forKey:@"endDelimiterKey"]; + [map setObject:[locale objectForKey:NSLocaleQuotationBeginDelimiterKey] ?: [NSNull null] + forKey:@"beginDelimiterKey"]; + [map setObject:[locale objectForKey:NSLocaleAlternateQuotationEndDelimiterKey] ?: [NSNull null] + forKey:@"alternateQuotationEndDelimiterKey"]; + [map setObject:[locale objectForKey:NSLocaleAlternateQuotationBeginDelimiterKey] ?: [NSNull null] + forKey:@"alternateQuotationBeginDelimiterKey"]; return map; } diff --git a/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/sk_product_wrapper.dart b/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/sk_product_wrapper.dart index ef0e6671d177..8518cc0ac193 100644 --- a/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/sk_product_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/sk_product_wrapper.dart @@ -329,25 +329,102 @@ class SKProductWrapper { /// Object that indicates the locale of the price /// /// It is a thin wrapper of [NSLocale](https://developer.apple.com/documentation/foundation/nslocale?language=objc). -// TODO(cyanglaz): NSLocale is a complex object, want to see the actual need of getting this expanded. -// Matching android to only get the currencySymbol for now. -// https://github.com/flutter/flutter/issues/26610 @JsonSerializable() class SKPriceLocaleWrapper { /// Creates a new price locale for `currencySymbol` and `currencyCode`. - SKPriceLocaleWrapper( - {required this.currencySymbol, required this.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? map) { if (map == null) { - return SKPriceLocaleWrapper(currencyCode: '', currencySymbol: ''); + 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; @@ -356,19 +433,64 @@ class SKPriceLocaleWrapper { @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) { - if (identical(other, this)) { - return true; - } - if (other.runtimeType != runtimeType) { - return false; - } - final SKPriceLocaleWrapper typedOther = other as SKPriceLocaleWrapper; - return typedOther.currencySymbol == currencySymbol && - typedOther.currencyCode == currencyCode; - } + 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 => hashValues(this.currencySymbol, this.currencyCode); + 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; } diff --git a/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/sk_product_wrapper.g.dart b/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/sk_product_wrapper.g.dart index 8c2eed3d6070..fd6ab372ed76 100644 --- a/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/sk_product_wrapper.g.dart +++ b/packages/in_app_purchase/in_app_purchase_ios/lib/src/store_kit_wrappers/sk_product_wrapper.g.dart @@ -110,14 +110,48 @@ Map _$SKProductWrapperToJson(SKProductWrapper instance) => SKPriceLocaleWrapper _$SKPriceLocaleWrapperFromJson(Map json) { return SKPriceLocaleWrapper( + localeIdentifier: json['localeIdentifier'] as String? ?? '', + countryCode: json['countryCode'] as String? ?? '', + languageCode: json['languageCode'] as String? ?? '', + scriptCode: json['scriptCode'] as String? ?? '', + variantCode: json['variantCode'] as String? ?? '', + collationIdentifier: json['collationIdentifier'] as String? ?? '', + collatorIdentifier: json['collatorIdentifier'] as String? ?? '', + usesMetricSystem: json['usesMetricSystem'] as bool? ?? true, + measurementSystem: json['measurementSystem'] as String? ?? '', + decimalSeparator: json['decimalSeparator'] as String? ?? '', + groupingSeparator: json['groupingSeparator'] as String? ?? '', currencySymbol: json['currencySymbol'] as String? ?? '', currencyCode: json['currencyCode'] as String? ?? '', + endDelimiterKey: json['endDelimiterKey'] as String? ?? '', + beginDelimiterKey: json['beginDelimiterKey'] as String? ?? '', + alternateQuotationEndDelimiterKey: + json['alternateQuotationEndDelimiterKey'] as String? ?? '', + alternateQuotationBeginDelimiterKey: + json['alternateQuotationBeginDelimiterKey'] as String? ?? '', ); } Map _$SKPriceLocaleWrapperToJson( SKPriceLocaleWrapper instance) => { + 'localeIdentifier': instance.localeIdentifier, + 'countryCode': instance.countryCode, + 'languageCode': instance.languageCode, + 'scriptCode': instance.scriptCode, + 'variantCode': instance.variantCode, + 'collationIdentifier': instance.collationIdentifier, + 'collatorIdentifier': instance.collatorIdentifier, + 'usesMetricSystem': instance.usesMetricSystem, + 'measurementSystem': instance.measurementSystem, + 'decimalSeparator': instance.decimalSeparator, + 'groupingSeparator': instance.groupingSeparator, 'currencySymbol': instance.currencySymbol, 'currencyCode': instance.currencyCode, + 'endDelimiterKey': instance.endDelimiterKey, + 'beginDelimiterKey': instance.beginDelimiterKey, + 'alternateQuotationEndDelimiterKey': + instance.alternateQuotationEndDelimiterKey, + 'alternateQuotationBeginDelimiterKey': + instance.alternateQuotationBeginDelimiterKey, }; diff --git a/packages/in_app_purchase/in_app_purchase_ios/pubspec.yaml b/packages/in_app_purchase/in_app_purchase_ios/pubspec.yaml index fcc7c5149ab8..c847fb4f5700 100644 --- a/packages/in_app_purchase/in_app_purchase_ios/pubspec.yaml +++ b/packages/in_app_purchase/in_app_purchase_ios/pubspec.yaml @@ -1,7 +1,7 @@ name: in_app_purchase_ios description: An implementation for the iOS platform of the Flutter `in_app_purchase` plugin. This uses the iOS StoreKit Framework. repository: https://github.com/flutter/plugins/tree/master/packages/in_app_purchase/in_app_purchase_ios -version: 0.1.0 +version: 0.1.1 flutter: plugin: diff --git a/packages/in_app_purchase/in_app_purchase_ios/test/store_kit_wrappers/sk_product_test.dart b/packages/in_app_purchase/in_app_purchase_ios/test/store_kit_wrappers/sk_product_test.dart index 9454a9d4ebee..55161dcec15d 100644 --- a/packages/in_app_purchase/in_app_purchase_ios/test/store_kit_wrappers/sk_product_test.dart +++ b/packages/in_app_purchase/in_app_purchase_ios/test/store_kit_wrappers/sk_product_test.dart @@ -44,8 +44,27 @@ void main() { final SKProductDiscountWrapper wrapper = SKProductDiscountWrapper.fromJson({}); expect(wrapper.price, ''); - expect(wrapper.priceLocale, - SKPriceLocaleWrapper(currencyCode: '', currencySymbol: '')); + expect( + wrapper.priceLocale, + SKPriceLocaleWrapper( + localeIdentifier: '', + countryCode: '', + languageCode: '', + scriptCode: '', + variantCode: '', + collationIdentifier: '', + collatorIdentifier: '', + usesMetricSystem: true, + measurementSystem: '', + decimalSeparator: '', + groupingSeparator: '', + currencySymbol: '', + currencyCode: '', + endDelimiterKey: '', + beginDelimiterKey: '', + alternateQuotationEndDelimiterKey: '', + alternateQuotationBeginDelimiterKey: '', + )); expect(wrapper.numberOfPeriods, 0); expect(wrapper.paymentMode, SKProductDiscountPaymentMode.payAsYouGo); expect( @@ -69,8 +88,27 @@ void main() { expect(wrapper.productIdentifier, ''); expect(wrapper.localizedTitle, ''); expect(wrapper.localizedDescription, ''); - expect(wrapper.priceLocale, - SKPriceLocaleWrapper(currencyCode: '', currencySymbol: '')); + expect( + wrapper.priceLocale, + SKPriceLocaleWrapper( + localeIdentifier: '', + countryCode: '', + languageCode: '', + scriptCode: '', + variantCode: '', + collationIdentifier: '', + collatorIdentifier: '', + usesMetricSystem: true, + measurementSystem: '', + decimalSeparator: '', + groupingSeparator: '', + currencySymbol: '', + currencyCode: '', + endDelimiterKey: '', + beginDelimiterKey: '', + alternateQuotationEndDelimiterKey: '', + alternateQuotationBeginDelimiterKey: '', + )); expect(wrapper.subscriptionGroupIdentifier, null); expect(wrapper.price, ''); expect(wrapper.subscriptionPeriod, null); diff --git a/packages/in_app_purchase/in_app_purchase_ios/test/store_kit_wrappers/sk_test_stub_objects.dart b/packages/in_app_purchase/in_app_purchase_ios/test/store_kit_wrappers/sk_test_stub_objects.dart index d6c24460761e..1298c60bf8a2 100644 --- a/packages/in_app_purchase/in_app_purchase_ios/test/store_kit_wrappers/sk_test_stub_objects.dart +++ b/packages/in_app_purchase/in_app_purchase_ios/test/store_kit_wrappers/sk_test_stub_objects.dart @@ -33,8 +33,25 @@ final SKPaymentTransactionWrapper dummyTransaction = error: dummyError, ); -final SKPriceLocaleWrapper dummyLocale = - SKPriceLocaleWrapper(currencySymbol: '\$', currencyCode: 'USD'); +final SKPriceLocaleWrapper dummyLocale = SKPriceLocaleWrapper( + localeIdentifier: 'en_US', + countryCode: 'US', + languageCode: 'en', + scriptCode: 'Latn', + variantCode: 'POSIX', + collationIdentifier: '', + collatorIdentifier: 'en', + usesMetricSystem: true, + measurementSystem: 'Metric', + decimalSeparator: '.', + groupingSeparator: ',', + currencySymbol: '\$', + currencyCode: 'USD', + endDelimiterKey: '”', + beginDelimiterKey: '“', + alternateQuotationEndDelimiterKey: '”', + alternateQuotationBeginDelimiterKey: '“', +); final SKProductSubscriptionPeriodWrapper dummySubscription = SKProductSubscriptionPeriodWrapper( @@ -69,8 +86,25 @@ final SkProductResponseWrapper dummyProductResponseWrapper = Map buildLocaleMap(SKPriceLocaleWrapper local) { return { + 'localeIdentifier': local.localeIdentifier, + 'countryCode': local.countryCode, + 'languageCode': local.languageCode, + 'scriptCode': local.scriptCode, + 'variantCode': local.variantCode, + 'collationIdentifier': local.collationIdentifier, + 'collatorIdentifier': local.collatorIdentifier, + 'usesMetricSystem': local.usesMetricSystem, + 'measurementSystem': local.measurementSystem, + 'decimalSeparator': local.decimalSeparator, + 'groupingSeparator': local.groupingSeparator, 'currencySymbol': local.currencySymbol, - 'currencyCode': local.currencyCode + 'currencyCode': local.currencyCode, + 'endDelimiterKey': local.endDelimiterKey, + 'beginDelimiterKey': local.beginDelimiterKey, + 'alternateQuotationEndDelimiterKey': + local.alternateQuotationEndDelimiterKey, + 'alternateQuotationBeginDelimiterKey': + local.alternateQuotationBeginDelimiterKey }; }