@whop/elements-react-native 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +179 -0
- package/android/build.gradle +64 -0
- package/android/consumer-rules.pro +3 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/java/com/whop/elements/WhopAddressSuggestionsModule.kt +102 -0
- package/android/src/main/java/com/whop/elements/WhopAuthSessionModule.kt +126 -0
- package/android/src/main/java/com/whop/elements/WhopElementsPackage.kt +39 -0
- package/android/src/main/java/com/whop/elements/WhopPayButtonManager.kt +74 -0
- package/android/src/main/java/com/whop/elements/WhopPayButtonPressEvent.kt +17 -0
- package/android/src/main/java/com/whop/elements/WhopPayButtonView.kt +178 -0
- package/android/src/main/java/com/whop/elements/WhopPlatformPayModule.kt +212 -0
- package/assets/whop-wordmark-dark.png +0 -0
- package/assets/whop-wordmark-dark@2x.png +0 -0
- package/assets/whop-wordmark-dark@3x.png +0 -0
- package/assets/whop-wordmark-light.png +0 -0
- package/assets/whop-wordmark-light@2x.png +0 -0
- package/assets/whop-wordmark-light@3x.png +0 -0
- package/ios/Package.swift +59 -0
- package/ios/Sources/ElementsReactNative/WhopAddressSuggestionsImpl.swift +189 -0
- package/ios/Sources/ElementsReactNative/WhopAuthSessionImpl.swift +106 -0
- package/ios/Sources/ElementsReactNative/WhopPayButtonImpl.swift +89 -0
- package/ios/Sources/ElementsReactNative/WhopPlatformPayImpl.swift +181 -0
- package/ios/generated/WhopAddressSuggestionsModule.h +11 -0
- package/ios/generated/WhopAddressSuggestionsModule.mm +46 -0
- package/ios/generated/WhopAuthSessionModule.h +11 -0
- package/ios/generated/WhopAuthSessionModule.mm +45 -0
- package/ios/generated/WhopElementsShims.h +35 -0
- package/ios/generated/WhopPayButtonComponentView.h +12 -0
- package/ios/generated/WhopPayButtonComponentView.mm +82 -0
- package/ios/generated/WhopPlatformPayModule.h +11 -0
- package/ios/generated/WhopPlatformPayModule.mm +51 -0
- package/lib/module/api/client.js +139 -0
- package/lib/module/api/client.js.map +1 -0
- package/lib/module/api/client.test.js +137 -0
- package/lib/module/api/client.test.js.map +1 -0
- package/lib/module/api/types.js +2 -0
- package/lib/module/api/types.js.map +1 -0
- package/lib/module/controller/actions.js +148 -0
- package/lib/module/controller/actions.js.map +1 -0
- package/lib/module/controller/actions.test.js +102 -0
- package/lib/module/controller/actions.test.js.map +1 -0
- package/lib/module/controller/store.js +158 -0
- package/lib/module/controller/store.js.map +1 -0
- package/lib/module/core/address/country-data.js +1370 -0
- package/lib/module/core/address/country-data.js.map +1 -0
- package/lib/module/core/address/country-name.js +38 -0
- package/lib/module/core/address/country-name.js.map +1 -0
- package/lib/module/core/address/country-names.generated.js +249 -0
- package/lib/module/core/address/country-names.generated.js.map +1 -0
- package/lib/module/core/address/engine.js +245 -0
- package/lib/module/core/address/engine.js.map +1 -0
- package/lib/module/core/address/engine.test.js +216 -0
- package/lib/module/core/address/engine.test.js.map +1 -0
- package/lib/module/core/address/form-state.js +409 -0
- package/lib/module/core/address/form-state.js.map +1 -0
- package/lib/module/core/address/form-state.test.js +516 -0
- package/lib/module/core/address/form-state.test.js.map +1 -0
- package/lib/module/core/address/places.js +36 -0
- package/lib/module/core/address/places.js.map +1 -0
- package/lib/module/core/address/required-coverage.test.js +57 -0
- package/lib/module/core/address/required-coverage.test.js.map +1 -0
- package/lib/module/core/address/suggest.js +102 -0
- package/lib/module/core/address/suggest.js.map +1 -0
- package/lib/module/core/address/suggest.test.js +156 -0
- package/lib/module/core/address/suggest.test.js.map +1 -0
- package/lib/module/core/address/use-suggestions.js +33 -0
- package/lib/module/core/address/use-suggestions.js.map +1 -0
- package/lib/module/core/payments/address-change.js +91 -0
- package/lib/module/core/payments/address-change.js.map +1 -0
- package/lib/module/core/payments/billing-merge.js +62 -0
- package/lib/module/core/payments/billing-merge.js.map +1 -0
- package/lib/module/core/payments/browser-info.js +42 -0
- package/lib/module/core/payments/browser-info.js.map +1 -0
- package/lib/module/core/payments/bt.js +151 -0
- package/lib/module/core/payments/bt.js.map +1 -0
- package/lib/module/core/payments/bt.test.js +23 -0
- package/lib/module/core/payments/bt.test.js.map +1 -0
- package/lib/module/core/payments/currency.js +37 -0
- package/lib/module/core/payments/currency.js.map +1 -0
- package/lib/module/core/payments/detail.js +159 -0
- package/lib/module/core/payments/detail.js.map +1 -0
- package/lib/module/core/payments/detail.test.js +225 -0
- package/lib/module/core/payments/detail.test.js.map +1 -0
- package/lib/module/core/payments/errors.js +115 -0
- package/lib/module/core/payments/errors.js.map +1 -0
- package/lib/module/core/payments/mint.js +89 -0
- package/lib/module/core/payments/mint.js.map +1 -0
- package/lib/module/core/payments/plan.js +131 -0
- package/lib/module/core/payments/plan.js.map +1 -0
- package/lib/module/core/payments/refusals.js +17 -0
- package/lib/module/core/payments/refusals.js.map +1 -0
- package/lib/module/core/payments/secure-fields.js +87 -0
- package/lib/module/core/payments/secure-fields.js.map +1 -0
- package/lib/module/core/payments/tax-id-catalog.js +616 -0
- package/lib/module/core/payments/tax-id-catalog.js.map +1 -0
- package/lib/module/core/payments/wallet-contact.js +42 -0
- package/lib/module/core/payments/wallet-contact.js.map +1 -0
- package/lib/module/core/payments/wallet-contact.test.js +77 -0
- package/lib/module/core/payments/wallet-contact.test.js.map +1 -0
- package/lib/module/elements/address.js +467 -0
- package/lib/module/elements/address.js.map +1 -0
- package/lib/module/elements/branding.js +114 -0
- package/lib/module/elements/branding.js.map +1 -0
- package/lib/module/elements/card-fields/context.js +254 -0
- package/lib/module/elements/card-fields/context.js.map +1 -0
- package/lib/module/elements/card-fields/fields.js +309 -0
- package/lib/module/elements/card-fields/fields.js.map +1 -0
- package/lib/module/elements/card-fields/index.js +30 -0
- package/lib/module/elements/card-fields/index.js.map +1 -0
- package/lib/module/elements/card.js +107 -0
- package/lib/module/elements/card.js.map +1 -0
- package/lib/module/elements/email.js +84 -0
- package/lib/module/elements/email.js.map +1 -0
- package/lib/module/elements/payment/declared-fields.js +186 -0
- package/lib/module/elements/payment/declared-fields.js.map +1 -0
- package/lib/module/elements/payment/index.js +448 -0
- package/lib/module/elements/payment/index.js.map +1 -0
- package/lib/module/elements/payment/wallet.js +132 -0
- package/lib/module/elements/payment/wallet.js.map +1 -0
- package/lib/module/elements/tax-id.js +100 -0
- package/lib/module/elements/tax-id.js.map +1 -0
- package/lib/module/i18n/catalogs.js +103 -0
- package/lib/module/i18n/catalogs.js.map +1 -0
- package/lib/module/i18n/index.js +45 -0
- package/lib/module/i18n/index.js.map +1 -0
- package/lib/module/index.js +27 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/namespace.js +174 -0
- package/lib/module/namespace.js.map +1 -0
- package/lib/module/native/index.js +128 -0
- package/lib/module/native/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/provider.js +56 -0
- package/lib/module/provider.js.map +1 -0
- package/lib/module/specs/NativeWhopAddressSuggestions.js +6 -0
- package/lib/module/specs/NativeWhopAddressSuggestions.js.map +1 -0
- package/lib/module/specs/NativeWhopAuthSession.js +10 -0
- package/lib/module/specs/NativeWhopAuthSession.js.map +1 -0
- package/lib/module/specs/NativeWhopPlatformPay.js +10 -0
- package/lib/module/specs/NativeWhopPlatformPay.js.map +1 -0
- package/lib/module/specs/WhopPayButtonNativeComponent.ts +22 -0
- package/lib/module/theme/appearance.js +85 -0
- package/lib/module/theme/appearance.js.map +1 -0
- package/lib/module/theme/appearance.test.js +124 -0
- package/lib/module/theme/appearance.test.js.map +1 -0
- package/lib/module/theme/provider.js +25 -0
- package/lib/module/theme/provider.js.map +1 -0
- package/lib/module/theme/resolve.js +69 -0
- package/lib/module/theme/resolve.js.map +1 -0
- package/lib/module/theme/scales.generated.js +419 -0
- package/lib/module/theme/scales.generated.js.map +1 -0
- package/lib/module/ui/element-frame.js +83 -0
- package/lib/module/ui/element-frame.js.map +1 -0
- package/lib/module/ui/payment-method-icon.js +69 -0
- package/lib/module/ui/payment-method-icon.js.map +1 -0
- package/lib/module/ui/primitives.js +266 -0
- package/lib/module/ui/primitives.js.map +1 -0
- package/lib/module/ui/select.js +281 -0
- package/lib/module/ui/select.js.map +1 -0
- package/lib/module/ui/suggestions.js +71 -0
- package/lib/module/ui/suggestions.js.map +1 -0
- package/lib/module/ui/whop-logo.js +42 -0
- package/lib/module/ui/whop-logo.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/api/client.d.ts +87 -0
- package/lib/typescript/src/api/client.d.ts.map +1 -0
- package/lib/typescript/src/api/types.d.ts +175 -0
- package/lib/typescript/src/api/types.d.ts.map +1 -0
- package/lib/typescript/src/controller/actions.d.ts +42 -0
- package/lib/typescript/src/controller/actions.d.ts.map +1 -0
- package/lib/typescript/src/controller/store.d.ts +90 -0
- package/lib/typescript/src/controller/store.d.ts.map +1 -0
- package/lib/typescript/src/core/address/country-data.d.ts +4 -0
- package/lib/typescript/src/core/address/country-data.d.ts.map +1 -0
- package/lib/typescript/src/core/address/country-name.d.ts +2 -0
- package/lib/typescript/src/core/address/country-name.d.ts.map +1 -0
- package/lib/typescript/src/core/address/country-names.generated.d.ts +2 -0
- package/lib/typescript/src/core/address/country-names.generated.d.ts.map +1 -0
- package/lib/typescript/src/core/address/engine.d.ts +97 -0
- package/lib/typescript/src/core/address/engine.d.ts.map +1 -0
- package/lib/typescript/src/core/address/form-state.d.ts +144 -0
- package/lib/typescript/src/core/address/form-state.d.ts.map +1 -0
- package/lib/typescript/src/core/address/places.d.ts +23 -0
- package/lib/typescript/src/core/address/places.d.ts.map +1 -0
- package/lib/typescript/src/core/address/suggest.d.ts +47 -0
- package/lib/typescript/src/core/address/suggest.d.ts.map +1 -0
- package/lib/typescript/src/core/address/use-suggestions.d.ts +3 -0
- package/lib/typescript/src/core/address/use-suggestions.d.ts.map +1 -0
- package/lib/typescript/src/core/payments/address-change.d.ts +52 -0
- package/lib/typescript/src/core/payments/address-change.d.ts.map +1 -0
- package/lib/typescript/src/core/payments/billing-merge.d.ts +39 -0
- package/lib/typescript/src/core/payments/billing-merge.d.ts.map +1 -0
- package/lib/typescript/src/core/payments/browser-info.d.ts +12 -0
- package/lib/typescript/src/core/payments/browser-info.d.ts.map +1 -0
- package/lib/typescript/src/core/payments/bt.d.ts +55 -0
- package/lib/typescript/src/core/payments/bt.d.ts.map +1 -0
- package/lib/typescript/src/core/payments/currency.d.ts +7 -0
- package/lib/typescript/src/core/payments/currency.d.ts.map +1 -0
- package/lib/typescript/src/core/payments/detail.d.ts +53 -0
- package/lib/typescript/src/core/payments/detail.d.ts.map +1 -0
- package/lib/typescript/src/core/payments/errors.d.ts +62 -0
- package/lib/typescript/src/core/payments/errors.d.ts.map +1 -0
- package/lib/typescript/src/core/payments/mint.d.ts +74 -0
- package/lib/typescript/src/core/payments/mint.d.ts.map +1 -0
- package/lib/typescript/src/core/payments/plan.d.ts +69 -0
- package/lib/typescript/src/core/payments/plan.d.ts.map +1 -0
- package/lib/typescript/src/core/payments/refusals.d.ts +12 -0
- package/lib/typescript/src/core/payments/refusals.d.ts.map +1 -0
- package/lib/typescript/src/core/payments/secure-fields.d.ts +33 -0
- package/lib/typescript/src/core/payments/secure-fields.d.ts.map +1 -0
- package/lib/typescript/src/core/payments/tax-id-catalog.d.ts +481 -0
- package/lib/typescript/src/core/payments/tax-id-catalog.d.ts.map +1 -0
- package/lib/typescript/src/core/payments/wallet-contact.d.ts +40 -0
- package/lib/typescript/src/core/payments/wallet-contact.d.ts.map +1 -0
- package/lib/typescript/src/elements/address.d.ts +55 -0
- package/lib/typescript/src/elements/address.d.ts.map +1 -0
- package/lib/typescript/src/elements/branding.d.ts +18 -0
- package/lib/typescript/src/elements/branding.d.ts.map +1 -0
- package/lib/typescript/src/elements/card-fields/context.d.ts +67 -0
- package/lib/typescript/src/elements/card-fields/context.d.ts.map +1 -0
- package/lib/typescript/src/elements/card-fields/fields.d.ts +15 -0
- package/lib/typescript/src/elements/card-fields/fields.d.ts.map +1 -0
- package/lib/typescript/src/elements/card-fields/index.d.ts +21 -0
- package/lib/typescript/src/elements/card-fields/index.d.ts.map +1 -0
- package/lib/typescript/src/elements/card.d.ts +21 -0
- package/lib/typescript/src/elements/card.d.ts.map +1 -0
- package/lib/typescript/src/elements/email.d.ts +31 -0
- package/lib/typescript/src/elements/email.d.ts.map +1 -0
- package/lib/typescript/src/elements/payment/declared-fields.d.ts +43 -0
- package/lib/typescript/src/elements/payment/declared-fields.d.ts.map +1 -0
- package/lib/typescript/src/elements/payment/index.d.ts +37 -0
- package/lib/typescript/src/elements/payment/index.d.ts.map +1 -0
- package/lib/typescript/src/elements/payment/wallet.d.ts +39 -0
- package/lib/typescript/src/elements/payment/wallet.d.ts.map +1 -0
- package/lib/typescript/src/elements/tax-id.d.ts +41 -0
- package/lib/typescript/src/elements/tax-id.d.ts.map +1 -0
- package/lib/typescript/src/i18n/catalogs.d.ts +7 -0
- package/lib/typescript/src/i18n/catalogs.d.ts.map +1 -0
- package/lib/typescript/src/i18n/index.d.ts +17 -0
- package/lib/typescript/src/i18n/index.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +42 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/namespace.d.ts +36 -0
- package/lib/typescript/src/namespace.d.ts.map +1 -0
- package/lib/typescript/src/native/index.d.ts +62 -0
- package/lib/typescript/src/native/index.d.ts.map +1 -0
- package/lib/typescript/src/provider.d.ts +37 -0
- package/lib/typescript/src/provider.d.ts.map +1 -0
- package/lib/typescript/src/specs/NativeWhopAddressSuggestions.d.ts +13 -0
- package/lib/typescript/src/specs/NativeWhopAddressSuggestions.d.ts.map +1 -0
- package/lib/typescript/src/specs/NativeWhopAuthSession.d.ts +20 -0
- package/lib/typescript/src/specs/NativeWhopAuthSession.d.ts.map +1 -0
- package/lib/typescript/src/specs/NativeWhopPlatformPay.d.ts +24 -0
- package/lib/typescript/src/specs/NativeWhopPlatformPay.d.ts.map +1 -0
- package/lib/typescript/src/specs/WhopPayButtonNativeComponent.d.ts +21 -0
- package/lib/typescript/src/specs/WhopPayButtonNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/theme/appearance.d.ts +71 -0
- package/lib/typescript/src/theme/appearance.d.ts.map +1 -0
- package/lib/typescript/src/theme/provider.d.ts +11 -0
- package/lib/typescript/src/theme/provider.d.ts.map +1 -0
- package/lib/typescript/src/theme/resolve.d.ts +19 -0
- package/lib/typescript/src/theme/resolve.d.ts.map +1 -0
- package/lib/typescript/src/theme/scales.generated.d.ts +18 -0
- package/lib/typescript/src/theme/scales.generated.d.ts.map +1 -0
- package/lib/typescript/src/ui/element-frame.d.ts +32 -0
- package/lib/typescript/src/ui/element-frame.d.ts.map +1 -0
- package/lib/typescript/src/ui/payment-method-icon.d.ts +21 -0
- package/lib/typescript/src/ui/payment-method-icon.d.ts.map +1 -0
- package/lib/typescript/src/ui/primitives.d.ts +94 -0
- package/lib/typescript/src/ui/primitives.d.ts.map +1 -0
- package/lib/typescript/src/ui/select.d.ts +25 -0
- package/lib/typescript/src/ui/select.d.ts.map +1 -0
- package/lib/typescript/src/ui/suggestions.d.ts +15 -0
- package/lib/typescript/src/ui/suggestions.d.ts.map +1 -0
- package/lib/typescript/src/ui/whop-logo.d.ts +4 -0
- package/lib/typescript/src/ui/whop-logo.d.ts.map +1 -0
- package/package.json +121 -0
- package/scripts/check-swift.sh +27 -0
- package/scripts/codegen-shims.mjs +409 -0
- package/scripts/gen-country-names.mjs +58 -0
- package/scripts/gen-theme.mjs +124 -0
- package/scripts/gen-wordmark.mjs +68 -0
- package/scripts/mirror.mjs +112 -0
- package/src/api/client.ts +202 -0
- package/src/api/types.ts +166 -0
- package/src/controller/actions.ts +197 -0
- package/src/controller/store.ts +201 -0
- package/src/core/address/country-data.ts +927 -0
- package/src/core/address/country-name.ts +36 -0
- package/src/core/address/country-names.generated.ts +246 -0
- package/src/core/address/engine.ts +349 -0
- package/src/core/address/form-state.ts +479 -0
- package/src/core/address/places.ts +39 -0
- package/src/core/address/suggest.ts +153 -0
- package/src/core/address/use-suggestions.ts +37 -0
- package/src/core/payments/address-change.ts +121 -0
- package/src/core/payments/billing-merge.ts +91 -0
- package/src/core/payments/browser-info.ts +43 -0
- package/src/core/payments/bt.ts +176 -0
- package/src/core/payments/currency.ts +54 -0
- package/src/core/payments/detail.ts +204 -0
- package/src/core/payments/errors.ts +171 -0
- package/src/core/payments/mint.ts +130 -0
- package/src/core/payments/plan.ts +198 -0
- package/src/core/payments/refusals.ts +24 -0
- package/src/core/payments/secure-fields.ts +85 -0
- package/src/core/payments/tax-id-catalog.ts +320 -0
- package/src/core/payments/wallet-contact.ts +56 -0
- package/src/elements/address.tsx +570 -0
- package/src/elements/branding.tsx +87 -0
- package/src/elements/card-fields/context.tsx +310 -0
- package/src/elements/card-fields/fields.tsx +281 -0
- package/src/elements/card-fields/index.tsx +37 -0
- package/src/elements/card.tsx +101 -0
- package/src/elements/email.tsx +100 -0
- package/src/elements/payment/declared-fields.tsx +238 -0
- package/src/elements/payment/index.tsx +497 -0
- package/src/elements/payment/wallet.tsx +155 -0
- package/src/elements/tax-id.tsx +143 -0
- package/src/i18n/catalogs.ts +100 -0
- package/src/i18n/index.tsx +46 -0
- package/src/index.ts +68 -0
- package/src/namespace.tsx +231 -0
- package/src/native/index.ts +173 -0
- package/src/provider.tsx +76 -0
- package/src/specs/NativeWhopAddressSuggestions.ts +14 -0
- package/src/specs/NativeWhopAuthSession.ts +21 -0
- package/src/specs/NativeWhopPlatformPay.ts +25 -0
- package/src/specs/WhopPayButtonNativeComponent.ts +22 -0
- package/src/theme/appearance.ts +150 -0
- package/src/theme/provider.tsx +28 -0
- package/src/theme/resolve.ts +68 -0
- package/src/theme/scales.generated.ts +427 -0
- package/src/ui/element-frame.tsx +94 -0
- package/src/ui/payment-method-icon.tsx +55 -0
- package/src/ui/primitives.tsx +269 -0
- package/src/ui/select.tsx +255 -0
- package/src/ui/suggestions.tsx +69 -0
- package/src/ui/whop-logo.tsx +37 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import AuthenticationServices
|
|
2
|
+
import UIKit
|
|
3
|
+
|
|
4
|
+
/// The redirect and 3DS surface.
|
|
5
|
+
///
|
|
6
|
+
/// `ASWebAuthenticationSession` runs the page in a separate process the host app can neither read
|
|
7
|
+
/// nor script, which is why it is the only acceptable answer here: a `WKWebView` showing a PSP's
|
|
8
|
+
/// 3DS challenge would put the issuer's page inside the app's own trust boundary.
|
|
9
|
+
/// `@unchecked Sendable` with a real invariant, not a silencer: React Native may call a Turbo
|
|
10
|
+
/// module off the main thread, so every method here hops to the main queue and the session state
|
|
11
|
+
/// below is read and written only from there — the completion handler included, since
|
|
12
|
+
/// `ASWebAuthenticationSession` does not document which queue it calls back on.
|
|
13
|
+
@objc(WhopAuthSessionImpl)
|
|
14
|
+
public final class WhopAuthSessionImpl: NSObject, @unchecked Sendable {
|
|
15
|
+
private var session: ASWebAuthenticationSession?
|
|
16
|
+
private var anchorProvider: AnchorProvider?
|
|
17
|
+
/// Bumped by every present(). A completion carries the value it was started with, so a late
|
|
18
|
+
/// one can tell whether the state it is about to clear is still its own.
|
|
19
|
+
private var generation = 0
|
|
20
|
+
|
|
21
|
+
@objc public func isAvailable() -> Bool {
|
|
22
|
+
true
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@objc public func present(
|
|
26
|
+
_ url: String,
|
|
27
|
+
callbackScheme: String?,
|
|
28
|
+
prefersEphemeral: Bool,
|
|
29
|
+
resolve: @escaping @Sendable (Any?) -> Void,
|
|
30
|
+
reject: @escaping @Sendable (String, String) -> Void
|
|
31
|
+
) {
|
|
32
|
+
guard let target = URL(string: url), target.scheme?.lowercased() == "https" else {
|
|
33
|
+
reject("INVALID_URL", "whop elements: an https URL is required")
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
DispatchQueue.main.async { [weak self] in
|
|
38
|
+
guard let self else { return }
|
|
39
|
+
self.cancel()
|
|
40
|
+
self.generation &+= 1
|
|
41
|
+
let generation = self.generation
|
|
42
|
+
|
|
43
|
+
let session = ASWebAuthenticationSession(
|
|
44
|
+
url: target,
|
|
45
|
+
callbackURLScheme: callbackScheme
|
|
46
|
+
) { callbackURL, error in
|
|
47
|
+
// Settling and clearing on the main queue keeps this off a race with a concurrent
|
|
48
|
+
// dismiss(), which is the whole basis of the @unchecked Sendable claim above.
|
|
49
|
+
DispatchQueue.main.async { [weak self] in
|
|
50
|
+
// Clear ONLY if this presentation is still the current one. A completion can
|
|
51
|
+
// land after a later present() has already started a new session, and nilling
|
|
52
|
+
// then would drop the live one: dismiss() could no longer cancel the visible
|
|
53
|
+
// browser. Settling is unconditional, because this promise is this
|
|
54
|
+
// presentation's however stale the presentation is.
|
|
55
|
+
if self?.generation == generation {
|
|
56
|
+
self?.session = nil
|
|
57
|
+
self?.anchorProvider = nil
|
|
58
|
+
}
|
|
59
|
+
if let error = error as? ASWebAuthenticationSessionError,
|
|
60
|
+
error.code == .canceledLogin
|
|
61
|
+
{
|
|
62
|
+
// A dismissal is an outcome, not a failure — handleNextAction's poll is the authority.
|
|
63
|
+
resolve(nil)
|
|
64
|
+
return
|
|
65
|
+
}
|
|
66
|
+
if let error {
|
|
67
|
+
reject("AUTH_SESSION_FAILED", error.localizedDescription)
|
|
68
|
+
return
|
|
69
|
+
}
|
|
70
|
+
resolve(callbackURL?.absoluteString)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
let provider = AnchorProvider()
|
|
75
|
+
self.anchorProvider = provider
|
|
76
|
+
session.presentationContextProvider = provider
|
|
77
|
+
session.prefersEphemeralWebBrowserSession = prefersEphemeral
|
|
78
|
+
|
|
79
|
+
guard session.start() else {
|
|
80
|
+
self.session = nil
|
|
81
|
+
self.anchorProvider = nil
|
|
82
|
+
reject("AUTH_SESSION_FAILED", "whop elements: the system browser could not be presented")
|
|
83
|
+
return
|
|
84
|
+
}
|
|
85
|
+
self.session = session
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
@objc public func dismiss() {
|
|
90
|
+
DispatchQueue.main.async { [weak self] in self?.cancel() }
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
private func cancel() {
|
|
94
|
+
session?.cancel()
|
|
95
|
+
session = nil
|
|
96
|
+
anchorProvider = nil
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
private final class AnchorProvider: NSObject, ASWebAuthenticationPresentationContextProviding {
|
|
101
|
+
func presentationAnchor(for _: ASWebAuthenticationSession) -> ASPresentationAnchor {
|
|
102
|
+
let scenes = UIApplication.shared.connectedScenes.compactMap { $0 as? UIWindowScene }
|
|
103
|
+
let active = scenes.first { $0.activationState == .foregroundActive } ?? scenes.first
|
|
104
|
+
return active?.windows.first { $0.isKeyWindow } ?? active?.windows.first ?? ASPresentationAnchor()
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import PassKit
|
|
2
|
+
import UIKit
|
|
3
|
+
|
|
4
|
+
/// `PKPaymentButton` itself. Apple's Human Interface Guidelines require the system control rather
|
|
5
|
+
/// than a drawn imitation, which is the whole reason this element is a native view.
|
|
6
|
+
@objc(WhopPayButtonImpl)
|
|
7
|
+
public final class WhopPayButtonImpl: UIView {
|
|
8
|
+
@objc public var onPayPress: (() -> Void)?
|
|
9
|
+
|
|
10
|
+
private var variant: PKPaymentButtonType = .plain
|
|
11
|
+
private var style: PKPaymentButtonStyle = .automatic
|
|
12
|
+
private var radius: CGFloat = 8
|
|
13
|
+
private var isDisabled = false
|
|
14
|
+
private var button: PKPaymentButton?
|
|
15
|
+
|
|
16
|
+
@objc override public init(frame: CGRect) {
|
|
17
|
+
super.init(frame: frame)
|
|
18
|
+
rebuild()
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@available(*, unavailable)
|
|
22
|
+
required init?(coder _: NSCoder) {
|
|
23
|
+
fatalError("init(coder:) is unavailable")
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
override public func layoutSubviews() {
|
|
27
|
+
super.layoutSubviews()
|
|
28
|
+
button?.frame = bounds
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
override public var intrinsicContentSize: CGSize {
|
|
32
|
+
CGSize(width: UIView.noIntrinsicMetric, height: 48)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@objc public func setVariant(_ value: String) {
|
|
36
|
+
let next: PKPaymentButtonType
|
|
37
|
+
switch value {
|
|
38
|
+
case "buy": next = .buy
|
|
39
|
+
case "checkout": next = .checkout
|
|
40
|
+
case "book": next = .book
|
|
41
|
+
case "subscribe": next = .subscribe
|
|
42
|
+
case "order": next = .order
|
|
43
|
+
// PassKit has no `.pay`; the verb-less Apple Pay mark is `.plain`.
|
|
44
|
+
default: next = .plain
|
|
45
|
+
}
|
|
46
|
+
guard next != variant else { return }
|
|
47
|
+
variant = next
|
|
48
|
+
rebuild()
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@objc public func setButtonAppearance(_ value: String) {
|
|
52
|
+
let next: PKPaymentButtonStyle
|
|
53
|
+
switch value {
|
|
54
|
+
case "light": next = .white
|
|
55
|
+
case "dark": next = .black
|
|
56
|
+
default: next = .automatic
|
|
57
|
+
}
|
|
58
|
+
guard next != style else { return }
|
|
59
|
+
style = next
|
|
60
|
+
rebuild()
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@objc public func setCornerRadius(_ value: Double) {
|
|
64
|
+
radius = CGFloat(value)
|
|
65
|
+
button?.cornerRadius = radius
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@objc public func setDisabled(_ value: Bool) {
|
|
69
|
+
isDisabled = value
|
|
70
|
+
button?.isEnabled = !value
|
|
71
|
+
alpha = value ? 0.5 : 1
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/// PKPaymentButton takes its type and style at init only, so a prop change is a fresh button.
|
|
75
|
+
private func rebuild() {
|
|
76
|
+
button?.removeFromSuperview()
|
|
77
|
+
let next = PKPaymentButton(paymentButtonType: variant, paymentButtonStyle: style)
|
|
78
|
+
next.cornerRadius = radius
|
|
79
|
+
next.isEnabled = !isDisabled
|
|
80
|
+
next.addTarget(self, action: #selector(handlePress), for: .touchUpInside)
|
|
81
|
+
next.frame = bounds
|
|
82
|
+
addSubview(next)
|
|
83
|
+
button = next
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
@objc private func handlePress() {
|
|
87
|
+
onPayPress?()
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import Contacts
|
|
2
|
+
import Foundation
|
|
3
|
+
import PassKit
|
|
4
|
+
|
|
5
|
+
/// Apple Pay, through PassKit.
|
|
6
|
+
///
|
|
7
|
+
/// The web element runs a merchant-validation round trip against whop.com and refuses to render a
|
|
8
|
+
/// button whose sheet is doomed, because a browser must prove the origin. PassKit replaces all of
|
|
9
|
+
/// that with the app's own merchant identifier and on-device certificate, so none of those gates
|
|
10
|
+
/// exist here. What crosses back is `PKPaymentToken.paymentData` — the same bytes the web path
|
|
11
|
+
/// posts to Basis Theory as a token intent.
|
|
12
|
+
/// `@unchecked Sendable` with a real invariant, not a silencer: React Native may call a Turbo
|
|
13
|
+
/// module off the main thread, so every method here hops to the main queue and all mutable state
|
|
14
|
+
/// below is read and written only from there. PassKit's own delegate callbacks arrive on the main
|
|
15
|
+
/// thread too, so the invariant holds end to end.
|
|
16
|
+
@objc(WhopPlatformPayImpl)
|
|
17
|
+
public final class WhopPlatformPayImpl: NSObject, @unchecked Sendable {
|
|
18
|
+
private var controller: PKPaymentAuthorizationController?
|
|
19
|
+
private var pendingResolve: (@Sendable (Any?) -> Void)?
|
|
20
|
+
private var completion: ((PKPaymentAuthorizationResult) -> Void)?
|
|
21
|
+
|
|
22
|
+
@objc public func capability() -> String {
|
|
23
|
+
PKPaymentAuthorizationController.canMakePayments() ? "apple" : "none"
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@objc public func canPay(
|
|
27
|
+
_ configJson: String,
|
|
28
|
+
resolve: @escaping @Sendable (Any?) -> Void,
|
|
29
|
+
reject: @escaping @Sendable (String, String) -> Void
|
|
30
|
+
) {
|
|
31
|
+
guard let config: SheetConfig = decode(configJson) else {
|
|
32
|
+
reject("INVALID_CONFIG", "whop elements: could not decode the wallet config")
|
|
33
|
+
return
|
|
34
|
+
}
|
|
35
|
+
let networks = config.networks.compactMap(Self.network(from:))
|
|
36
|
+
resolve(PKPaymentAuthorizationController.canMakePayments(usingNetworks: networks))
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@objc public func present(
|
|
40
|
+
_ requestJson: String,
|
|
41
|
+
resolve: @escaping @Sendable (Any?) -> Void,
|
|
42
|
+
reject: @escaping @Sendable (String, String) -> Void
|
|
43
|
+
) {
|
|
44
|
+
guard let request: SheetRequest = decode(requestJson) else {
|
|
45
|
+
reject("INVALID_REQUEST", "whop elements: could not decode the wallet request")
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
let payment = PKPaymentRequest()
|
|
50
|
+
payment.merchantIdentifier = request.merchantIdentifier
|
|
51
|
+
payment.countryCode = request.countryCode
|
|
52
|
+
payment.currencyCode = request.currencyCode.uppercased()
|
|
53
|
+
payment.merchantCapabilities = .threeDSecure
|
|
54
|
+
payment.supportedNetworks = request.networks.compactMap(Self.network(from:))
|
|
55
|
+
payment.requiredBillingContactFields = request.requiresBillingAddress ? [.postalAddress, .name] : [.name]
|
|
56
|
+
if request.requiresEmail { payment.requiredShippingContactFields = [.emailAddress] }
|
|
57
|
+
payment.paymentSummaryItems = request.lineItems.map {
|
|
58
|
+
PKPaymentSummaryItem(label: $0.label, amount: NSDecimalNumber(string: $0.amount))
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
DispatchQueue.main.async { [weak self] in
|
|
62
|
+
guard let self else { return }
|
|
63
|
+
let controller = PKPaymentAuthorizationController(paymentRequest: payment)
|
|
64
|
+
controller.delegate = self
|
|
65
|
+
self.controller = controller
|
|
66
|
+
self.pendingResolve = resolve
|
|
67
|
+
controller.present { presented in
|
|
68
|
+
guard !presented else { return }
|
|
69
|
+
self.pendingResolve = nil
|
|
70
|
+
self.controller = nil
|
|
71
|
+
reject("SHEET_UNAVAILABLE", "whop elements: the Apple Pay sheet could not be presented")
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/// The sheet's verdict follows the CONFIRM outcome, not the tokenization — a refused confirm has
|
|
77
|
+
/// to land in-sheet as a failure rather than after a checkmark.
|
|
78
|
+
@objc public func complete(_ success: Bool) {
|
|
79
|
+
DispatchQueue.main.async { [weak self] in
|
|
80
|
+
guard let self, let completion = self.completion else { return }
|
|
81
|
+
self.completion = nil
|
|
82
|
+
completion(PKPaymentAuthorizationResult(status: success ? .success : .failure, errors: nil))
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
private func decode<T: Decodable>(_ json: String) -> T? {
|
|
87
|
+
guard let data = json.data(using: .utf8) else { return nil }
|
|
88
|
+
return try? JSONDecoder().decode(T.self, from: data)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
private static func network(from raw: String) -> PKPaymentNetwork? {
|
|
92
|
+
switch raw.lowercased() {
|
|
93
|
+
case "visa": return .visa
|
|
94
|
+
case "mastercard", "master-card": return .masterCard
|
|
95
|
+
case "amex", "american-express": return .amex
|
|
96
|
+
case "discover": return .discover
|
|
97
|
+
case "jcb": return .JCB
|
|
98
|
+
case "maestro": return .maestro
|
|
99
|
+
case "elo": return .elo
|
|
100
|
+
case "mir": return .mir
|
|
101
|
+
case "cartes-bancaires", "cartesbancaires": return .cartesBancaires
|
|
102
|
+
default: return nil
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
extension WhopPlatformPayImpl: PKPaymentAuthorizationControllerDelegate {
|
|
108
|
+
public func paymentAuthorizationController(
|
|
109
|
+
_: PKPaymentAuthorizationController,
|
|
110
|
+
didAuthorizePayment payment: PKPayment,
|
|
111
|
+
handler: @escaping (PKPaymentAuthorizationResult) -> Void
|
|
112
|
+
) {
|
|
113
|
+
completion = handler
|
|
114
|
+
let resolve = pendingResolve
|
|
115
|
+
pendingResolve = nil
|
|
116
|
+
resolve?(Self.envelope(for: payment))
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/// The token PLUS the contact fields the sheet collected.
|
|
120
|
+
///
|
|
121
|
+
/// Apple gathers these only because `present` asked for them, and it asks precisely when no
|
|
122
|
+
/// email or address element is mounted — so they are the only copy that exists. Returning bare
|
|
123
|
+
/// `paymentData` discarded them, and the mint then refused a buyer who had just typed their
|
|
124
|
+
/// email into the sheet.
|
|
125
|
+
private static func envelope(for payment: PKPayment) -> String {
|
|
126
|
+
let raw = String(data: payment.token.paymentData, encoding: .utf8)
|
|
127
|
+
var bag: [String: Any] = [:]
|
|
128
|
+
if let raw { bag["paymentData"] = raw }
|
|
129
|
+
if let email = payment.shippingContact?.emailAddress ?? payment.billingContact?.emailAddress {
|
|
130
|
+
bag["email"] = email
|
|
131
|
+
}
|
|
132
|
+
if let components = payment.billingContact?.name {
|
|
133
|
+
let name = PersonNameComponentsFormatter.localizedString(from: components, style: .default)
|
|
134
|
+
if !name.isEmpty { bag["name"] = name }
|
|
135
|
+
}
|
|
136
|
+
if let postal = payment.billingContact?.postalAddress {
|
|
137
|
+
var address: [String: String] = [:]
|
|
138
|
+
// CNPostalAddress.street is the whole street block, newline separated.
|
|
139
|
+
let street = postal.street.split(separator: "\n").map(String.init)
|
|
140
|
+
if let line1 = street.first, !line1.isEmpty { address["line1"] = line1 }
|
|
141
|
+
if street.count > 1 { address["line2"] = street.dropFirst().joined(separator: " ") }
|
|
142
|
+
if !postal.city.isEmpty { address["city"] = postal.city }
|
|
143
|
+
if !postal.state.isEmpty { address["state"] = postal.state }
|
|
144
|
+
if !postal.postalCode.isEmpty { address["postal_code"] = postal.postalCode }
|
|
145
|
+
if !postal.isoCountryCode.isEmpty { address["country"] = postal.isoCountryCode.uppercased() }
|
|
146
|
+
if !address.isEmpty { bag["address"] = address }
|
|
147
|
+
}
|
|
148
|
+
guard let data = try? JSONSerialization.data(withJSONObject: bag),
|
|
149
|
+
let json = String(data: data, encoding: .utf8)
|
|
150
|
+
else { return raw ?? "" }
|
|
151
|
+
return json
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
public func paymentAuthorizationControllerDidFinish(_ controller: PKPaymentAuthorizationController) {
|
|
155
|
+
controller.dismiss(completion: nil)
|
|
156
|
+
self.controller = nil
|
|
157
|
+
// Dismissed before authorizing: settle the promise so the JS side is never left hanging.
|
|
158
|
+
let resolve = pendingResolve
|
|
159
|
+
pendingResolve = nil
|
|
160
|
+
resolve?(nil)
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
private struct SheetConfig: Decodable {
|
|
165
|
+
let networks: [String]
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
private struct SheetRequest: Decodable {
|
|
169
|
+
struct LineItem: Decodable {
|
|
170
|
+
let label: String
|
|
171
|
+
let amount: String
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
let merchantIdentifier: String
|
|
175
|
+
let countryCode: String
|
|
176
|
+
let currencyCode: String
|
|
177
|
+
let networks: [String]
|
|
178
|
+
let lineItems: [LineItem]
|
|
179
|
+
let requiresBillingAddress: Bool
|
|
180
|
+
let requiresEmail: Bool
|
|
181
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// GENERATED by scripts/codegen-shims.mjs — do not edit, do not commit.
|
|
2
|
+
// Source of truth: src/specs/. Implementations are Swift, in ios/Sources/WhopElements.
|
|
3
|
+
|
|
4
|
+
#import <WhopElementsSpec/WhopElementsSpec.h>
|
|
5
|
+
|
|
6
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
7
|
+
|
|
8
|
+
@interface WhopAddressSuggestionsModule : NSObject <NativeWhopAddressSuggestionsSpec>
|
|
9
|
+
@end
|
|
10
|
+
|
|
11
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// GENERATED by scripts/codegen-shims.mjs — do not edit, do not commit.
|
|
2
|
+
// Source of truth: src/specs/. Implementations are Swift, in ios/Sources/WhopElements.
|
|
3
|
+
|
|
4
|
+
#import "WhopAddressSuggestionsModule.h"
|
|
5
|
+
#import "WhopElementsShims.h"
|
|
6
|
+
|
|
7
|
+
@implementation WhopAddressSuggestionsModule {
|
|
8
|
+
WhopAddressSuggestionsImpl *_impl;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// The JS name, explicitly: bare RCT_EXPORT_MODULE() registers under the CLASS name
|
|
12
|
+
// ("WhopAddressSuggestionsModule"), and TurboModuleRegistry then cannot find "WhopAddressSuggestions".
|
|
13
|
+
RCT_EXPORT_MODULE(WhopAddressSuggestions)
|
|
14
|
+
|
|
15
|
+
- (instancetype)init
|
|
16
|
+
{
|
|
17
|
+
if (self = [super init]) {
|
|
18
|
+
_impl = [WhopAddressSuggestionsImpl new];
|
|
19
|
+
}
|
|
20
|
+
return self;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
|
24
|
+
(const facebook::react::ObjCTurboModule::InitParams &)params
|
|
25
|
+
{
|
|
26
|
+
return std::make_shared<facebook::react::NativeWhopAddressSuggestionsSpecJSI>(params);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
- (NSNumber *)isAvailable
|
|
30
|
+
{
|
|
31
|
+
return @([_impl isAvailable]);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
- (void)suggest:(NSString *)query resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
|
|
35
|
+
{
|
|
36
|
+
[_impl suggest:query resolve:^(id _Nullable value) { resolve(value); }
|
|
37
|
+
reject:^(NSString *code, NSString *message) { reject(code, message, nil); }];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
- (void)details:(NSString *)suggestionId resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
|
|
41
|
+
{
|
|
42
|
+
[_impl details:suggestionId resolve:^(id _Nullable value) { resolve(value); }
|
|
43
|
+
reject:^(NSString *code, NSString *message) { reject(code, message, nil); }];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// GENERATED by scripts/codegen-shims.mjs — do not edit, do not commit.
|
|
2
|
+
// Source of truth: src/specs/. Implementations are Swift, in ios/Sources/WhopElements.
|
|
3
|
+
|
|
4
|
+
#import <WhopElementsSpec/WhopElementsSpec.h>
|
|
5
|
+
|
|
6
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
7
|
+
|
|
8
|
+
@interface WhopAuthSessionModule : NSObject <NativeWhopAuthSessionSpec>
|
|
9
|
+
@end
|
|
10
|
+
|
|
11
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// GENERATED by scripts/codegen-shims.mjs — do not edit, do not commit.
|
|
2
|
+
// Source of truth: src/specs/. Implementations are Swift, in ios/Sources/WhopElements.
|
|
3
|
+
|
|
4
|
+
#import "WhopAuthSessionModule.h"
|
|
5
|
+
#import "WhopElementsShims.h"
|
|
6
|
+
|
|
7
|
+
@implementation WhopAuthSessionModule {
|
|
8
|
+
WhopAuthSessionImpl *_impl;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// The JS name, explicitly: bare RCT_EXPORT_MODULE() registers under the CLASS name
|
|
12
|
+
// ("WhopAuthSessionModule"), and TurboModuleRegistry then cannot find "WhopAuthSession".
|
|
13
|
+
RCT_EXPORT_MODULE(WhopAuthSession)
|
|
14
|
+
|
|
15
|
+
- (instancetype)init
|
|
16
|
+
{
|
|
17
|
+
if (self = [super init]) {
|
|
18
|
+
_impl = [WhopAuthSessionImpl new];
|
|
19
|
+
}
|
|
20
|
+
return self;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
|
24
|
+
(const facebook::react::ObjCTurboModule::InitParams &)params
|
|
25
|
+
{
|
|
26
|
+
return std::make_shared<facebook::react::NativeWhopAuthSessionSpecJSI>(params);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
- (NSNumber *)isAvailable
|
|
30
|
+
{
|
|
31
|
+
return @([_impl isAvailable]);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
- (void)present:(NSString *)url callbackScheme:(NSString * _Nullable)callbackScheme prefersEphemeral:(BOOL)prefersEphemeral resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
|
|
35
|
+
{
|
|
36
|
+
[_impl present:url callbackScheme:callbackScheme prefersEphemeral:prefersEphemeral resolve:^(id _Nullable value) { resolve(value); }
|
|
37
|
+
reject:^(NSString *code, NSString *message) { reject(code, message, nil); }];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
- (void)dismiss
|
|
41
|
+
{
|
|
42
|
+
[_impl dismiss];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// GENERATED by scripts/codegen-shims.mjs — do not edit, do not commit.
|
|
2
|
+
// Source of truth: src/specs/. Implementations are Swift, in ios/Sources/WhopElements.
|
|
3
|
+
|
|
4
|
+
#import <UIKit/UIKit.h>
|
|
5
|
+
|
|
6
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
7
|
+
|
|
8
|
+
@interface WhopPayButtonImpl : UIView
|
|
9
|
+
@property (nonatomic, copy, nullable) void (^onPayPress)(void);
|
|
10
|
+
- (void)setVariant:(NSString * _Nonnull)value;
|
|
11
|
+
- (void)setButtonAppearance:(NSString * _Nonnull)value;
|
|
12
|
+
- (void)setCornerRadius:(double)value;
|
|
13
|
+
- (void)setDisabled:(BOOL)value;
|
|
14
|
+
@end
|
|
15
|
+
|
|
16
|
+
@interface WhopAddressSuggestionsImpl : NSObject
|
|
17
|
+
- (BOOL)isAvailable;
|
|
18
|
+
- (void)suggest:(NSString *)query resolve:(void (^ _Nonnull)(id _Nullable))resolve reject:(void (^ _Nonnull)(NSString * _Nonnull, NSString * _Nonnull))reject;
|
|
19
|
+
- (void)details:(NSString *)suggestionId resolve:(void (^ _Nonnull)(id _Nullable))resolve reject:(void (^ _Nonnull)(NSString * _Nonnull, NSString * _Nonnull))reject;
|
|
20
|
+
@end
|
|
21
|
+
|
|
22
|
+
@interface WhopAuthSessionImpl : NSObject
|
|
23
|
+
- (BOOL)isAvailable;
|
|
24
|
+
- (void)present:(NSString *)url callbackScheme:(NSString * _Nullable)callbackScheme prefersEphemeral:(BOOL)prefersEphemeral resolve:(void (^ _Nonnull)(id _Nullable))resolve reject:(void (^ _Nonnull)(NSString * _Nonnull, NSString * _Nonnull))reject;
|
|
25
|
+
- (void)dismiss;
|
|
26
|
+
@end
|
|
27
|
+
|
|
28
|
+
@interface WhopPlatformPayImpl : NSObject
|
|
29
|
+
- (NSString * _Nonnull)capability;
|
|
30
|
+
- (void)canPay:(NSString *)configJson resolve:(void (^ _Nonnull)(id _Nullable))resolve reject:(void (^ _Nonnull)(NSString * _Nonnull, NSString * _Nonnull))reject;
|
|
31
|
+
- (void)present:(NSString *)requestJson resolve:(void (^ _Nonnull)(id _Nullable))resolve reject:(void (^ _Nonnull)(NSString * _Nonnull, NSString * _Nonnull))reject;
|
|
32
|
+
- (void)complete:(BOOL)success;
|
|
33
|
+
@end
|
|
34
|
+
|
|
35
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// GENERATED by scripts/codegen-shims.mjs — do not edit, do not commit.
|
|
2
|
+
// Source of truth: src/specs/. Implementations are Swift, in ios/Sources/WhopElements.
|
|
3
|
+
|
|
4
|
+
#import <React/RCTViewComponentView.h>
|
|
5
|
+
#import <UIKit/UIKit.h>
|
|
6
|
+
|
|
7
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
8
|
+
|
|
9
|
+
@interface WhopPayButtonComponentView : RCTViewComponentView
|
|
10
|
+
@end
|
|
11
|
+
|
|
12
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// GENERATED by scripts/codegen-shims.mjs — do not edit, do not commit.
|
|
2
|
+
// Source of truth: src/specs/. Implementations are Swift, in ios/Sources/WhopElements.
|
|
3
|
+
|
|
4
|
+
#import "WhopPayButtonComponentView.h"
|
|
5
|
+
#import "WhopElementsShims.h"
|
|
6
|
+
|
|
7
|
+
#import <React/RCTConversions.h>
|
|
8
|
+
#import <React/RCTFabricComponentsPlugins.h>
|
|
9
|
+
|
|
10
|
+
#import <react/renderer/components/WhopElementsSpec/ComponentDescriptors.h>
|
|
11
|
+
#import <react/renderer/components/WhopElementsSpec/EventEmitters.h>
|
|
12
|
+
#import <react/renderer/components/WhopElementsSpec/Props.h>
|
|
13
|
+
#import <react/renderer/components/WhopElementsSpec/RCTComponentViewHelpers.h>
|
|
14
|
+
|
|
15
|
+
using namespace facebook::react;
|
|
16
|
+
|
|
17
|
+
static NSString *WhopPayButtonVariantToString(WhopPayButtonVariant value)
|
|
18
|
+
{
|
|
19
|
+
return RCTNSStringFromString(toString(value));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
static NSString *WhopPayButtonButtonAppearanceToString(WhopPayButtonButtonAppearance value)
|
|
23
|
+
{
|
|
24
|
+
return RCTNSStringFromString(toString(value));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@interface WhopPayButtonComponentView () <RCTWhopPayButtonViewProtocol>
|
|
28
|
+
@end
|
|
29
|
+
|
|
30
|
+
@implementation WhopPayButtonComponentView {
|
|
31
|
+
WhopPayButtonImpl *_impl;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
|
35
|
+
{
|
|
36
|
+
return concreteComponentDescriptorProvider<WhopPayButtonComponentDescriptor>();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
- (instancetype)initWithFrame:(CGRect)frame
|
|
40
|
+
{
|
|
41
|
+
if (self = [super initWithFrame:frame]) {
|
|
42
|
+
static const auto defaultProps = std::make_shared<const WhopPayButtonProps>();
|
|
43
|
+
_props = defaultProps;
|
|
44
|
+
_impl = [[WhopPayButtonImpl alloc] initWithFrame:frame];
|
|
45
|
+
__weak __typeof(self) weakSelf = self;
|
|
46
|
+
_impl.onPayPress = ^{
|
|
47
|
+
__strong __typeof(weakSelf) strongSelf = weakSelf;
|
|
48
|
+
if (!strongSelf || !strongSelf->_eventEmitter) { return; }
|
|
49
|
+
std::static_pointer_cast<const WhopPayButtonEventEmitter>(strongSelf->_eventEmitter)->onPayPress({});
|
|
50
|
+
};
|
|
51
|
+
self.contentView = _impl;
|
|
52
|
+
}
|
|
53
|
+
return self;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
|
|
57
|
+
{
|
|
58
|
+
const auto &oldViewProps = *std::static_pointer_cast<WhopPayButtonProps const>(_props);
|
|
59
|
+
const auto &newViewProps = *std::static_pointer_cast<WhopPayButtonProps const>(props);
|
|
60
|
+
|
|
61
|
+
if (oldViewProps.variant != newViewProps.variant) {
|
|
62
|
+
[_impl setVariant:WhopPayButtonVariantToString(newViewProps.variant)];
|
|
63
|
+
}
|
|
64
|
+
if (oldViewProps.buttonAppearance != newViewProps.buttonAppearance) {
|
|
65
|
+
[_impl setButtonAppearance:WhopPayButtonButtonAppearanceToString(newViewProps.buttonAppearance)];
|
|
66
|
+
}
|
|
67
|
+
if (oldViewProps.cornerRadius != newViewProps.cornerRadius) {
|
|
68
|
+
[_impl setCornerRadius:newViewProps.cornerRadius];
|
|
69
|
+
}
|
|
70
|
+
if (oldViewProps.disabled != newViewProps.disabled) {
|
|
71
|
+
[_impl setDisabled:newViewProps.disabled];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
[super updateProps:props oldProps:oldProps];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
@end
|
|
78
|
+
|
|
79
|
+
Class<RCTComponentViewProtocol> WhopPayButtonCls(void)
|
|
80
|
+
{
|
|
81
|
+
return WhopPayButtonComponentView.class;
|
|
82
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// GENERATED by scripts/codegen-shims.mjs — do not edit, do not commit.
|
|
2
|
+
// Source of truth: src/specs/. Implementations are Swift, in ios/Sources/WhopElements.
|
|
3
|
+
|
|
4
|
+
#import <WhopElementsSpec/WhopElementsSpec.h>
|
|
5
|
+
|
|
6
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
7
|
+
|
|
8
|
+
@interface WhopPlatformPayModule : NSObject <NativeWhopPlatformPaySpec>
|
|
9
|
+
@end
|
|
10
|
+
|
|
11
|
+
NS_ASSUME_NONNULL_END
|