Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[in_app_purchase_storekit] migrate main plugin class to swift in preperation to storekit 2 #6561

Merged
merged 33 commits into from May 14, 2024

Conversation

LouiseHsu
Copy link
Contributor

@LouiseHsu LouiseHsu commented Apr 17, 2024

Part of flutter/flutter#119106

This PR migrates the main InAppPurchasePlugin.m class to swift.

Pre-launch Checklist

  • I read the [Contributor Guide] and followed the process outlined there for submitting PRs.
  • I read the [Tree Hygiene] wiki page, which explains my responsibilities.
  • I read and followed the [relevant style guides] and ran the auto-formatter. (Unlike the flutter/flutter repo, the flutter/packages repo does use dart format.)
  • I signed the [CLA].
  • The title of the PR starts with the name of the package surrounded by square brackets, e.g. [shared_preferences]
  • I [linked to at least one issue that this PR fixes] in the description above.
  • I updated pubspec.yaml with an appropriate new version according to the [pub versioning philosophy], or this PR is [exempt from version changes].
  • I updated CHANGELOG.md to add a description of the change, [following repository CHANGELOG style].
  • I updated/added relevant documentation (doc comments with ///).
  • I added new tests to check the change I am making, or this PR is [test-exempt].
  • All existing and new tests are passing.

@@ -238,7 +238,7 @@ abstract class InAppPurchaseAPI {
SKProductsResponseMessage startProductRequest(
List<String> productIdentifiers);

void finishTransaction(Map<String, String?> finishMap);
void finishTransaction(Map<String, Object?> finishMap);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even though the intended type here should be a nullable String, when pigeon generates obj C code, it is generated as type NSString. NSString is nullable in objective c, but when Xcode generates the corresponding swift method signature, it converts into a String, not a String?. NSString also cannot be annoted with _Nullable as it is a generic.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

im confused. why is NSString generic?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

^ this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, its not generic, but you can't specify a type inside a NSDictionary to be nullable. (i dont think)
Specifically here -

- (void)finishTransactionFinishMap:(NSDictionary<NSString *, id> *)finishMap

What I really want is for this line in swift
_ finishMap: [String: Any], error: AutoreleasingUnsafeMutablePointer<FlutterError?>

To be finishMap: [String: String?]. But the automatic conversion turns all NSStrings as String and not String?. And because I can't specify the NSString as extra nullable, I have to make it Object? (in pigeon) so it gets generated into id in objc, which then will turn into Any, and thus allow for nullability
Not sure if that makes sense lol

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using Any to represent an optional can be error-prone.
Why do you want [String:String?]? Is there any issue with using [String:String]?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how pendingTransactions is related to the dictionary type. Can you explain how using [String:String] type would fail to work here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea I meant the comments
Im not understanding the question i think? finishMap should be [String:String?] because finishMap["transactionIdentifier"] should be allowed to be null.

Copy link
Contributor Author

@LouiseHsu LouiseHsu May 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's just [String:String] then finishMap["transactionIdentifier"] wouldn't be allowed to be null, right?
But if finishMap["transactionIdentifier"] is null and a transaction in pendingTransactions also has a null transactionIdentifier then that would also be a valid transaction. If we had [String:String] then we couldn't check that?

Copy link
Contributor Author

@LouiseHsu LouiseHsu May 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can see on the dart side that the finishMap arg it gets called with has [String:String?] as well - I genuinely do not think it would be correct to make it [String:String]. Once this gets converted to using Swift pigeon, I can change it from String:Any to String:String?, so this should be temporary

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

finishMap should be [String:String?] because finishMap["transactionIdentifier"] should be allowed to be null.
If it's just [String:String] then finishMap["transactionIdentifier"] wouldn't be allowed to be null, right?

Not really. dict[key] always returns optional. If type of finishMap is [String:String], then the type of finishMap["transactionIdentifier"] would be String?.

If you use [String:String?] as the type, then finishMap["transactionIdentifier"] would be String?? (double optional).

@@ -144,28 +144,6 @@ - (instancetype)initWithMap:(NSDictionary *)map {

@end

@interface InAppPurchasePluginStub ()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This plugin stub needed to be converted to swift as you cannot subclass a swift class in objective C.

@LouiseHsu LouiseHsu marked this pull request as ready for review April 18, 2024 19:54
@hellohuanlin
Copy link
Contributor

Could you run formatter first so it's easier for review?

@LouiseHsu LouiseHsu requested a review from jmagman April 24, 2024 18:31
Copy link
Contributor

@hellohuanlin hellohuanlin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I briefly looked at the code and did not look into the details. I have to stop early as it's getting long, and there are enough feedback already.


public func handleTransactionsRemoved(_ transactions: [SKPaymentTransaction]) {
var maps: [[AnyHashable: Any]] = []
for transaction in transactions {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here.

return value is NSNull ? nil : value
}

func getRefreshReceiptRequest(properties: [String: Any]?) -> SKReceiptRefreshRequest {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are these helpers only used inside this file? should use private if that's the case.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these need to be not private so they can be overriden for testing purposes
Like here:

override func getProductRequest(withIdentifiers productIdentifiers: Set<String>)

//

#import "Stubs.h"
#import "Stubs.m"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is it importing the .m file?

@@ -238,7 +238,7 @@ abstract class InAppPurchaseAPI {
SKProductsResponseMessage startProductRequest(
List<String> productIdentifiers);

void finishTransaction(Map<String, String?> finishMap);
void finishTransaction(Map<String, Object?> finishMap);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

im confused. why is NSString generic?

@LouiseHsu LouiseHsu marked this pull request as draft April 24, 2024 19:52
@jmagman
Copy link
Member

jmagman commented Apr 30, 2024

SwiftGeneratePch normal arm64 Compiling\ bridging\ header (in target 'RunnerTests' from project 'Runner')
    cd /Volumes/Work/s/w/ir/x/w/packages/packages/in_app_purchase/in_app_purchase_storekit/example/macos
    builtin-swiftTaskExecution -- /Volumes/Work/s/w/ir/cache/osx_sdk/xcode_15a240d/XCode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-frontend -frontend -target arm64-apple-macos10.15 -Xllvm -aarch64-use-tbi -enable-objc-interop -stack-check -sdk /Volumes/Work/s/w/ir/cache/osx_sdk/xcode_15a240d/XCode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.0.sdk -I /Users/chrome-bot/Library/Developer/Xcode/DerivedData/Runner-cqhwqvjiontyvddtpbfbwdhoqskw/Build/Products/Debug -I /Volumes/Work/s/w/ir/cache/osx_sdk/xcode_15a240d/XCode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/lib -F /Users/chrome-bot/Library/Developer/Xcode/DerivedData/Runner-cqhwqvjiontyvddtpbfbwdhoqskw/Build/Products/Debug -F /Users/chrome-bot/Library/Developer/Xcode/DerivedData/Runner-cqhwqvjiontyvddtpbfbwdhoqskw/Build/Products/Debug/in_app_purchase_storekit -F /Users/chrome-bot/Library/Developer/Xcode/DerivedData/Runner-cqhwqvjiontyvddtpbfbwdhoqskw/Build/Products/Debug/shared_preferences_foundation -F /Volumes/Work/s/w/ir/cache/osx_sdk/xcode_15a240d/XCode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks -F /Users/chrome-bot/Library/Developer/Xcode/DerivedData/Runner-cqhwqvjiontyvddtpbfbwdhoqskw/Build/Products/Debug/OCMock -F /Users/chrome-bot/Library/Developer/Xcode/DerivedData/Runner-cqhwqvjiontyvddtpbfbwdhoqskw/Build/Products/Debug/in_app_purchase_storekit -F /Users/chrome-bot/Library/Developer/Xcode/DerivedData/Runner-cqhwqvjiontyvddtpbfbwdhoqskw/Build/Products/Debug/shared_preferences_foundation -no-color-diagnostics -enable-testing -g -module-cache-path /Users/chrome-bot/Library/Developer/Xcode/DerivedData/ModuleCache.noindex -swift-version 5 -enforce-exclusivity\=checked -Onone -D DEBUG -D COCOAPODS -D COCOAPODS -serialize-debugging-options -const-gather-protocols-file /Users/chrome-bot/Library/Developer/Xcode/DerivedData/Runner-cqhwqvjiontyvddtpbfbwdhoqskw/Build/Intermediates.noindex/Runner.build/Debug/RunnerTests.build/Objects-normal/arm64/RunnerTests_const_extract_protocols.json -enable-bare-slash-regex -empty-abi-descriptor -validate-clang-modules-once -clang-build-session-file /Users/chrome-bot/Library/Developer/Xcode/DerivedData/ModuleCache.noindex/Session.modulevalidation -Xcc -working-directory -Xcc /Volumes/Work/s/w/ir/x/w/packages/packages/in_app_purchase/in_app_purchase_storekit/example/macos -resource-dir /Volumes/Work/s/w/ir/cache/osx_sdk/xcode_15a240d/XCode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift -enable-anonymous-context-mangled-names -Xcc -fmodule-map-file\=/Volumes/Work/s/w/ir/x/w/packages/packages/in_app_purchase/in_app_purchase_storekit/example/macos/Pods/Headers/Public/in_app_purchase_storekit/in_app_purchase_storekit.modulemap -Xcc -fmodule-map-file\=/Volumes/Work/s/w/ir/x/w/packages/packages/in_app_purchase/in_app_purchase_storekit/example/macos/Pods/Headers/Public/integration_test/integration_test.modulemap -Xcc -fmodule-map-file\=/Volumes/Work/s/w/ir/x/w/packages/packages/in_app_purchase/in_app_purchase_storekit/example/macos/Pods/Headers/Public/shared_preferences_macos/shared_preferences_macos.modulemap -Xcc -ivfsstatcache -Xcc /Users/chrome-bot/Library/Developer/Xcode/DerivedData/SDKStatCaches.noindex/macosx14.0-23A334-edcf116c3e76c79d4aee70e3f10029bc.sdkstatcache -Xcc -I/Users/chrome-bot/Library/Developer/Xcode/DerivedData/Runner-cqhwqvjiontyvddtpbfbwdhoqskw/Build/Intermediates.noindex/Runner.build/Debug/RunnerTests.build/swift-overrides.hmap -Xcc -iquote -Xcc /Users/chrome-bot/Library/Developer/Xcode/DerivedData/Runner-cqhwqvjiontyvddtpbfbwdhoqskw/Build/Intermediates.noindex/Runner.build/Debug/RunnerTests.build/RunnerTests-generated-files.hmap -Xcc -I/Users/chrome-bot/Library/Developer/Xcode/DerivedData/Runner-cqhwqvjiontyvddtpbfbwdhoqskw/Build/Intermediates.noindex/Runner.build/Debug/RunnerTests.build/RunnerTests-own-target-headers.hmap -Xcc -I/Users/chrome-bot/Library/Developer/Xcode/DerivedData/Runner-cqhwqvjiontyvddtpbfbwdhoqskw/Build/Intermediates.noindex/Runner.build/Debug/RunnerTests.build/RunnerTests-all-non-framework-target-headers.hmap -Xcc -ivfsoverlay -Xcc /Users/chrome-bot/Library/Developer/Xcode/DerivedData/Runner-cqhwqvjiontyvddtpbfbwdhoqskw/Build/Intermediates.noindex/Runner.build/Debug/RunnerTests.build/all-product-headers.yaml -Xcc -iquote -Xcc /Users/chrome-bot/Library/Developer/Xcode/DerivedData/Runner-cqhwqvjiontyvddtpbfbwdhoqskw/Build/Intermediates.noindex/Runner.build/Debug/RunnerTests.build/RunnerTests-project-headers.hmap -Xcc -I/Users/chrome-bot/Library/Developer/Xcode/DerivedData/Runner-cqhwqvjiontyvddtpbfbwdhoqskw/Build/Products/Debug/include -Xcc -I/Users/chrome-bot/Library/Developer/Xcode/DerivedData/Runner-cqhwqvjiontyvddtpbfbwdhoqskw/Build/Products/Debug/in_app_purchase_storekit/in_app_purchase_storekit.framework/Headers -Xcc -I/Users/chrome-bot/Library/Developer/Xcode/DerivedData/Runner-cqhwqvjiontyvddtpbfbwdhoqskw/Build/Products/Debug/shared_preferences_foundation/shared_preferences_foundation.framework/Headers -Xcc -I/Users/chrome-bot/Library/Developer/Xcode/DerivedData/Runner-cqhwqvjiontyvddtpbfbwdhoqskw/Build/Products/Debug/OCMock/OCMock.framework/Headers -Xcc -I/Users/chrome-bot/Library/Developer/Xcode/DerivedData/Runner-cqhwqvjiontyvddtpbfbwdhoqskw/Build/Products/Debug/in_app_purchase_storekit/in_app_purchase_storekit.framework/Headers -Xcc -I/Users/chrome-bot/Library/Developer/Xcode/DerivedData/Runner-cqhwqvjiontyvddtpbfbwdhoqskw/Build/Products/Debug/shared_preferences_foundation/shared_preferences_foundation.framework/Headers -Xcc -I/Users/chrome-bot/Library/Developer/Xcode/DerivedData/Runner-cqhwqvjiontyvddtpbfbwdhoqskw/Build/Intermediates.noindex/Runner.build/Debug/RunnerTests.build/DerivedSources-normal/arm64 -Xcc -I/Users/chrome-bot/Library/Developer/Xcode/DerivedData/Runner-cqhwqvjiontyvddtpbfbwdhoqskw/Build/Intermediates.noindex/Runner.build/Debug/RunnerTests.build/DerivedSources/arm64 -Xcc -I/Users/chrome-bot/Library/Developer/Xcode/DerivedData/Runner-cqhwqvjiontyvddtpbfbwdhoqskw/Build/Intermediates.noindex/Runner.build/Debug/RunnerTests.build/DerivedSources -Xcc -DDEBUG\=1 -Xcc -DCOCOAPODS\=1 -Xcc -DCOCOAPODS\=1 -import-objc-header /Volumes/Work/s/w/ir/x/w/packages/packages/in_app_purchase/in_app_purchase_storekit/example/macos/RunnerTests/RunnerTests-Bridging-Header.h -module-name RunnerTests -disable-clang-spi -target-sdk-version 14.0 -target-sdk-name macosx14.0 -external-plugin-path /Volumes/Work/s/w/ir/cache/osx_sdk/xcode_15a240d/XCode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.0.sdk/usr/lib/swift/host/plugins\#/Volumes/Work/s/w/ir/cache/osx_sdk/xcode_15a240d/XCode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.0.sdk/usr/bin/swift-plugin-server -external-plugin-path /Volumes/Work/s/w/ir/cache/osx_sdk/xcode_15a240d/XCode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.0.sdk/usr/local/lib/swift/host/plugins\#/Volumes/Work/s/w/ir/cache/osx_sdk/xcode_15a240d/XCode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.0.sdk/usr/bin/swift-plugin-server -external-plugin-path /Volumes/Work/s/w/ir/cache/osx_sdk/xcode_15a240d/XCode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/lib/swift/host/plugins\#/Volumes/Work/s/w/ir/cache/osx_sdk/xcode_15a240d/XCode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/bin/swift-plugin-server -external-plugin-path /Volumes/Work/s/w/ir/cache/osx_sdk/xcode_15a240d/XCode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/local/lib/swift/host/plugins\#/Volumes/Work/s/w/ir/cache/osx_sdk/xcode_15a240d/XCode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/bin/swift-plugin-server -plugin-path /Volumes/Work/s/w/ir/cache/osx_sdk/xcode_15a240d/XCode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/host/plugins -plugin-path /Volumes/Work/s/w/ir/cache/osx_sdk/xcode_15a240d/XCode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/local/lib/swift/host/plugins -index-store-path /Users/chrome-bot/Library/Developer/Xcode/DerivedData/Runner-cqhwqvjiontyvddtpbfbwdhoqskw/Index.noindex/DataStore -serialize-diagnostics-path /Users/chrome-bot/Library/Developer/Xcode/DerivedData/Runner-cqhwqvjiontyvddtpbfbwdhoqskw/Build/Intermediates.noindex/PrecompiledHeaders/RunnerTests-Bridging-Header-dmi8xq9h13gd.dia /Volumes/Work/s/w/ir/x/w/packages/packages/in_app_purchase/in_app_purchase_storekit/example/macos/RunnerTests/RunnerTests-Bridging-Header.h -index-store-path /Users/chrome-bot/Library/Developer/Xcode/DerivedData/Runner-cqhwqvjiontyvddtpbfbwdhoqskw/Index.noindex/DataStore -emit-pch -pch-output-dir /Users/chrome-bot/Library/Developer/Xcode/DerivedData/Runner-cqhwqvjiontyvddtpbfbwdhoqskw/Build/Intermediates.noindex/PrecompiledHeaders
<unknown>:0: error: module map file '/Volumes/Work/s/w/ir/x/w/packages/packages/in_app_purchase/in_app_purchase_storekit/example/macos/Pods/Headers/Public/in_app_purchase_storekit/in_app_purchase_storekit.modulemap' not found
<unknown>:0: error: module map file '/Volumes/Work/s/w/ir/x/w/packages/packages/in_app_purchase/in_app_purchase_storekit/example/macos/Pods/Headers/Public/integration_test/integration_test.modulemap' not found
<unknown>:0: error: module map file '/Volumes/Work/s/w/ir/x/w/packages/packages/in_app_purchase/in_app_purchase_storekit/example/macos/Pods/Headers/Public/shared_preferences_macos/shared_preferences_macos.modulemap' not found
Command SwiftGeneratePch emitted errors but did not return a nonzero exit code to indicate failure

https://logs.chromium.org/logs/flutter/buildbucket/cr-buildbucket/8749646386009370081/+/u/Run_package_tests/native_test/stdout

I believe the OTHER_SWIFT_FLAGS in the macOS project is set up incorrectly:

OTHER_SWIFT_FLAGS = "$(inherited) -D COCOAPODS -Xcc -fmodule-map-file=\"${PODS_ROOT}/Headers/Public/in_app_purchase_storekit/in_app_purchase_storekit.modulemap\" -Xcc -fmodule-map-file=\"${PODS_ROOT}/Headers/Public/integration_test/integration_test.modulemap\" -Xcc -fmodule-map-file=\"${PODS_ROOT}/Headers/Public/shared_preferences_macos/shared_preferences_macos.modulemap\"";

From the original commit of the project:
https://github.com/flutter/plugins/pull/6517/files#diff-0baa9bfc86ab566e4f94f744d8fa57d187570868e84706c04b21b8ced0a6fedaR769

@@ -773,7 +773,6 @@
MARKETING_VERSION = 1.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
OTHER_SWIFT_FLAGS = "$(inherited) -D COCOAPODS -Xcc -fmodule-map-file=\"${PODS_ROOT}/Headers/Public/in_app_purchase_storekit/in_app_purchase_storekit.modulemap\" -Xcc -fmodule-map-file=\"${PODS_ROOT}/Headers/Public/integration_test/integration_test.modulemap\" -Xcc -fmodule-map-file=\"${PODS_ROOT}/Headers/Public/shared_preferences_macos/shared_preferences_macos.modulemap\"";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are two more of these I believe, one for each configuration.

@LouiseHsu LouiseHsu marked this pull request as ready for review May 2, 2024 23:37
@hellohuanlin
Copy link
Contributor

is it ready for another review?

@LouiseHsu
Copy link
Contributor Author

is it ready for another review?

@hellohuanlin Yeah, please take a look when you can!

@@ -1,7 +1,7 @@
// 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.
// Autogenerated from Pigeon (v16.0.4), do not edit directly.
// Autogenerated from Pigeon (v16.0.5), do not edit directly.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this bump required for this pr?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, it just gets regenerated. is it worth going down a version to avoid these comment changes?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to regenerate. just don't check-in the changes that's not related to this PR.

@@ -238,7 +238,7 @@ abstract class InAppPurchaseAPI {
SKProductsResponseMessage startProductRequest(
List<String> productIdentifiers);

void finishTransaction(Map<String, String?> finishMap);
void finishTransaction(Map<String, Object?> finishMap);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

^ this

return value is NSNull ? nil : value
}

func getRefreshReceiptRequest(properties: [String: Any]?) -> SKReceiptRefreshRequest {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this

Copy link
Contributor

@hellohuanlin hellohuanlin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I started the review, but unless im mistaken, it looks like a few previous comments have not been addressed. can you make sure all previous comments are addressed before i continue?

#endif

public class InAppPurchasePlugin: NSObject, FlutterPlugin, InAppPurchaseAPI {
// Properties
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need this comment

Copy link
Contributor

@hellohuanlin hellohuanlin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Getting very close

@@ -238,7 +238,7 @@ abstract class InAppPurchaseAPI {
SKProductsResponseMessage startProductRequest(
List<String> productIdentifiers);

void finishTransaction(Map<String, String?> finishMap);
void finishTransaction(Map<String, Object?> finishMap);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using Any to represent an optional can be error-prone.
Why do you want [String:String?]? Is there any issue with using [String:String]?

Copy link
Contributor

@hellohuanlin hellohuanlin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thanks for making all the changes! Please make sure to manually test out if the feature still works as expected.

@LouiseHsu LouiseHsu merged commit 2f35b83 into flutter:main May 14, 2024
74 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants