Skip to content

Commit 9b4aaae

Browse files
Chris Yangandreidiaconu
authored andcommitted
Using json serializer for skproduct wrapper and related classes (flutter#1147)
1 parent fa66e1a commit 9b4aaae

File tree

5 files changed

+146
-73
lines changed

5 files changed

+146
-73
lines changed

packages/in_app_purchase/lib/src/store_kit_wrappers/sk_product_wrapper.dart

Lines changed: 38 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,18 @@
33
// found in the LICENSE file.
44

55
import 'package:flutter/foundation.dart';
6+
import 'package:json_annotation/json_annotation.dart';
7+
8+
// WARNING: Changes to `@JsonSerializable` classes need to be reflected in the
9+
// below generated file. Run `flutter packages pub run build_runner watch` to
10+
// rebuild and watch for further changes.
11+
part 'sk_product_wrapper.g.dart';
612

713
/// Dart wrapper around StoreKit's [SKProductsResponse](https://developer.apple.com/documentation/storekit/skproductsresponse?language=objc).
814
///
915
/// Represents the response object returned by [SKRequestMaker.startProductRequest].
1016
/// Contains information about a list of products and a list of invalid product identifiers.
17+
@JsonSerializable()
1118
class SkProductResponseWrapper {
1219
SkProductResponseWrapper(
1320
{@required this.products, @required this.invalidProductIdentifiers});
@@ -16,11 +23,10 @@ class SkProductResponseWrapper {
1623
///
1724
/// This method should only be used with `map` values returned by [SKRequestMaker.startProductRequest].
1825
/// The `map` parameter must not be null.
19-
SkProductResponseWrapper.fromMap(Map<String, List<dynamic>> map)
20-
: assert(map != null),
21-
products = _getListFromMapList(_getProductMapListFromResponseMap(map)),
22-
invalidProductIdentifiers =
23-
List.castFrom<dynamic, String>(map['invalidProductIdentifiers']);
26+
factory SkProductResponseWrapper.fromJson(Map map) {
27+
assert(map != null);
28+
return _$SkProductResponseWrapperFromJson(map);
29+
}
2430

2531
/// Stores all matching successfully found products.
2632
///
@@ -34,18 +40,6 @@ class SkProductResponseWrapper {
3440
/// found here https://developer.apple.com/documentation/storekit/skproductsresponse/1505985-invalidproductidentifiers?language=objc.
3541
/// Will be empty if all the product identifiers are valid.
3642
final List<String> invalidProductIdentifiers;
37-
38-
static List<Map<dynamic, dynamic>> _getProductMapListFromResponseMap(
39-
Map<String, List<dynamic>> map) {
40-
return map['products'].cast<Map<dynamic, dynamic>>();
41-
}
42-
43-
static List<SKProductWrapper> _getListFromMapList(
44-
List<Map<dynamic, dynamic>> mapList) {
45-
return mapList
46-
.map((Map<dynamic, dynamic> map) => SKProductWrapper.fromMap(map))
47-
.toList();
48-
}
4943
}
5044

5145
/// Dart wrapper around StoreKit's [SKProductPeriodUnit](https://developer.apple.com/documentation/storekit/skproductperiodunit?language=objc).
@@ -54,30 +48,34 @@ class SkProductResponseWrapper {
5448
// The values of the enum options are matching the [SKProductPeriodUnit]'s values. Should there be an update or addition
5549
// in the [SKProductPeriodUnit], this need to be updated to match.
5650
enum SubscriptionPeriodUnit {
51+
@JsonValue(0)
5752
day,
53+
@JsonValue(1)
5854
week,
55+
@JsonValue(2)
5956
month,
57+
@JsonValue(3)
6058
year,
6159
}
6260

6361
/// Dart wrapper around StoreKit's [SKProductSubscriptionPeriod](https://developer.apple.com/documentation/storekit/skproductsubscriptionperiod?language=objc).
6462
///
6563
/// 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.
6664
/// It is used as a property in [SKProductDiscountWrapper] and [SKProductWrapper].
65+
@JsonSerializable(nullable: true)
6766
class SKProductSubscriptionPeriodWrapper {
6867
SKProductSubscriptionPeriodWrapper(
6968
{@required this.numberOfUnits, @required this.unit});
7069

7170
/// Constructing an instance from a map from the Objective-C layer.
72-
/// This method should only be used with `map` values returned by [SKProductDiscountWrapper.fromMap] or [SKProductWrapper.fromMap].
71+
///
72+
/// This method should only be used with `map` values returned by [SKProductDiscountWrapper.fromJson] or [SKProductWrapper.fromJson].
7373
/// The `map` parameter must not be null.
74-
SKProductSubscriptionPeriodWrapper.fromMap(Map<String, dynamic> map)
75-
: assert(map != null &&
76-
(map['numberOfUnits'] == null || map['numberOfUnits'] > 0)),
77-
numberOfUnits = map['numberOfUnits'],
78-
unit = (map['unit'] != null)
79-
? SubscriptionPeriodUnit.values[map['unit']]
80-
: null;
74+
factory SKProductSubscriptionPeriodWrapper.fromJson(Map map) {
75+
assert(map != null &&
76+
(map['numberOfUnits'] == null || map['numberOfUnits'] > 0));
77+
return _$SKProductSubscriptionPeriodWrapperFromJson(map);
78+
}
8179

8280
/// The number of [unit] units in this period.
8381
///
@@ -95,12 +93,15 @@ class SKProductSubscriptionPeriodWrapper {
9593
// in the [SKProductDiscountPaymentMode], this need to be updated to match.
9694
enum ProductDiscountPaymentMode {
9795
/// Allows user to pay the discounted price at each payment period.
96+
@JsonValue(0)
9897
payAsYouGo,
9998

10099
/// Allows user to pay the discounted price upfront and receive the product for the rest of time that was paid for.
100+
@JsonValue(1)
101101
payUpFront,
102102

103103
/// User pays nothing during the discounted period.
104+
@JsonValue(2)
104105
freeTrail,
105106
}
106107

@@ -109,6 +110,7 @@ enum ProductDiscountPaymentMode {
109110
/// Most of the fields are identical to OBJC SKProduct.
110111
/// The only difference is instead of the locale object, we only exposed currencyCode for simplicity.
111112
/// It is used as a property in [SKProductWrapper].
113+
@JsonSerializable(nullable: true)
112114
class SKProductDiscountWrapper {
113115
SKProductDiscountWrapper(
114116
{@required this.price,
@@ -119,20 +121,12 @@ class SKProductDiscountWrapper {
119121

120122
/// Constructing an instance from a map from the Objective-C layer.
121123
///
122-
/// This method should only be used with `map` values returned by [SKProductWrapper.fromMap].
124+
/// This method should only be used with `map` values returned by [SKProductWrapper.fromJson].
123125
/// The `map` parameter must not be null.
124-
SKProductDiscountWrapper.fromMap(Map<String, dynamic> map)
125-
: assert(map != null),
126-
price = map['price'],
127-
currencyCode = map['currencyCode'],
128-
numberOfPeriods = map['numberOfPeriods'],
129-
paymentMode = (map['paymentMode'] != null)
130-
? ProductDiscountPaymentMode.values[map['paymentMode']]
131-
: null,
132-
subscriptionPeriod = map['subscriptionPeriod'] != null
133-
? SKProductSubscriptionPeriodWrapper.fromMap(
134-
map['subscriptionPeriod'].cast<String, dynamic>())
135-
: null;
126+
factory SKProductDiscountWrapper.fromJson(Map map) {
127+
assert(map != null);
128+
return _$SKProductDiscountWrapperFromJson(map);
129+
}
136130

137131
/// The discounted price, in the currency that is defined in [currencyCode].
138132
final double price;
@@ -164,6 +158,7 @@ class SKProductDiscountWrapper {
164158
/// The only difference is instead of the locale object, we only exposed currencyCode for simplicity.
165159
/// A list of [SKProductWrapper] is returned in the [SKRequestMaker.startProductRequest] method, and
166160
/// should be stored for use when making a payment.
161+
@JsonSerializable(nullable: true)
167162
class SKProductWrapper {
168163
SKProductWrapper({
169164
@required this.productIdentifier,
@@ -181,28 +176,12 @@ class SKProductWrapper {
181176

182177
/// Constructing an instance from a map from the Objective-C layer.
183178
///
184-
/// This method should only be used with `map` values returned by [SkProductResponseWrapper.fromMap].
179+
/// This method should only be used with `map` values returned by [SkProductResponseWrapper.fromJson].
185180
/// The `map` parameter must not be null.
186-
SKProductWrapper.fromMap(Map<dynamic, dynamic> map)
187-
: assert(map != null),
188-
productIdentifier = map['productIdentifier'],
189-
localizedTitle = map['localizedTitle'],
190-
localizedDescription = map['localizedDescription'],
191-
currencyCode = map['currencyCode'],
192-
downloadContentVersion = map['downloadContentVersion'],
193-
subscriptionGroupIdentifier = map['subscriptionGroupIdentifier'],
194-
price = map['price'],
195-
downloadable = map['downloadable'],
196-
downloadContentLengths =
197-
List.castFrom<dynamic, int>(map['downloadContentLengths']),
198-
subscriptionPeriod = map['subscriptionPeriod'] != null
199-
? SKProductSubscriptionPeriodWrapper.fromMap(
200-
map['subscriptionPeriod'].cast<String, dynamic>())
201-
: null,
202-
introductoryPrice = (map['introductoryPrice'] != null)
203-
? SKProductDiscountWrapper.fromMap(
204-
map['introductoryPrice'].cast<String, dynamic>())
205-
: null;
181+
factory SKProductWrapper.fromJson(Map map) {
182+
assert(map != null);
183+
return _$SKProductWrapperFromJson(map);
184+
}
206185

207186
/// The unique identifier of the product.
208187
final String productIdentifier;

packages/in_app_purchase/lib/src/store_kit_wrappers/sk_product_wrapper.g.dart

Lines changed: 96 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/in_app_purchase/lib/src/store_kit_wrappers/sk_request_maker.dart

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class SKRequestMaker {
2424
/// A [PlatformException] is thrown if the platform code making the request fails.
2525
Future<SkProductResponseWrapper> startProductRequest(
2626
List<String> productIdentifiers) async {
27-
final Map<dynamic, dynamic> productResponseMap = await channel.invokeMethod(
27+
final Map productResponseMap = await channel.invokeMethod(
2828
'-[InAppPurchasePlugin startProductRequest:result:]',
2929
productIdentifiers,
3030
);
@@ -34,7 +34,6 @@ class SKRequestMaker {
3434
message: 'StoreKit: Failed to get response from platform.',
3535
);
3636
}
37-
return SkProductResponseWrapper.fromMap(
38-
productResponseMap.cast<String, List<dynamic>>());
37+
return SkProductResponseWrapper.fromJson(productResponseMap);
3938
}
4039
}

packages/in_app_purchase/test/store_kit_wrappers/sk_product_test.dart

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ void main() {
4141
'SKProductSubscriptionPeriodWrapper should have property values consistent with map',
4242
() {
4343
final SKProductSubscriptionPeriodWrapper wrapper =
44-
SKProductSubscriptionPeriodWrapper.fromMap(subMap);
44+
SKProductSubscriptionPeriodWrapper.fromJson(subMap);
4545
expect(wrapper.numberOfUnits, subMap['numberOfUnits']);
4646
expect(wrapper.unit, SubscriptionPeriodUnit.values[subMap['unit']]);
4747
});
@@ -50,7 +50,7 @@ void main() {
5050
'SKProductSubscriptionPeriodWrapper should have properties to be null if map is empty',
5151
() {
5252
final SKProductSubscriptionPeriodWrapper wrapper =
53-
SKProductSubscriptionPeriodWrapper.fromMap(<String, dynamic>{});
53+
SKProductSubscriptionPeriodWrapper.fromJson(<String, dynamic>{});
5454
expect(wrapper.numberOfUnits, null);
5555
expect(wrapper.unit, null);
5656
});
@@ -59,7 +59,7 @@ void main() {
5959
'SKProductDiscountWrapper should have property values consistent with map',
6060
() {
6161
final SKProductDiscountWrapper wrapper =
62-
SKProductDiscountWrapper.fromMap(discountMap);
62+
SKProductDiscountWrapper.fromJson(discountMap);
6363
expect(wrapper.price, discountMap['price']);
6464
expect(wrapper.currencyCode, discountMap['currencyCode']);
6565
expect(wrapper.numberOfPeriods, discountMap['numberOfPeriods']);
@@ -77,7 +77,7 @@ void main() {
7777
'SKProductDiscountWrapper should have properties to be null if map is empty',
7878
() {
7979
final SKProductDiscountWrapper wrapper =
80-
SKProductDiscountWrapper.fromMap(<String, dynamic>{});
80+
SKProductDiscountWrapper.fromJson(<String, dynamic>{});
8181
expect(wrapper.price, null);
8282
expect(wrapper.currencyCode, null);
8383
expect(wrapper.numberOfPeriods, null);
@@ -125,15 +125,14 @@ void main() {
125125

126126
test('SKProductWrapper should have property values consistent with map',
127127
() {
128-
final SKProductWrapper wrapper = SKProductWrapper.fromMap(productMap);
128+
final SKProductWrapper wrapper = SKProductWrapper.fromJson(productMap);
129129
testMatchingProductMap(wrapper, productMap);
130130
});
131131

132-
test(
133-
'SKProductDiscountWrapper should have properties to be null if map is empty',
132+
test('SKProductWrapper should have properties to be null if map is empty',
134133
() {
135134
final SKProductWrapper wrapper =
136-
SKProductWrapper.fromMap(<String, dynamic>{});
135+
SKProductWrapper.fromJson(<String, dynamic>{});
137136
expect(wrapper.productIdentifier, null);
138137
expect(wrapper.localizedTitle, null);
139138
expect(wrapper.localizedDescription, null);
@@ -147,7 +146,7 @@ void main() {
147146

148147
test('SKProductResponse wrapper should match', () {
149148
final SkProductResponseWrapper wrapper =
150-
SkProductResponseWrapper.fromMap(productResponseMap);
149+
SkProductResponseWrapper.fromJson(productResponseMap);
151150
testMatchingProductMap(
152151
wrapper.products[0], productResponseMap['products'][0]);
153152
expect(wrapper.invalidProductIdentifiers,
@@ -160,7 +159,7 @@ void main() {
160159
'invalidProductIdentifiers': <String>[],
161160
};
162161
final SkProductResponseWrapper wrapper =
163-
SkProductResponseWrapper.fromMap(productResponseMapEmptyList);
162+
SkProductResponseWrapper.fromJson(productResponseMapEmptyList);
164163
expect(wrapper.products.length, 0);
165164
expect(wrapper.invalidProductIdentifiers.length, 0);
166165
});

packages/in_app_purchase/test/store_kit_wrappers/sk_request_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ void main() {
4848
test('platform call should get result', () async {
4949
stubPlatform.addResponse(
5050
name: '-[InAppPurchasePlugin startProductRequest:result:]',
51-
value: productResponseMap.cast<String, dynamic>());
51+
value: productResponseMap);
5252
final SKRequestMaker request = SKRequestMaker();
5353
final SkProductResponseWrapper response =
5454
await request.startProductRequest(<String>['123']);

0 commit comments

Comments
 (0)