Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions example/screens/PresentActionScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
Alert,
TextInput,
Platform,
Switch,
} from 'react-native';
import type { NativeStackScreenProps } from '@react-navigation/native-stack';
import type { RootStackParamList } from '../App';
Expand All @@ -31,6 +32,7 @@ const PresentActionScreen: React.FC<Props> = () => {
const [isLoading, setIsLoading] = useState(false);
const [presentationStyleIOS, setPresentationStyleIOS] =
useState<PresentationStyleIOS>(PresentationStyles.formSheet);
const [debugEnabled, setDebugEnabled] = useState(false);

const environmentOptions = [
{ key: 'sandbox' as EnvironmentOption, label: 'Sandbox' },
Expand Down Expand Up @@ -85,6 +87,7 @@ const PresentActionScreen: React.FC<Props> = () => {
id: actionId.trim(),
environment: getEnvironment(),
presentationStyleIOS,
setDebug: debugEnabled,
onLaunch: () => {
console.log('Action launched');
setIsLoading(false);
Expand Down Expand Up @@ -172,6 +175,22 @@ const PresentActionScreen: React.FC<Props> = () => {
</View>
</View>

<View style={styles.section}>
<Text style={styles.sectionTitle}>Debug Mode</Text>
<View style={styles.switchGroup}>
<View style={styles.switchContainer}>
<Text style={styles.switchLabel}>Off</Text>
<Switch
value={debugEnabled}
onValueChange={setDebugEnabled}
trackColor={{ false: '#d1d5db', true: '#3b82f6' }}
thumbColor="#fff"
/>
<Text style={styles.switchLabel}>On</Text>
</View>
</View>
</View>

<View style={styles.section}>
<Text style={styles.sectionTitle}>How it works</Text>
<View style={styles.infoCard}>
Expand Down
16 changes: 16 additions & 0 deletions example/screens/TransactScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ const TransactScreen: React.FC<Props> = () => {
const [deeplinkStep, setDeeplinkStep] = useState<StepType>(
Step.LOGIN_COMPANY
);
const [debugEnabled, setDebugEnabled] = useState(false);

const products = [
{ key: Product.DEPOSIT, label: 'Deposit' },
Expand Down Expand Up @@ -142,6 +143,7 @@ const TransactScreen: React.FC<Props> = () => {
config,
environment: getEnvironment(),
presentationStyleIOS,
setDebug: debugEnabled,
onInteraction: (interaction: any) => {
console.log('Interaction:', interaction);
},
Expand Down Expand Up @@ -239,6 +241,20 @@ const TransactScreen: React.FC<Props> = () => {
/>
</View>
</View>

<View style={styles.switchGroup}>
<Text style={styles.label}>Debug Mode</Text>
<View style={styles.switchContainer}>
<Text style={styles.switchLabel}>Off</Text>
<Switch
value={debugEnabled}
onValueChange={setDebugEnabled}
trackColor={{ false: '#d1d5db', true: '#3b82f6' }}
thumbColor="#fff"
/>
<Text style={styles.switchLabel}>On</Text>
</View>
</View>
</View>

<View style={styles.section}>
Expand Down
2 changes: 2 additions & 0 deletions ios/TransactReactNative.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ @interface RCT_EXTERN_MODULE(TransactReactNative, RCTEventEmitter)
RCT_EXTERN_METHOD(presentTransact:(NSDictionary *)config
environment:(NSDictionary *)environment
presentationStyle:(nullable NSString *)presentationStyle
setDebug:(nullable NSNumber *)setDebug
withResolver:(RCTPromiseResolveBlock)resolve
withRejecter:(RCTPromiseRejectBlock)reject)

RCT_EXTERN_METHOD(presentAction:(NSString *)id
environment:(NSDictionary *)environment
presentationStyle:(nullable NSString *)presentationStyle
setDebug:(nullable NSNumber *)setDebug
withResolver:(RCTPromiseResolveBlock)resolve
withRejecter:(RCTPromiseRejectBlock)reject)

Expand Down
44 changes: 28 additions & 16 deletions ios/TransactReactNative.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,28 +37,34 @@ class TransactReactNative: RCTEventEmitter {
}
}

@objc(presentTransact:environment:presentationStyle:withResolver:withRejecter:)
func presentTransact(config: [String: Any], environment: [String: Any], presentationStyle: String?, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
DispatchQueue.main.async {
@objc(presentTransact:environment:presentationStyle:setDebug:withResolver:withRejecter:)
func presentTransact(config: [String: Any], environment: [String: Any], presentationStyle: String?, setDebug: NSNumber?, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
let debugEnabled = setDebug?.boolValue ?? false

Task { @MainActor in
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@eriksargent this is the biggest change that was made. Just wanted to double check that this is going to be ok to switch from DispatchQueue.main.async

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yep, looks great 👍

await Atomic.setDebug(isEnabled: debugEnabled, forwardLogs: { logMessage in
self.sendEvent(withName: "onDebugLog", body: ["message": logMessage])
})

guard let source = RCTPresentedViewController() else { return }

let decoder = JSONDecoder()
let parsedEnvironment = self.parseEnvironment(environment)

do {
var json = config

let parsedPresentationStyle = self.parsePresentationStyle(presentationStyle)

if var platform = AtomicConfig.Platform().encode() as? [String: Any] {
platform["sdkVersion"] = platform["sdkVersion"] as! String + "-react"
json["platform"] = platform
}

guard let data = try? JSONSerialization.data(withJSONObject: json, options: []) else { return }

let config = try decoder.decode(AtomicConfig.self, from: data)

Atomic.presentTransact(
from: source, config: config, environment: parsedEnvironment, presentationStyle: parsedPresentationStyle,
onInteraction: { interaction in
Expand All @@ -67,7 +73,7 @@ class TransactReactNative: RCTEventEmitter {
onDataRequest: { request async -> TransactDataResponse? in
// Create a task to handle the async request to React Native
return await withCheckedContinuation { continuation in
// Store the completion handler
// Store the completion handler
self.dataResponseHandler = { responseData in
if let responseDict = responseData as? [String: Any] {
// The SDK expects the response data to be passed directly
Expand All @@ -87,7 +93,7 @@ class TransactReactNative: RCTEventEmitter {
continuation.resume(returning: nil)
}
}

// Send event with request data to React Native
self.sendEvent(withName: "onDataRequest", body: request.data)
}
Expand Down Expand Up @@ -130,14 +136,20 @@ class TransactReactNative: RCTEventEmitter {
}
}

@objc(presentAction:environment:presentationStyle:withResolver:withRejecter:)
func presentAction(id: String, environment: [String: Any], presentationStyle: String?, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
DispatchQueue.main.async {
@objc(presentAction:environment:presentationStyle:setDebug:withResolver:withRejecter:)
func presentAction(id: String, environment: [String: Any], presentationStyle: String?, setDebug: NSNumber?, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
let debugEnabled = setDebug?.boolValue ?? false

Task { @MainActor in
await Atomic.setDebug(isEnabled: debugEnabled, forwardLogs: { logMessage in
self.sendEvent(withName: "onDebugLog", body: ["message": logMessage])
})

guard let source = RCTPresentedViewController() else { return }

let parsedEnvironment = self.parseEnvironment(environment)
let parsedPresentationStyle = self.parsePresentationStyle(presentationStyle)

Atomic.presentAction(
from: source,
id: id,
Expand Down Expand Up @@ -181,7 +193,7 @@ class TransactReactNative: RCTEventEmitter {
}

@objc override func supportedEvents() -> [String] {
return ["onInteraction", "onDataRequest", "onLaunch", "onCompletion", "onAuthStatusUpdate", "onTaskStatusUpdate"]
return ["onInteraction", "onDataRequest", "onLaunch", "onCompletion", "onAuthStatusUpdate", "onTaskStatusUpdate", "onDebugLog"]
}

@objc override static func requiresMainQueueSetup() -> Bool {
Expand Down
6 changes: 6 additions & 0 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ export const Atomic = {
onAuthStatusUpdate,
onTaskStatusUpdate,
presentationStyleIOS,
setDebug,
}: {
config: Config;
environment?: CONSTANTS.TransactEnvironment;
Expand All @@ -112,6 +113,7 @@ export const Atomic = {
onFinish?: Function;
onClose?: Function;
presentationStyleIOS?: PresentationStyleIOS;
setDebug?: boolean;
}): void {
config.language = config.language || 'en';
config.theme = config.theme || {};
Expand All @@ -131,6 +133,7 @@ export const Atomic = {
onAuthStatusUpdate,
onTaskStatusUpdate,
presentationStyleIOS,
setDebug,
};

switch (Platform.OS) {
Expand All @@ -153,6 +156,7 @@ export const Atomic = {
onClose,
onAuthStatusUpdate,
onTaskStatusUpdate,
setDebug,
}: {
id: String;
environment?: CONSTANTS.TransactEnvironment;
Expand All @@ -162,6 +166,7 @@ export const Atomic = {
onClose?: Function;
onAuthStatusUpdate?: Function;
onTaskStatusUpdate?: Function;
setDebug?: boolean;
}): void {
const args = {
TransactReactNative,
Expand All @@ -173,6 +178,7 @@ export const Atomic = {
onClose,
onAuthStatusUpdate,
onTaskStatusUpdate,
setDebug,
};

switch (Platform.OS) {
Expand Down
28 changes: 26 additions & 2 deletions src/ios.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const AtomicIOS = {
onAuthStatusUpdate,
onTaskStatusUpdate,
presentationStyleIOS,
setDebug,
}: {
TransactReactNative: any;
config: any;
Expand All @@ -24,20 +25,30 @@ export const AtomicIOS = {
onAuthStatusUpdate?: Function;
onTaskStatusUpdate?: Function;
presentationStyleIOS?: CONSTANTS.PresentationStyleIOS;
setDebug?: boolean;
}): void {
const TransactReactNativeEvents = new NativeEventEmitter(
TransactReactNative
);
let onInteractionListener: any;
let onDataRequestListener: any;
let onAuthStatusUpdateListener: any;
let onDebugLogListener: any;

const removeListeners = () => {
if (onInteractionListener) onInteractionListener.remove();
if (onDataRequestListener) onDataRequestListener.remove();
if (onAuthStatusUpdateListener) onAuthStatusUpdateListener.remove();
if (onDebugLogListener) onDebugLogListener.remove();
};

onDebugLogListener = TransactReactNativeEvents.addListener(
'onDebugLog',
(log) => {
console.debug('[TransactNative]', log.message);
}
);

if (onInteraction) {
onInteractionListener = TransactReactNativeEvents.addListener(
'onInteraction',
Expand Down Expand Up @@ -84,7 +95,8 @@ export const AtomicIOS = {
TransactReactNative.presentTransact(
config,
environment,
presentationStyleIOS
presentationStyleIOS,
setDebug
).then((event: any) => {
if (event.finished && onFinish) {
removeListeners();
Expand All @@ -105,6 +117,7 @@ export const AtomicIOS = {
onClose,
onAuthStatusUpdate,
onTaskStatusUpdate,
setDebug,
}: {
TransactReactNative: any;
id: String;
Expand All @@ -115,18 +128,28 @@ export const AtomicIOS = {
onClose?: Function;
onAuthStatusUpdate?: Function;
onTaskStatusUpdate?: Function;
setDebug?: boolean;
}): void {
const TransactReactNativeEvents = new NativeEventEmitter(
TransactReactNative
);
let onLaunchListener: any;
let onAuthStatusUpdateListener: any;
let onDebugLogListener: any;

const removeListeners = () => {
if (onLaunchListener) onLaunchListener.remove();
if (onAuthStatusUpdateListener) onAuthStatusUpdateListener.remove();
if (onDebugLogListener) onDebugLogListener.remove();
};

onDebugLogListener = TransactReactNativeEvents.addListener(
'onDebugLog',
(log) => {
console.debug('[TransactNative]', log.message);
}
);

if (onLaunch) {
onLaunchListener = TransactReactNativeEvents.addListener('onLaunch', () =>
onLaunch()
Expand All @@ -150,7 +173,8 @@ export const AtomicIOS = {
TransactReactNative.presentAction(
id,
environment,
presentationStyleIOS
presentationStyleIOS,
setDebug
).then((event: any) => {
if (event.finished && onFinish) {
removeListeners();
Expand Down
Loading