From ed72571a82fbd55bd143b336629e449aba9f3b23 Mon Sep 17 00:00:00 2001 From: Mark Murray Date: Tue, 2 Sep 2025 10:12:11 +0100 Subject: [PATCH 1/6] Initial scaffold --- .../ios/ShopifyCheckoutSheetKit.mm | 2 +- .../@shopify/checkout-sheet-kit/package.json | 12 +++ .../components/AcceleratedCheckoutButtons.tsx | 6 +- .../@shopify/checkout-sheet-kit/src/index.ts | 27 ++++--- ...eleratedCheckoutButtonsNativeComponent.tsx | 52 +++++++++++++ .../native/NativeShopifyCheckoutSheetKit.ts | 54 +++++++++++++ .../checkout-sheet-kit/src/native/module.ts | 77 +++++++++++++++++++ 7 files changed, 215 insertions(+), 15 deletions(-) create mode 100644 modules/@shopify/checkout-sheet-kit/src/native/AcceleratedCheckoutButtonsNativeComponent.tsx create mode 100644 modules/@shopify/checkout-sheet-kit/src/native/NativeShopifyCheckoutSheetKit.ts create mode 100644 modules/@shopify/checkout-sheet-kit/src/native/module.ts diff --git a/modules/@shopify/checkout-sheet-kit/ios/ShopifyCheckoutSheetKit.mm b/modules/@shopify/checkout-sheet-kit/ios/ShopifyCheckoutSheetKit.mm index c70f3248..8683df7b 100644 --- a/modules/@shopify/checkout-sheet-kit/ios/ShopifyCheckoutSheetKit.mm +++ b/modules/@shopify/checkout-sheet-kit/ios/ShopifyCheckoutSheetKit.mm @@ -25,7 +25,7 @@ of this software and associated documentation files (the "Software"), to deal #import #import -@interface RCT_EXTERN_MODULE (RCTShopifyCheckoutSheetKit, NSObject) +@interface RCT_EXTERN_REMAP_MODULE (ShopifyCheckoutSheetKit, RCTShopifyCheckoutSheetKit, NSObject) /** * Present checkout diff --git a/modules/@shopify/checkout-sheet-kit/package.json b/modules/@shopify/checkout-sheet-kit/package.json index 8ff762e7..74dfbb8d 100644 --- a/modules/@shopify/checkout-sheet-kit/package.json +++ b/modules/@shopify/checkout-sheet-kit/package.json @@ -63,5 +63,17 @@ } ] ] + }, + "codegenConfig": { + "name": "ShopifyCheckoutSheetKitSpec", + "type": "all", + "jsSrcsDir": "src", + "android": { + "javaPackageName": "com.shopify.reactnative.checkoutsheetkit" + }, + "ios": { + "libraryName": "RNShopifyCheckoutSheetKit", + "prefix": "Shopify" + } } } diff --git a/modules/@shopify/checkout-sheet-kit/src/components/AcceleratedCheckoutButtons.tsx b/modules/@shopify/checkout-sheet-kit/src/components/AcceleratedCheckoutButtons.tsx index 7958fe85..a6f65b96 100644 --- a/modules/@shopify/checkout-sheet-kit/src/components/AcceleratedCheckoutButtons.tsx +++ b/modules/@shopify/checkout-sheet-kit/src/components/AcceleratedCheckoutButtons.tsx @@ -163,7 +163,7 @@ interface NativeAcceleratedCheckoutButtonsProps { onSizeChange?: (event: {nativeEvent: {height: number}}) => void; } -const RCTAcceleratedCheckoutButtons = +const NativeAcceleratedCheckoutButtons = requireNativeComponent( 'RCTAcceleratedCheckoutButtons', ); @@ -304,8 +304,10 @@ export const AcceleratedCheckoutButtons: React.FC< } } + const NativeComponent = NativeAcceleratedCheckoutButtons; + return ( - void; + onComplete?: (event: {nativeEvent: any}) => void; + onCancel?: () => void; + onRenderStateChange?: (event: { + nativeEvent: {state: string; reason?: string}; + }) => void; + onWebPixelEvent?: (event: {nativeEvent: any}) => void; + onClickLink?: (event: {nativeEvent: {url: string}}) => void; + onSizeChange?: (event: {nativeEvent: {height: number}}) => void; + } +>; + +export default codegenNativeComponent( + 'ShopifyAcceleratedCheckoutButtons', +) as HostComponent; diff --git a/modules/@shopify/checkout-sheet-kit/src/native/NativeShopifyCheckoutSheetKit.ts b/modules/@shopify/checkout-sheet-kit/src/native/NativeShopifyCheckoutSheetKit.ts new file mode 100644 index 00000000..bbc320c7 --- /dev/null +++ b/modules/@shopify/checkout-sheet-kit/src/native/NativeShopifyCheckoutSheetKit.ts @@ -0,0 +1,54 @@ +/* +MIT License + +Copyright 2023 - Present, Shopify Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +import type {TurboModule} from 'react-native'; +import {TurboModuleRegistry} from 'react-native'; +import type {Configuration} from '../index.d'; + +export interface Spec extends TurboModule { + readonly version: string; + dismiss(): void; + invalidateCache(): void; + preload(checkoutUrl: string): void; + present(checkoutUrl: string): void; + getConfig(): Promise; + setConfig(configuration: Configuration): void; + configureAcceleratedCheckouts?: ( + storefrontDomain: string, + storefrontAccessToken: string, + customerEmail: string | null, + customerPhoneNumber: string | null, + customerAccessToken: string | null, + applePayMerchantIdentifier: string | null, + applePayContactFields: string[], + ) => Promise; + isAcceleratedCheckoutAvailable?: () => Promise; + isApplePayAvailable?: () => Promise; + initiateGeolocationRequest?: (allow: boolean) => void; + addListener(eventName: string): void; + removeListeners(count: number): void; +} + +export default TurboModuleRegistry.getEnforcing( + 'ShopifyCheckoutSheetKit', +); diff --git a/modules/@shopify/checkout-sheet-kit/src/native/module.ts b/modules/@shopify/checkout-sheet-kit/src/native/module.ts new file mode 100644 index 00000000..966324b5 --- /dev/null +++ b/modules/@shopify/checkout-sheet-kit/src/native/module.ts @@ -0,0 +1,77 @@ +/* +MIT License + +Copyright 2023 - Present, Shopify Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +import {NativeModules} from 'react-native'; +import type {Configuration} from '../index.d'; + +type NativeShopifyCheckoutSheetKit = { + readonly version: string; + dismiss(): void; + invalidateCache(): void; + preload(checkoutUrl: string): void; + present(checkoutUrl: string): void; + getConfig(): Promise; + setConfig(configuration: Configuration): void; + // iOS-specific accelerated checkouts + configureAcceleratedCheckouts?: ( + storefrontDomain: string, + storefrontAccessToken: string, + customerEmail: string | null, + customerPhoneNumber: string | null, + customerAccessToken: string | null, + applePayMerchantIdentifier: string | null, + applePayContactFields: string[], + ) => Promise; + isAcceleratedCheckoutAvailable?: () => Promise; + isApplePayAvailable?: () => Promise; + // Android-specific geolocation + initiateGeolocationRequest?: (allow: boolean) => void; + // RN event emitter contract for TurboModules + addListener: (eventName: string) => void; + removeListeners: (count: number) => void; +}; + +export function getShopifyCheckoutNativeModule(): + | NativeShopifyCheckoutSheetKit + | undefined { + // Prefer TurboModule if available; fall back to classic bridge. + try { + // Dynamically require to avoid throwing when codegen isn't wired yet. + // If the generated spec is present, default export should be the TurboModule proxy. + // eslint-disable-next-line @typescript-eslint/no-var-requires + const turbo: NativeShopifyCheckoutSheetKit = + require('./NativeShopifyCheckoutSheetKit').default; + if (turbo != null) { + return turbo; + } + } catch { + // no-op; fall back to classic bridge + } + + const legacy = (NativeModules as any).ShopifyCheckoutSheetKit as + | NativeShopifyCheckoutSheetKit + | undefined; + return legacy; +} + +export type {NativeShopifyCheckoutSheetKit}; From 2a33a9299cc3db8b33fc70eb38c96bc55e374b93 Mon Sep 17 00:00:00 2001 From: Mark Murray Date: Tue, 2 Sep 2025 10:40:41 +0100 Subject: [PATCH 2/6] Implement TurboModule for Android --- .../ShopifyCheckoutSheetKitModule.java | 53 +++++++++++++++++- .../ios/ShopifyCheckoutSheetKit.mm | 4 +- .../ios/ShopifyCheckoutSheetKit.swift | 4 ++ .../@shopify/checkout-sheet-kit/src/index.ts | 6 ++- ...eleratedCheckoutButtonsNativeComponent.tsx | 52 ------------------ .../native/NativeShopifyCheckoutSheetKit.ts | 54 ------------------- 6 files changed, 64 insertions(+), 109 deletions(-) delete mode 100644 modules/@shopify/checkout-sheet-kit/src/native/AcceleratedCheckoutButtonsNativeComponent.tsx delete mode 100644 modules/@shopify/checkout-sheet-kit/src/native/NativeShopifyCheckoutSheetKit.ts diff --git a/modules/@shopify/checkout-sheet-kit/android/src/main/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java b/modules/@shopify/checkout-sheet-kit/android/src/main/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java index dd778fcf..17bba054 100644 --- a/modules/@shopify/checkout-sheet-kit/android/src/main/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java +++ b/modules/@shopify/checkout-sheet-kit/android/src/main/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java @@ -30,6 +30,57 @@ of this software and associated documentation files (the "Software"), to deal import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; +#if RCT_NEW_ARCH_ENABLED +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.Promise; +import com.facebook.react.module.annotations.ReactModule; +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.WritableNativeMap; +import com.facebook.react.bridge.UiThreadUtil; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.ReactNoCrashSoftException; +import com.facebook.react.module.annotations.ReactModuleList; +import com.facebook.react.bridge.NativeModule; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; +import com.facebook.react.fabric.events.EventDispatcher; +import com.facebook.react.uimanager.events.EventDispatcherImpl; +import com.facebook.react.codegen.module.JavaModuleWrapper; +import com.facebook.react.bridge.ReactMarker; +import com.facebook.react.modules.core.DeviceEventManagerModule; +import com.facebook.react.modules.core.DeviceEventManagerModule.RCTDeviceEventEmitter; +import com.facebook.react.bridge.NoSuchKeyException; +import com.facebook.react.module.model.ReactModuleInfo; +import com.facebook.react.module.model.ReactModuleInfoProvider; +import com.facebook.jni.HybridData; +import com.facebook.proguard.annotations.DoNotStrip; +import com.facebook.react.bridge.JavaScriptContextHolder; +import com.facebook.proguard.annotations.DoNotStripAny; +import com.facebook.react.bridge.queue.MessageQueueThread; +import com.facebook.react.bridge.Dynamic; +import com.facebook.react.bridge.Arguments; +import com.facebook.react.common.MapBuilder; +import com.facebook.react.codegen.ReactNativeFeatureFlags; +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.bridge.ReactSoftExceptionLogger; +import com.facebook.react.bridge.Callback; +import com.facebook.react.modules.core.DeviceEventManagerModule; +import com.facebook.react.bridge.ActivityEventListener; +import com.facebook.react.bridge.BaseJavaModule; +import com.facebook.react.bridge.LifecycleEventListener; +// Generated spec +import com.facebook.react.bridge.ReactContext; +import com.facebook.react.module.annotations.ReactModule; +import com.facebook.react.module.annotations.ReactModuleList; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.bridge.arguments; +import com.facebook.react.module.model.ReactModuleInfo; +import com.facebook.react.module.model.ReactModuleInfoProvider; +import com.facebook.react.module.annotations.ReactModule; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; +#endif import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.WritableNativeMap; @@ -39,7 +90,7 @@ of this software and associated documentation files (the "Software"), to deal import java.util.Map; import java.util.Objects; -public class ShopifyCheckoutSheetKitModule extends ReactContextBaseJavaModule { +public class ShopifyCheckoutSheetKitModule extends ReactContextBaseJavaModule implements TurboModule { private static final String MODULE_NAME = "ShopifyCheckoutSheetKit"; public static Configuration checkoutConfig = new Configuration(); diff --git a/modules/@shopify/checkout-sheet-kit/ios/ShopifyCheckoutSheetKit.mm b/modules/@shopify/checkout-sheet-kit/ios/ShopifyCheckoutSheetKit.mm index 8683df7b..93991916 100644 --- a/modules/@shopify/checkout-sheet-kit/ios/ShopifyCheckoutSheetKit.mm +++ b/modules/@shopify/checkout-sheet-kit/ios/ShopifyCheckoutSheetKit.mm @@ -75,7 +75,9 @@ @interface RCT_EXTERN_REMAP_MODULE (ShopifyCheckoutSheetKit, RCTShopifyCheckoutS /** * Check if Apple Pay is available */ -RCT_EXTERN_METHOD(isApplePayAvailable : (RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject); +RCT_EXTERN_METHOD(isApplePayAvailable : (RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject) + +RCT_EXTERN__BLOCKING_SYNCHRONOUS_METHOD(getVersion) @end diff --git a/modules/@shopify/checkout-sheet-kit/ios/ShopifyCheckoutSheetKit.swift b/modules/@shopify/checkout-sheet-kit/ios/ShopifyCheckoutSheetKit.swift index b19012cf..82f9bd5b 100644 --- a/modules/@shopify/checkout-sheet-kit/ios/ShopifyCheckoutSheetKit.swift +++ b/modules/@shopify/checkout-sheet-kit/ios/ShopifyCheckoutSheetKit.swift @@ -102,6 +102,10 @@ class RCTShopifyCheckoutSheetKit: RCTEventEmitter, CheckoutDelegate { ] } + @objc func getVersion() -> String { + return ShopifyCheckoutSheetKit.version + } + static func getRootViewController() -> UIViewController? { return (UIApplication.shared.connectedScenes .first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene)?.windows diff --git a/modules/@shopify/checkout-sheet-kit/src/index.ts b/modules/@shopify/checkout-sheet-kit/src/index.ts index 0a3d7485..174ddd2b 100644 --- a/modules/@shopify/checkout-sheet-kit/src/index.ts +++ b/modules/@shopify/checkout-sheet-kit/src/index.ts @@ -109,7 +109,11 @@ class ShopifyCheckoutSheet implements ShopifyCheckoutSheetKit { } } - public readonly version: string = RNShopifyCheckoutSheetKit.version; + public readonly version: string = + // Prefer constant; fallback to sync getter if provided by TurboModule. + (RNShopifyCheckoutSheetKit as any).version ?? + (RNShopifyCheckoutSheetKit as any).getVersion?.() ?? + 'unknown'; /** * Dismisses the currently displayed checkout sheet diff --git a/modules/@shopify/checkout-sheet-kit/src/native/AcceleratedCheckoutButtonsNativeComponent.tsx b/modules/@shopify/checkout-sheet-kit/src/native/AcceleratedCheckoutButtonsNativeComponent.tsx deleted file mode 100644 index cebdc9f2..00000000 --- a/modules/@shopify/checkout-sheet-kit/src/native/AcceleratedCheckoutButtonsNativeComponent.tsx +++ /dev/null @@ -1,52 +0,0 @@ -/* -MIT License - -Copyright 2023 - Present, Shopify Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; -import type {HostComponent} from 'react-native'; -import type {ViewProps} from 'react-native'; - -export type AcceleratedCheckoutButtonsNativeProps = Readonly< - ViewProps & { - checkoutIdentifier?: { - cartId?: string; - variantId?: string; - quantity?: number; - }; - cornerRadius?: number; - wallets?: string[]; - applePayLabel?: string; - onFail?: (event: {nativeEvent: any}) => void; - onComplete?: (event: {nativeEvent: any}) => void; - onCancel?: () => void; - onRenderStateChange?: (event: { - nativeEvent: {state: string; reason?: string}; - }) => void; - onWebPixelEvent?: (event: {nativeEvent: any}) => void; - onClickLink?: (event: {nativeEvent: {url: string}}) => void; - onSizeChange?: (event: {nativeEvent: {height: number}}) => void; - } ->; - -export default codegenNativeComponent( - 'ShopifyAcceleratedCheckoutButtons', -) as HostComponent; diff --git a/modules/@shopify/checkout-sheet-kit/src/native/NativeShopifyCheckoutSheetKit.ts b/modules/@shopify/checkout-sheet-kit/src/native/NativeShopifyCheckoutSheetKit.ts deleted file mode 100644 index bbc320c7..00000000 --- a/modules/@shopify/checkout-sheet-kit/src/native/NativeShopifyCheckoutSheetKit.ts +++ /dev/null @@ -1,54 +0,0 @@ -/* -MIT License - -Copyright 2023 - Present, Shopify Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -import type {TurboModule} from 'react-native'; -import {TurboModuleRegistry} from 'react-native'; -import type {Configuration} from '../index.d'; - -export interface Spec extends TurboModule { - readonly version: string; - dismiss(): void; - invalidateCache(): void; - preload(checkoutUrl: string): void; - present(checkoutUrl: string): void; - getConfig(): Promise; - setConfig(configuration: Configuration): void; - configureAcceleratedCheckouts?: ( - storefrontDomain: string, - storefrontAccessToken: string, - customerEmail: string | null, - customerPhoneNumber: string | null, - customerAccessToken: string | null, - applePayMerchantIdentifier: string | null, - applePayContactFields: string[], - ) => Promise; - isAcceleratedCheckoutAvailable?: () => Promise; - isApplePayAvailable?: () => Promise; - initiateGeolocationRequest?: (allow: boolean) => void; - addListener(eventName: string): void; - removeListeners(count: number): void; -} - -export default TurboModuleRegistry.getEnforcing( - 'ShopifyCheckoutSheetKit', -); From 46ef4722ff2c1cd32e15cd7f7d6b04b3a19a1153 Mon Sep 17 00:00:00 2001 From: Mark Murray Date: Tue, 2 Sep 2025 13:36:33 +0100 Subject: [PATCH 3/6] Codegen, upgrade gesture handler --- .../ShopifyCheckoutSheetKitModule.java | 105 +++++++----------- .../components/AcceleratedCheckoutButtons.tsx | 5 +- .../native/NativeShopifyCheckoutSheetKit.ts | 92 +++++++++++++++ package.json | 2 +- sample/Gemfile.lock | 4 +- sample/ios/Podfile.lock | 24 ++-- sample/package.json | 4 +- yarn.lock | 24 ++-- 8 files changed, 165 insertions(+), 95 deletions(-) create mode 100644 modules/@shopify/checkout-sheet-kit/src/native/NativeShopifyCheckoutSheetKit.ts diff --git a/modules/@shopify/checkout-sheet-kit/android/src/main/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java b/modules/@shopify/checkout-sheet-kit/android/src/main/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java index 17bba054..6081490f 100644 --- a/modules/@shopify/checkout-sheet-kit/android/src/main/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java +++ b/modules/@shopify/checkout-sheet-kit/android/src/main/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java @@ -30,59 +30,10 @@ of this software and associated documentation files (the "Software"), to deal import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; -#if RCT_NEW_ARCH_ENABLED -import com.facebook.react.bridge.ReactApplicationContext; +import com.shopify.reactnative.checkoutsheetkit.NativeShopifyCheckoutSheetKitSpec; import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.Promise; -import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.bridge.WritableNativeMap; -import com.facebook.react.bridge.UiThreadUtil; import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.bridge.ReactNoCrashSoftException; -import com.facebook.react.module.annotations.ReactModuleList; -import com.facebook.react.bridge.NativeModule; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; -import com.facebook.react.fabric.events.EventDispatcher; -import com.facebook.react.uimanager.events.EventDispatcherImpl; -import com.facebook.react.codegen.module.JavaModuleWrapper; -import com.facebook.react.bridge.ReactMarker; -import com.facebook.react.modules.core.DeviceEventManagerModule; -import com.facebook.react.modules.core.DeviceEventManagerModule.RCTDeviceEventEmitter; -import com.facebook.react.bridge.NoSuchKeyException; -import com.facebook.react.module.model.ReactModuleInfo; -import com.facebook.react.module.model.ReactModuleInfoProvider; -import com.facebook.jni.HybridData; -import com.facebook.proguard.annotations.DoNotStrip; -import com.facebook.react.bridge.JavaScriptContextHolder; -import com.facebook.proguard.annotations.DoNotStripAny; -import com.facebook.react.bridge.queue.MessageQueueThread; -import com.facebook.react.bridge.Dynamic; -import com.facebook.react.bridge.Arguments; -import com.facebook.react.common.MapBuilder; -import com.facebook.react.codegen.ReactNativeFeatureFlags; -import com.facebook.react.bridge.WritableMap; -import com.facebook.react.bridge.ReactSoftExceptionLogger; -import com.facebook.react.bridge.Callback; -import com.facebook.react.modules.core.DeviceEventManagerModule; -import com.facebook.react.bridge.ActivityEventListener; -import com.facebook.react.bridge.BaseJavaModule; -import com.facebook.react.bridge.LifecycleEventListener; -// Generated spec -import com.facebook.react.bridge.ReactContext; -import com.facebook.react.module.annotations.ReactModule; -import com.facebook.react.module.annotations.ReactModuleList; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; -import com.facebook.react.bridge.WritableMap; -import com.facebook.react.bridge.arguments; -import com.facebook.react.module.model.ReactModuleInfo; -import com.facebook.react.module.model.ReactModuleInfoProvider; -import com.facebook.react.module.annotations.ReactModule; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; -#endif -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.WritableNativeMap; import com.shopify.checkoutsheetkit.*; @@ -90,9 +41,7 @@ of this software and associated documentation files (the "Software"), to deal import java.util.Map; import java.util.Objects; -public class ShopifyCheckoutSheetKitModule extends ReactContextBaseJavaModule implements TurboModule { - private static final String MODULE_NAME = "ShopifyCheckoutSheetKit"; - +public class ShopifyCheckoutSheetKitModule extends NativeShopifyCheckoutSheetKitSpec { public static Configuration checkoutConfig = new Configuration(); private final ReactApplicationContext reactContext; @@ -112,12 +61,6 @@ public ShopifyCheckoutSheetKitModule(ReactApplicationContext reactContext) { }); } - @NonNull - @Override - public String getName() { - return MODULE_NAME; - } - @Override public Map getConstants() { final Map constants = new HashMap<>(); @@ -131,11 +74,12 @@ public void addListener(String eventName) { } @ReactMethod - public void removeListeners(Integer count) { + public void removeListeners(double count) { // No-op but required for RN to register module } @ReactMethod + @Override public void present(String checkoutURL) { Activity currentActivity = getCurrentActivity(); if (currentActivity instanceof ComponentActivity) { @@ -148,6 +92,7 @@ public void present(String checkoutURL) { } @ReactMethod + @Override public void dismiss() { if (checkoutSheet != null) { checkoutSheet.dismiss(); @@ -156,6 +101,7 @@ public void dismiss() { } @ReactMethod + @Override public void preload(String checkoutURL) { Activity currentActivity = getCurrentActivity(); @@ -165,11 +111,13 @@ public void preload(String checkoutURL) { } @ReactMethod + @Override public void invalidateCache() { ShopifyCheckoutSheetKit.invalidate(); } @ReactMethod + @Override public void getConfig(Promise promise) { WritableNativeMap resultConfig = new WritableNativeMap(); @@ -180,6 +128,7 @@ public void getConfig(Promise promise) { } @ReactMethod + @Override public void setConfig(ReadableMap config) { Context context = getReactApplicationContext(); @@ -213,13 +162,41 @@ public void setConfig(ReadableMap config) { }); } + @Override + public void isApplePayAvailable(Promise promise) { + promise.resolve(false); + } + + @Override + public void isAcceleratedCheckoutAvailable(Promise promise) { + promise.resolve(false); + } + + @Override + public void configureAcceleratedCheckouts( + String storefrontDomain, + String storefrontAccessToken, + String customerEmail, + String customerPhoneNumber, + String customerAccessToken, + String applePayMerchantIdentifier, + ReadableArray applePayContactFields, + Promise promise) { + promise.resolve(false); + } + @ReactMethod - public void initiateGeolocationRequest(Boolean allow) { + public void initiateGeolocationRequest(boolean allow) { if (checkoutEventProcessor != null) { checkoutEventProcessor.invokeGeolocationCallback(allow); } } + @Override + public String getVersion() { + return ShopifyCheckoutSheetKit.version; + } + // Private private ColorScheme getColorScheme(String colorScheme) { @@ -308,10 +285,10 @@ private Colors createColorsFromConfig(ReadableMap config) { headerBackground, headerFont, progressIndicator, - // Parameter allows passing a custom drawable, we'll just support custom color for now + // Parameter allows passing a custom drawable, we'll just support custom color + // for now null, - closeButtonColor - ); + closeButtonColor); } return null; diff --git a/modules/@shopify/checkout-sheet-kit/src/components/AcceleratedCheckoutButtons.tsx b/modules/@shopify/checkout-sheet-kit/src/components/AcceleratedCheckoutButtons.tsx index a6f65b96..04fcdd33 100644 --- a/modules/@shopify/checkout-sheet-kit/src/components/AcceleratedCheckoutButtons.tsx +++ b/modules/@shopify/checkout-sheet-kit/src/components/AcceleratedCheckoutButtons.tsx @@ -163,7 +163,7 @@ interface NativeAcceleratedCheckoutButtonsProps { onSizeChange?: (event: {nativeEvent: {height: number}}) => void; } -const NativeAcceleratedCheckoutButtons = +const LegacyAcceleratedCheckoutButtons = requireNativeComponent( 'RCTAcceleratedCheckoutButtons', ); @@ -304,7 +304,8 @@ export const AcceleratedCheckoutButtons: React.FC< } } - const NativeComponent = NativeAcceleratedCheckoutButtons; + // Use legacy view manager; RN 0.80 interop bridges it under Fabric when enabled + const NativeComponent = LegacyAcceleratedCheckoutButtons; return ( ; + setConfig(configuration: ConfigurationInput): void; + configureAcceleratedCheckouts( + storefrontDomain: string, + storefrontAccessToken: string, + customerEmail: string | null, + customerPhoneNumber: string | null, + customerAccessToken: string | null, + applePayMerchantIdentifier: string | null, + applePayContactFields: ReadonlyArray<'email' | 'phone'>, + ): Promise; + isAcceleratedCheckoutAvailable(): Promise; + isApplePayAvailable(): Promise; + initiateGeolocationRequest(allow: boolean): void; + addListener(eventName: string): void; + removeListeners(count: number): void; +} + +export default TurboModuleRegistry.getEnforcing( + 'ShopifyCheckoutSheetKit', +); diff --git a/package.json b/package.json index f641f7d3..a8136cce 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "react": "19.1.0", "react-native": "0.80.2", "react-native-dotenv": "^3.4.9", - "react-native-gesture-handler": "2.26.0", + "react-native-gesture-handler": "2.28.0", "react-native-gradle-plugin": "^0.71.19", "react-test-renderer": "19.1.0", "ts-jest": "^29.4.1", diff --git a/sample/Gemfile.lock b/sample/Gemfile.lock index a4eab9b9..13b9ab76 100644 --- a/sample/Gemfile.lock +++ b/sample/Gemfile.lock @@ -81,7 +81,7 @@ GEM mutex_m i18n (1.14.7) concurrent-ruby (~> 1.0) - json (2.13.2) + json (2.15.0) logger (1.7.0) minitest (5.25.5) molinillo (0.8.0) @@ -91,7 +91,7 @@ GEM netrc (0.11.0) nkf (0.2.0) public_suffix (4.0.7) - rexml (3.4.2) + rexml (3.4.4) ruby-macho (2.5.1) securerandom (0.4.1) typhoeus (1.5.0) diff --git a/sample/ios/Podfile.lock b/sample/ios/Podfile.lock index 9a5d803f..aabc1661 100644 --- a/sample/ios/Podfile.lock +++ b/sample/ios/Podfile.lock @@ -2245,7 +2245,7 @@ PODS: - ReactCommon/turbomodule/core - SocketRocket - Yoga - - RNGestureHandler (2.26.0): + - RNGestureHandler (2.28.0): - boost - DoubleConversion - fast_float @@ -2274,7 +2274,7 @@ PODS: - ReactCommon/turbomodule/core - SocketRocket - Yoga - - RNReanimated (3.18.0): + - RNReanimated (3.19.1): - boost - DoubleConversion - fast_float @@ -2301,11 +2301,11 @@ PODS: - ReactCodegen - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - - RNReanimated/reanimated (= 3.18.0) - - RNReanimated/worklets (= 3.18.0) + - RNReanimated/reanimated (= 3.19.1) + - RNReanimated/worklets (= 3.19.1) - SocketRocket - Yoga - - RNReanimated/reanimated (3.18.0): + - RNReanimated/reanimated (3.19.1): - boost - DoubleConversion - fast_float @@ -2332,10 +2332,10 @@ PODS: - ReactCodegen - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - - RNReanimated/reanimated/apple (= 3.18.0) + - RNReanimated/reanimated/apple (= 3.19.1) - SocketRocket - Yoga - - RNReanimated/reanimated/apple (3.18.0): + - RNReanimated/reanimated/apple (3.19.1): - boost - DoubleConversion - fast_float @@ -2364,7 +2364,7 @@ PODS: - ReactCommon/turbomodule/core - SocketRocket - Yoga - - RNReanimated/worklets (3.18.0): + - RNReanimated/worklets (3.19.1): - boost - DoubleConversion - fast_float @@ -2391,10 +2391,10 @@ PODS: - ReactCodegen - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - - RNReanimated/worklets/apple (= 3.18.0) + - RNReanimated/worklets/apple (= 3.19.1) - SocketRocket - Yoga - - RNReanimated/worklets/apple (3.18.0): + - RNReanimated/worklets/apple (3.19.1): - boost - DoubleConversion - fast_float @@ -2879,8 +2879,8 @@ SPEC CHECKSUMS: ReactCodegen: 37cf3321221b0c4f89b0750dbaf466bc99de7a57 ReactCommon: 592ef441605638b95e533653259254b4bd35ff4f RNCMaskedView: 7e0ce15656772a939ff0d269100bca3a182163c8 - RNGestureHandler: eeb622199ef1fb3a076243131095df1c797072f0 - RNReanimated: 288616f9c66ff4b0911f3862ffcf4104482a2adc + RNGestureHandler: db29d3e7edf41a11d133cc3ffd4029762376ed1a + RNReanimated: 7e1500bf2058454a0dfdb9fb7a342ef55c518b84 RNScreens: 26bb60cdb2ef2ca06fd87feefc495072f25982a7 RNShopifyCheckoutSheetKit: 123b2f5948dd4223ffd7d0b318e09c653afd3c0d RNVectorIcons: be4d047a76ad307ffe54732208fb0498fcb8477f diff --git a/sample/package.json b/sample/package.json index 3f5818d7..ae703ca5 100644 --- a/sample/package.json +++ b/sample/package.json @@ -27,8 +27,8 @@ "jotai": "^2.13.1", "react-native-config": "1.5.6", "react-native-dotenv": "^3.4.11", - "react-native-reanimated": "3.18.0", - "react-native-safe-area-context": "^5.2.0", + "react-native-reanimated": "3.19.1", + "react-native-safe-area-context": "^5.6.1", "react-native-screens": "^4.10.0", "react-native-vector-icons": "^10.3.0" }, diff --git a/yarn.lock b/yarn.lock index 30e5f76c..7f16b92c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6124,7 +6124,7 @@ __metadata: react: "npm:19.1.0" react-native: "npm:0.80.2" react-native-dotenv: "npm:^3.4.9" - react-native-gesture-handler: "npm:2.26.0" + react-native-gesture-handler: "npm:2.28.0" react-native-gradle-plugin: "npm:^0.71.19" react-test-renderer: "npm:19.1.0" ts-jest: "npm:^29.4.1" @@ -11120,9 +11120,9 @@ __metadata: languageName: node linkType: hard -"react-native-gesture-handler@npm:2.26.0": - version: 2.26.0 - resolution: "react-native-gesture-handler@npm:2.26.0" +"react-native-gesture-handler@npm:2.28.0": + version: 2.28.0 + resolution: "react-native-gesture-handler@npm:2.28.0" dependencies: "@egjs/hammerjs": "npm:^2.0.17" hoist-non-react-statics: "npm:^3.3.0" @@ -11130,7 +11130,7 @@ __metadata: peerDependencies: react: "*" react-native: "*" - checksum: 10c0/43aee4f0aeb7be9e2e72a9abaeaff38104c188a44ffc1a5634940a851adca5f10ee3a8d1b4828eb654574d4d45aa0f0c2af5a7b4ed2e9bca4e76d0d932f13955 + checksum: 10c0/4240c8eedca69eb36b5d3e375b71867251cf8b87a755ba7066b3f73cfdbc80574042dbd4ff821041fd1539c4cd90dbf7ee34586f5a0ea6cc38052375b3169f2e languageName: node linkType: hard @@ -11161,9 +11161,9 @@ __metadata: languageName: node linkType: hard -"react-native-reanimated@npm:3.18.0": - version: 3.18.0 - resolution: "react-native-reanimated@npm:3.18.0" +"react-native-reanimated@npm:3.19.1": + version: 3.19.1 + resolution: "react-native-reanimated@npm:3.19.1" dependencies: "@babel/plugin-transform-arrow-functions": "npm:^7.0.0-0" "@babel/plugin-transform-class-properties": "npm:^7.0.0-0" @@ -11181,11 +11181,11 @@ __metadata: "@babel/core": ^7.0.0-0 react: "*" react-native: "*" - checksum: 10c0/7420f410a76b2a46f1a0a7df41f8b2508aade8de26fd00eb7305bf25b3ab27e7c06f52ec76d221d8c7317ca3e2bdf842c51216f2adba7fbb60ce321c171d1437 + checksum: 10c0/82f83f8cd307dbb3d0d435a7c801fa27d06265b1eed51844013682e133072e447fd15c3f12814f4bd8d4759c89ad4b1043631611284afbd8e6eb505f57af0f12 languageName: node linkType: hard -"react-native-safe-area-context@npm:^5.2.0": +"react-native-safe-area-context@npm:^5.6.1": version: 5.6.1 resolution: "react-native-safe-area-context@npm:5.6.1" peerDependencies: @@ -11728,8 +11728,8 @@ __metadata: jotai: "npm:^2.13.1" react-native-config: "npm:1.5.6" react-native-dotenv: "npm:^3.4.11" - react-native-reanimated: "npm:3.18.0" - react-native-safe-area-context: "npm:^5.2.0" + react-native-reanimated: "npm:3.19.1" + react-native-safe-area-context: "npm:^5.6.1" react-native-screens: "npm:^4.10.0" react-native-vector-icons: "npm:^10.3.0" setimmediate: "npm:^1.0.5" From d22d09132dfaa0c99b97731b180407fc0d2c3426 Mon Sep 17 00:00:00 2001 From: Mark Murray Date: Tue, 2 Sep 2025 13:47:10 +0100 Subject: [PATCH 4/6] Update package snapshot to include new files --- .../checkout-sheet-kit/package.snapshot.json | 14 ++++++++++++++ .../checkout-sheet-kit/src/native/module.ts | 3 ++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/modules/@shopify/checkout-sheet-kit/package.snapshot.json b/modules/@shopify/checkout-sheet-kit/package.snapshot.json index 782ccbaa..c24c8ab2 100644 --- a/modules/@shopify/checkout-sheet-kit/package.snapshot.json +++ b/modules/@shopify/checkout-sheet-kit/package.snapshot.json @@ -28,6 +28,10 @@ "lib/commonjs/index.d.js.map", "lib/commonjs/index.js", "lib/commonjs/index.js.map", + "lib/commonjs/native/module.js", + "lib/commonjs/native/module.js.map", + "lib/commonjs/native/NativeShopifyCheckoutSheetKit.js", + "lib/commonjs/native/NativeShopifyCheckoutSheetKit.js.map", "lib/commonjs/pixels.d.js", "lib/commonjs/pixels.d.js.map", "lib/module/components/AcceleratedCheckoutButtons.js", @@ -42,6 +46,10 @@ "lib/module/index.d.js.map", "lib/module/index.js", "lib/module/index.js.map", + "lib/module/native/module.js", + "lib/module/native/module.js.map", + "lib/module/native/NativeShopifyCheckoutSheetKit.js", + "lib/module/native/NativeShopifyCheckoutSheetKit.js.map", "lib/module/pixels.d.js", "lib/module/pixels.d.js.map", "lib/typescript/src/components/AcceleratedCheckoutButtons.d.ts", @@ -50,6 +58,10 @@ "lib/typescript/src/context.d.ts.map", "lib/typescript/src/index.d.ts", "lib/typescript/src/index.d.ts.map", + "lib/typescript/src/native/module.d.ts", + "lib/typescript/src/native/module.d.ts.map", + "lib/typescript/src/native/NativeShopifyCheckoutSheetKit.d.ts", + "lib/typescript/src/native/NativeShopifyCheckoutSheetKit.d.ts.map", "package.json", "src/components/AcceleratedCheckoutButtons.tsx", "src/context.tsx", @@ -57,5 +69,7 @@ "src/events.d.ts", "src/index.d.ts", "src/index.ts", + "src/native/module.ts", + "src/native/NativeShopifyCheckoutSheetKit.ts", "src/pixels.d.ts" ] diff --git a/modules/@shopify/checkout-sheet-kit/src/native/module.ts b/modules/@shopify/checkout-sheet-kit/src/native/module.ts index 966324b5..f7683cdf 100644 --- a/modules/@shopify/checkout-sheet-kit/src/native/module.ts +++ b/modules/@shopify/checkout-sheet-kit/src/native/module.ts @@ -58,9 +58,9 @@ export function getShopifyCheckoutNativeModule(): try { // Dynamically require to avoid throwing when codegen isn't wired yet. // If the generated spec is present, default export should be the TurboModule proxy. - // eslint-disable-next-line @typescript-eslint/no-var-requires const turbo: NativeShopifyCheckoutSheetKit = require('./NativeShopifyCheckoutSheetKit').default; + if (turbo != null) { return turbo; } @@ -71,6 +71,7 @@ export function getShopifyCheckoutNativeModule(): const legacy = (NativeModules as any).ShopifyCheckoutSheetKit as | NativeShopifyCheckoutSheetKit | undefined; + return legacy; } From 654f2731a3f322411d9068b6aa5a3964c6446d4b Mon Sep 17 00:00:00 2001 From: Mark Murray Date: Wed, 3 Sep 2025 09:28:55 +0100 Subject: [PATCH 5/6] Update CI to run tests across both architectures --- .github/actions/install-cocoapods/action.yml | 5 ++-- .github/workflows/ci.yml | 29 ++++++++++++++++--- .../components/AcceleratedCheckoutButtons.tsx | 15 +++++++++- sample/ios/Podfile | 2 +- sample/scripts/build_android | 2 +- sample/scripts/test_android | 2 +- 6 files changed, 45 insertions(+), 10 deletions(-) diff --git a/.github/actions/install-cocoapods/action.yml b/.github/actions/install-cocoapods/action.yml index 9ec7f7e3..9b48ef8a 100644 --- a/.github/actions/install-cocoapods/action.yml +++ b/.github/actions/install-cocoapods/action.yml @@ -17,7 +17,7 @@ runs: with: path: | sample/ios/Pods - key: ${{ runner.os }}-cocoapods-${{ hashFiles('sample/ios/Podfile.lock', 'sample/Gemfile.lock', 'sample/Gemfile', 'package.json', 'sample/package.json', 'modules/@shopify/checkout-sheet-kit/package.json', 'yarn.lock') }} + key: ${{ runner.os }}-cocoapods-na-${{ env.RCT_NEW_ARCH_ENABLED }}-${{ hashFiles('sample/ios/Podfile.lock', 'sample/Gemfile.lock', 'sample/Gemfile', 'package.json', 'sample/package.json', 'modules/@shopify/checkout-sheet-kit/package.json', 'yarn.lock') }} - name: Install cocoapods shell: bash @@ -27,5 +27,6 @@ runs: cd sample bundle install cd ios - bundle exec pod install --deployment --repo-update + echo "RCT_NEW_ARCH_ENABLED: ${{ env.RCT_NEW_ARCH_ENABLED }}" + bundle exec pod install --repo-update cd $ROOT diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 665a5f2e..87f5af4b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -83,10 +83,18 @@ jobs: create-new-comment: false test-android: - name: Run Android Tests + name: Run Android Tests (${{ matrix.arch }}) runs-on: ubuntu-latest timeout-minutes: 20 needs: [lint, test] + strategy: + fail-fast: false + matrix: + include: + - arch: Legacy Arch + new_arch_enabled: 'false' + - arch: New Arch + new_arch_enabled: 'true' steps: - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 @@ -101,11 +109,12 @@ jobs: distribution: 'zulu' java-version: ${{ env.JAVA_VERSION }} - - name: Run Android tests + - name: Run Android tests (${{ matrix.arch }}) timeout-minutes: 20 env: GRADLE_OPTS: -Xmx4g -XX:MaxMetaspaceSize=768m JAVA_HOME: ${{ steps.setup-java.outputs.path }} + ORG_GRADLE_PROJECT_newArchEnabled: ${{ matrix.new_arch_enabled }} run: | echo "JAVA_HOME: $JAVA_HOME" java -version @@ -115,10 +124,18 @@ jobs: yarn sample test:android --no-daemon test-ios: - name: Run Swift Tests + name: Run Swift Tests (${{ matrix.arch }}) runs-on: macos-15-xlarge timeout-minutes: 20 needs: [lint, test] + strategy: + fail-fast: false + matrix: + include: + - arch: legacy + new_arch_enabled: 'false' + - arch: new-arch + new_arch_enabled: 'true' steps: - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 @@ -139,7 +156,11 @@ jobs: - name: Install cocoapods uses: ./.github/actions/install-cocoapods + env: + RCT_NEW_ARCH_ENABLED: ${{ matrix.new_arch_enabled }} - - name: Run Swift tests + - name: Run Swift tests (${{ matrix.arch }}) + env: + RCT_NEW_ARCH_ENABLED: ${{ matrix.new_arch_enabled }} run: | yarn sample test:ios diff --git a/modules/@shopify/checkout-sheet-kit/src/components/AcceleratedCheckoutButtons.tsx b/modules/@shopify/checkout-sheet-kit/src/components/AcceleratedCheckoutButtons.tsx index 04fcdd33..dab20f1d 100644 --- a/modules/@shopify/checkout-sheet-kit/src/components/AcceleratedCheckoutButtons.tsx +++ b/modules/@shopify/checkout-sheet-kit/src/components/AcceleratedCheckoutButtons.tsx @@ -304,7 +304,20 @@ export const AcceleratedCheckoutButtons: React.FC< } } - // Use legacy view manager; RN 0.80 interop bridges it under Fabric when enabled + /** + * Renderer note: Paper (old renderer) vs Fabric (new renderer). + * + * We intentionally keep supporting both: + * - When Fabric is enabled (RN 0.80+), the Legacy ViewManager Interop layer auto-registers + * an interop component that proxies mount/prop updates/events to our existing Paper + * `RCTViewManager` (`RCTAcceleratedCheckoutButtons`). No dedicated Fabric ComponentView + * is required for this path to work. + * - When Fabric is disabled, this goes through the classic Paper UIManager path. + * + * This preserves the public API while we migrate. When we switch to a true Fabric component + * (codegen + `RCTViewComponentView`), we can replace this with the generated component and + * remove the interop/legacy manager entirely. + */ const NativeComponent = LegacyAcceleratedCheckoutButtons; return ( diff --git a/sample/ios/Podfile b/sample/ios/Podfile index d728b048..9c94cb53 100644 --- a/sample/ios/Podfile +++ b/sample/ios/Podfile @@ -25,7 +25,7 @@ target 'ReactNative' do :path => config[:reactNativePath], # An absolute path to your application root. :app_path => "#{Pod::Config.instance.installation_root}/..", - :new_arch_enabled => true + :new_arch_enabled => (ENV['RCT_NEW_ARCH_ENABLED'] == '1' || ENV['RCT_NEW_ARCH_ENABLED']&.downcase == 'true') ) target 'ReactNativeTests' do diff --git a/sample/scripts/build_android b/sample/scripts/build_android index 424ca874..63f13416 100755 --- a/sample/scripts/build_android +++ b/sample/scripts/build_android @@ -4,4 +4,4 @@ set -ex cd android -./gradlew assembleDebug --no-daemon --console=plain -PreactNativeArchitectures=arm64-v8a +./gradlew assembleDebug --no-daemon --console=plain -PreactNativeArchitectures=arm64-v8a -PnewArchEnabled=${ORG_GRADLE_PROJECT_newArchEnabled:-true} diff --git a/sample/scripts/test_android b/sample/scripts/test_android index b6e4223e..e6361731 100755 --- a/sample/scripts/test_android +++ b/sample/scripts/test_android @@ -4,4 +4,4 @@ set -e cd android -./gradlew clean generateAndroidManifestFromTemplate test --no-daemon --console=plain -Dorg.gradle.workers.max=1 -PreactNativeArchitectures=arm64-v8a +./gradlew clean generateAndroidManifestFromTemplate test --no-daemon --console=plain -Dorg.gradle.workers.max=1 -PreactNativeArchitectures=arm64-v8a -PnewArchEnabled=${ORG_GRADLE_PROJECT_newArchEnabled:-true} From 75d0fe90d5c82a8465bc8abc3f446d60b61b846f Mon Sep 17 00:00:00 2001 From: Mark Murray Date: Wed, 3 Sep 2025 16:49:29 +0100 Subject: [PATCH 6/6] Refactor Android module to work across architectures --- .github/workflows/ci.yml | 8 +- .../checkout-sheet-kit/android/build.gradle | 11 ++ .../ShopifyCheckoutSheetKitModule.java | 142 ++++++++++++++++++ .../ShopifyCheckoutSheetKitModule.java | 137 +++++++++++++++++ .../checkoutsheetkit/CheckoutKitDelegate.java | 62 ++++++++ .../checkoutsheetkit/CheckoutKitModule.java} | 80 ++++------ .../checkout-sheet-kit/package.snapshot.json | 5 +- sample/package.json | 3 +- sample/scripts/test_android | 10 +- scripts/compare_snapshot | 9 +- 10 files changed, 409 insertions(+), 58 deletions(-) create mode 100644 modules/@shopify/checkout-sheet-kit/android/src/legacy/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java create mode 100644 modules/@shopify/checkout-sheet-kit/android/src/newarch/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java create mode 100644 modules/@shopify/checkout-sheet-kit/android/src/shared/java/com/shopify/reactnative/checkoutsheetkit/CheckoutKitDelegate.java rename modules/@shopify/checkout-sheet-kit/android/src/{main/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java => shared/java/com/shopify/reactnative/checkoutsheetkit/CheckoutKitModule.java} (89%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 87f5af4b..f70871f5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -91,9 +91,9 @@ jobs: fail-fast: false matrix: include: - - arch: Legacy Arch + - arch: Legacy arch new_arch_enabled: 'false' - - arch: New Arch + - arch: New arch new_arch_enabled: 'true' steps: - name: Checkout @@ -132,9 +132,9 @@ jobs: fail-fast: false matrix: include: - - arch: legacy + - arch: Legacy arch new_arch_enabled: 'false' - - arch: new-arch + - arch: New arch new_arch_enabled: 'true' steps: - name: Checkout diff --git a/modules/@shopify/checkout-sheet-kit/android/build.gradle b/modules/@shopify/checkout-sheet-kit/android/build.gradle index 82b9a034..a23704f0 100644 --- a/modules/@shopify/checkout-sheet-kit/android/build.gradle +++ b/modules/@shopify/checkout-sheet-kit/android/build.gradle @@ -80,6 +80,17 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + + // Note: this is where the module class is chosen, based on the RN architecture + sourceSets { + main.java.srcDirs += ["src/shared/java"] + + if (isNewArchitectureEnabled()) { + main.java.srcDirs += ["src/newarch/java"] + } else { + main.java.srcDirs += ["src/legacy/java"] + } + } } repositories { diff --git a/modules/@shopify/checkout-sheet-kit/android/src/legacy/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java b/modules/@shopify/checkout-sheet-kit/android/src/legacy/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java new file mode 100644 index 00000000..447d51cb --- /dev/null +++ b/modules/@shopify/checkout-sheet-kit/android/src/legacy/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java @@ -0,0 +1,142 @@ +/* +MIT License + +Copyright 2023 - Present, Shopify Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +package com.shopify.reactnative.checkoutsheetkit; + +import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.ReadableMap; + +import java.util.Map; + +/** + * @note + * + * This is the legacy module class for the ShopifyCheckoutSheetKit module. + * It is used to support applications using React Native with the old + * legacy architecture. + */ + +public class ShopifyCheckoutSheetKitModule extends ReactContextBaseJavaModule { + private final CheckoutKitModule common; + public static com.shopify.checkoutsheetkit.Configuration checkoutConfig; + + public ShopifyCheckoutSheetKitModule(ReactApplicationContext reactContext) { + super(reactContext); + this.common = new CheckoutKitModule(reactContext); + ShopifyCheckoutSheetKitModule.checkoutConfig = CheckoutKitModule.checkoutConfig; + } + + @Override + public String getName() { + return common.getName(); + } + + @Override + public Map getConstants() { + return common.getConstants(); + } + + @ReactMethod + public void addListener(String eventName) { + common.addListener(eventName); + } + + @ReactMethod + public void configureAcceleratedCheckouts( + String storefrontDomain, + String storefrontAccessToken, + String customerEmail, + String customerPhoneNumber, + String customerAccessToken, + String applePayMerchantIdentifier, + ReadableArray applePayContactFields, + Promise promise) { + common.configureAcceleratedCheckouts( + storefrontDomain, + storefrontAccessToken, + customerEmail, + customerPhoneNumber, + customerAccessToken, + applePayMerchantIdentifier, + applePayContactFields, + promise); + } + + @ReactMethod + public void dismiss() { + common.dismiss(); + } + + @ReactMethod + public void getConfig(Promise promise) { + common.getConfig(promise); + } + + public String getVersion() { + return common.getVersion(); + } + + @ReactMethod + public void initiateGeolocationRequest(boolean allow) { + common.initiateGeolocationRequest(allow); + } + + @ReactMethod + public void invalidateCache() { + common.invalidateCache(); + } + + @ReactMethod + public void isAcceleratedCheckoutAvailable(Promise promise) { + common.isAcceleratedCheckoutAvailable(promise); + } + + @ReactMethod + public void isApplePayAvailable(Promise promise) { + common.isApplePayAvailable(promise); + } + + @ReactMethod + public void preload(String checkoutURL) { + common.preload(checkoutURL); + } + + @ReactMethod + public void present(String checkoutURL) { + common.present(checkoutURL); + } + + @ReactMethod + public void removeListeners(double count) { + common.removeListeners(count); + } + + @ReactMethod + public void setConfig(ReadableMap config) { + common.setConfig(config); + ShopifyCheckoutSheetKitModule.checkoutConfig = CheckoutKitModule.checkoutConfig; + } +} diff --git a/modules/@shopify/checkout-sheet-kit/android/src/newarch/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java b/modules/@shopify/checkout-sheet-kit/android/src/newarch/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java new file mode 100644 index 00000000..b7a4a817 --- /dev/null +++ b/modules/@shopify/checkout-sheet-kit/android/src/newarch/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java @@ -0,0 +1,137 @@ +/* +MIT License + +Copyright 2023 - Present, Shopify Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +package com.shopify.reactnative.checkoutsheetkit; + +import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.ReadableMap; + +import java.util.Map; + +/** + * @note + * + * This is the new architecture module class for the + * ShopifyCheckoutSheetKit module. + * It is used to support applications using React Native with the new + * new architecture. + */ + +public class ShopifyCheckoutSheetKitModule extends NativeShopifyCheckoutSheetKitSpec { + private final CheckoutKitModule common; + public static com.shopify.checkoutsheetkit.Configuration checkoutConfig; + + public ShopifyCheckoutSheetKitModule(ReactApplicationContext reactContext) { + super(reactContext); + this.common = new CheckoutKitModule(reactContext); + ShopifyCheckoutSheetKitModule.checkoutConfig = CheckoutKitModule.checkoutConfig; + } + + @Override + public Map getConstants() { + return common.getConstants(); + } + + @Override + public void addListener(String eventName) { + common.addListener(eventName); + } + + @Override + public void removeListeners(double count) { + common.removeListeners(count); + } + + @Override + public void present(String checkoutURL) { + common.present(checkoutURL); + } + + @Override + public void dismiss() { + common.dismiss(); + } + + @Override + public void preload(String checkoutURL) { + common.preload(checkoutURL); + } + + @Override + public void invalidateCache() { + common.invalidateCache(); + } + + @Override + public void getConfig(Promise promise) { + common.getConfig(promise); + } + + @Override + public void setConfig(ReadableMap config) { + common.setConfig(config); + ShopifyCheckoutSheetKitModule.checkoutConfig = CheckoutKitModule.checkoutConfig; + } + + @Override + public void isApplePayAvailable(Promise promise) { + common.isApplePayAvailable(promise); + } + + @Override + public void isAcceleratedCheckoutAvailable(Promise promise) { + common.isAcceleratedCheckoutAvailable(promise); + } + + @Override + public void configureAcceleratedCheckouts( + String storefrontDomain, + String storefrontAccessToken, + String customerEmail, + String customerPhoneNumber, + String customerAccessToken, + String applePayMerchantIdentifier, + ReadableArray applePayContactFields, + Promise promise) { + common.configureAcceleratedCheckouts( + storefrontDomain, + storefrontAccessToken, + customerEmail, + customerPhoneNumber, + customerAccessToken, + applePayMerchantIdentifier, + applePayContactFields, + promise); + } + + @Override + public void initiateGeolocationRequest(boolean allow) { + common.initiateGeolocationRequest(allow); + } + + @Override + public String getVersion() { + return common.getVersion(); + } +} diff --git a/modules/@shopify/checkout-sheet-kit/android/src/shared/java/com/shopify/reactnative/checkoutsheetkit/CheckoutKitDelegate.java b/modules/@shopify/checkout-sheet-kit/android/src/shared/java/com/shopify/reactnative/checkoutsheetkit/CheckoutKitDelegate.java new file mode 100644 index 00000000..419bca8b --- /dev/null +++ b/modules/@shopify/checkout-sheet-kit/android/src/shared/java/com/shopify/reactnative/checkoutsheetkit/CheckoutKitDelegate.java @@ -0,0 +1,62 @@ +/* +MIT License + +Copyright 2023 - Present, Shopify Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +package com.shopify.reactnative.checkoutsheetkit; + +import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.ReadableMap; + +import java.util.Map; + +public interface CheckoutKitDelegate { + void addListener(String eventName); + + void configureAcceleratedCheckouts(String domain, String token, String email, String phone, String customerToken, + String applePayMerchantId, ReadableArray contactFields, Promise promise); + + void dismiss(); + + void getConfig(Promise promise); + + String getName(); + + Map getConstants(); + + String getVersion(); + + void initiateGeolocationRequest(boolean allow); + + void invalidateCache(); + + void isAcceleratedCheckoutAvailable(Promise promise); + + void isApplePayAvailable(Promise promise); + + void preload(String checkoutUrl); + + void present(String checkoutUrl); + + void removeListeners(double count); + + void setConfig(ReadableMap config); +} diff --git a/modules/@shopify/checkout-sheet-kit/android/src/main/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java b/modules/@shopify/checkout-sheet-kit/android/src/shared/java/com/shopify/reactnative/checkoutsheetkit/CheckoutKitModule.java similarity index 89% rename from modules/@shopify/checkout-sheet-kit/android/src/main/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java rename to modules/@shopify/checkout-sheet-kit/android/src/shared/java/com/shopify/reactnative/checkoutsheetkit/CheckoutKitModule.java index 6081490f..20196282 100644 --- a/modules/@shopify/checkout-sheet-kit/android/src/main/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java +++ b/modules/@shopify/checkout-sheet-kit/android/src/shared/java/com/shopify/reactnative/checkoutsheetkit/CheckoutKitModule.java @@ -20,20 +20,15 @@ of this software and associated documentation files (the "Software"), to deal LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - package com.shopify.reactnative.checkoutsheetkit; import android.app.Activity; -import android.content.Context; import androidx.activity.ComponentActivity; -import androidx.annotation.NonNull; + import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.shopify.reactnative.checkoutsheetkit.NativeShopifyCheckoutSheetKitSpec; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.WritableNativeMap; import com.shopify.checkoutsheetkit.*; @@ -41,7 +36,7 @@ of this software and associated documentation files (the "Software"), to deal import java.util.Map; import java.util.Objects; -public class ShopifyCheckoutSheetKitModule extends NativeShopifyCheckoutSheetKitSpec { +public final class CheckoutKitModule implements CheckoutKitDelegate { public static Configuration checkoutConfig = new Configuration(); private final ReactApplicationContext reactContext; @@ -50,10 +45,8 @@ public class ShopifyCheckoutSheetKitModule extends NativeShopifyCheckoutSheetKit private CustomCheckoutEventProcessor checkoutEventProcessor; - public ShopifyCheckoutSheetKitModule(ReactApplicationContext reactContext) { - super(reactContext); - - this.reactContext = reactContext; + public CheckoutKitModule(ReactApplicationContext ctx) { + this.reactContext = ctx; ShopifyCheckoutSheetKit.configure(configuration -> { configuration.setPlatform(Platform.REACT_NATIVE); @@ -61,6 +54,11 @@ public ShopifyCheckoutSheetKitModule(ReactApplicationContext reactContext) { }); } + @Override + public String getName() { + return "ShopifyCheckoutSheetKit"; + } + @Override public Map getConstants() { final Map constants = new HashMap<>(); @@ -68,30 +66,33 @@ public Map getConstants() { return constants; } - @ReactMethod + @Override + public String getVersion() { + return ShopifyCheckoutSheetKit.version; + } + + @Override public void addListener(String eventName) { // No-op but required for RN to register module } - @ReactMethod + @Override public void removeListeners(double count) { // No-op but required for RN to register module } - @ReactMethod @Override - public void present(String checkoutURL) { + public void present(String checkoutUrl) { Activity currentActivity = getCurrentActivity(); if (currentActivity instanceof ComponentActivity) { checkoutEventProcessor = new CustomCheckoutEventProcessor(currentActivity, this.reactContext); currentActivity.runOnUiThread(() -> { - checkoutSheet = ShopifyCheckoutSheetKit.present(checkoutURL, (ComponentActivity) currentActivity, + checkoutSheet = ShopifyCheckoutSheetKit.present(checkoutUrl, (ComponentActivity) currentActivity, checkoutEventProcessor); }); } } - @ReactMethod @Override public void dismiss() { if (checkoutSheet != null) { @@ -100,23 +101,19 @@ public void dismiss() { } } - @ReactMethod @Override - public void preload(String checkoutURL) { + public void preload(String checkoutUrl) { Activity currentActivity = getCurrentActivity(); - if (currentActivity instanceof ComponentActivity) { - ShopifyCheckoutSheetKit.preload(checkoutURL, (ComponentActivity) currentActivity); + ShopifyCheckoutSheetKit.preload(checkoutUrl, (ComponentActivity) currentActivity); } } - @ReactMethod @Override public void invalidateCache() { ShopifyCheckoutSheetKit.invalidate(); } - @ReactMethod @Override public void getConfig(Promise promise) { WritableNativeMap resultConfig = new WritableNativeMap(); @@ -127,11 +124,8 @@ public void getConfig(Promise promise) { promise.resolve(resultConfig); } - @ReactMethod @Override public void setConfig(ReadableMap config) { - Context context = getReactApplicationContext(); - ShopifyCheckoutSheetKit.configure(configuration -> { if (config.hasKey("preloading")) { configuration.setPreloading(new Preloading(config.getBoolean("preloading"))); @@ -163,8 +157,10 @@ public void setConfig(ReadableMap config) { } @Override - public void isApplePayAvailable(Promise promise) { - promise.resolve(false); + public void initiateGeolocationRequest(boolean allow) { + if (checkoutEventProcessor != null) { + checkoutEventProcessor.invokeGeolocationCallback(allow); + } } @Override @@ -173,32 +169,22 @@ public void isAcceleratedCheckoutAvailable(Promise promise) { } @Override - public void configureAcceleratedCheckouts( - String storefrontDomain, - String storefrontAccessToken, - String customerEmail, - String customerPhoneNumber, - String customerAccessToken, - String applePayMerchantIdentifier, - ReadableArray applePayContactFields, - Promise promise) { + public void isApplePayAvailable(Promise promise) { promise.resolve(false); } - @ReactMethod - public void initiateGeolocationRequest(boolean allow) { - if (checkoutEventProcessor != null) { - checkoutEventProcessor.invokeGeolocationCallback(allow); - } - } - @Override - public String getVersion() { - return ShopifyCheckoutSheetKit.version; + public void configureAcceleratedCheckouts(String domain, String token, String email, String phone, + String customerToken, String applePayMerchantId, ReadableArray contactFields, Promise promise) { + promise.resolve(false); } // Private + private Activity getCurrentActivity() { + return reactContext.getCurrentActivity(); + } + private ColorScheme getColorScheme(String colorScheme) { switch (colorScheme) { case "web_default": diff --git a/modules/@shopify/checkout-sheet-kit/package.snapshot.json b/modules/@shopify/checkout-sheet-kit/package.snapshot.json index c24c8ab2..091cac94 100644 --- a/modules/@shopify/checkout-sheet-kit/package.snapshot.json +++ b/modules/@shopify/checkout-sheet-kit/package.snapshot.json @@ -4,11 +4,14 @@ "android/build.gradle", "android/gradle.properties", "android/proguard-rules.pro", + "android/src/legacy/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java", "android/src/main/AndroidManifest.xml", "android/src/main/AndroidManifestNew.xml", "android/src/main/java/com/shopify/reactnative/checkoutsheetkit/CustomCheckoutEventProcessor.java", - "android/src/main/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java", "android/src/main/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitPackage.java", + "android/src/newarch/java/com/shopify/reactnative/checkoutsheetkit/ShopifyCheckoutSheetKitModule.java", + "android/src/shared/java/com/shopify/reactnative/checkoutsheetkit/CheckoutKitDelegate.java", + "android/src/shared/java/com/shopify/reactnative/checkoutsheetkit/CheckoutKitModule.java", "ios/AcceleratedCheckoutButtons.swift", "ios/AcceleratedCheckoutButtons+Extensions.swift", "ios/ShopifyCheckoutSheetKit-Bridging-Header.h", diff --git a/sample/package.json b/sample/package.json index ae703ca5..a1c31b2b 100644 --- a/sample/package.json +++ b/sample/package.json @@ -14,7 +14,8 @@ "start": "react-native start -- --simulator 'iPhone 15 Pro' --reset-cache", "typecheck": "tsc --noEmit", "test:ios": "sh ./scripts/test_ios", - "test:android": "sh ./scripts/test_android" + "test:android": "sh ./scripts/test_android", + "test:android:legacy": "ORG_GRADLE_PROJECT_newArchEnabled=false sh ./scripts/test_android" }, "dependencies": { "@apollo/client": "^3.13.9", diff --git a/sample/scripts/test_android b/sample/scripts/test_android index e6361731..56bcfa77 100755 --- a/sample/scripts/test_android +++ b/sample/scripts/test_android @@ -2,6 +2,14 @@ set -e +NEW_ARCH_ENABLED=${ORG_GRADLE_PROJECT_newArchEnabled:-true} + cd android -./gradlew clean generateAndroidManifestFromTemplate test --no-daemon --console=plain -Dorg.gradle.workers.max=1 -PreactNativeArchitectures=arm64-v8a -PnewArchEnabled=${ORG_GRADLE_PROJECT_newArchEnabled:-true} +if [ "$NEW_ARCH_ENABLED" = "false" ]; then + echo "-> Running tests with Legacy Architecture" +else + echo "-> Running tests with New Architecture" +fi + +./gradlew clean generateAndroidManifestFromTemplate test --no-daemon --console=plain -Dorg.gradle.workers.max=1 -PreactNativeArchitectures=arm64-v8a -PnewArchEnabled=$NEW_ARCH_ENABLED diff --git a/scripts/compare_snapshot b/scripts/compare_snapshot index d6ea3579..9aaf647a 100755 --- a/scripts/compare_snapshot +++ b/scripts/compare_snapshot @@ -1,7 +1,10 @@ #!/bin/bash FILENAME="modules/@shopify/checkout-sheet-kit/package.snapshot.json" -TMP_SNAPSHOT_FILENAME="snapshot.json" +TMP_SNAPSHOT_FILENAME="/tmp/snapshot.json" + +# Always remove the temporary snapshot on exit +trap 'rm -f "$TMP_SNAPSHOT_FILENAME"' EXIT # Set up some colors to use later red=$(tput setaf 1) @@ -30,11 +33,9 @@ else If it NOT intentional, please manually check the diff below to discern if the file(s) should be included in the public package or not: -${green}EXISTING SNAPSHOT${reset} ${red}NEW SNAPSHOT${reset} +${green}EXISTING SNAPSHOT${reset} ${red}NEW SNAPSHOT${reset} " diff --color --side-by-side $FILENAME $TMP_SNAPSHOT_FILENAME exit 1 fi - -rm $TMP_SNAPSHOT_FILENAME