@propel-nsl/propel-react-native-sdk 1.0.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/assets/fonts/Lexend-Black.ttf +0 -0
- package/assets/fonts/Lexend-Bold.ttf +0 -0
- package/assets/fonts/Lexend-ExtraBold.ttf +0 -0
- package/assets/fonts/Lexend-ExtraLight.ttf +0 -0
- package/assets/fonts/Lexend-Light.ttf +0 -0
- package/assets/fonts/Lexend-Medium.ttf +0 -0
- package/assets/fonts/Lexend-Regular.ttf +0 -0
- package/assets/fonts/Lexend-SemiBold.ttf +0 -0
- package/assets/fonts/Lexend-Thin.ttf +0 -0
- package/assets/images/HomeGoods.png +0 -0
- package/assets/images/accessories.png +0 -0
- package/assets/images/amazon.png +0 -0
- package/assets/images/apnaClubLogo.png +0 -0
- package/assets/images/apparel.png +0 -0
- package/assets/images/backgroundblue.png +0 -0
- package/assets/images/bannerCard.png +0 -0
- package/assets/images/bottomWave.png +0 -0
- package/assets/images/coin_1_1.png +0 -0
- package/assets/images/flipkart.png +0 -0
- package/assets/images/frame_1171278967.png +0 -0
- package/assets/images/gift.png +0 -0
- package/assets/images/herobanner.png +0 -0
- package/assets/images/hinduPencilsLogo.png +0 -0
- package/assets/images/icons/addwhiteicon.png +0 -0
- package/assets/images/icons/arrow-back.png +0 -0
- package/assets/images/icons/arrowgreen.png +0 -0
- package/assets/images/icons/arrowred.png +0 -0
- package/assets/images/icons/arrowright.png +0 -0
- package/assets/images/icons/arrowup.png +0 -0
- package/assets/images/icons/blackarrowdown.png +0 -0
- package/assets/images/icons/blackarrowup.png +0 -0
- package/assets/images/icons/blackcross.png +0 -0
- package/assets/images/icons/call.png +0 -0
- package/assets/images/icons/camera.png +0 -0
- package/assets/images/icons/cart.png +0 -0
- package/assets/images/icons/chat.png +0 -0
- package/assets/images/icons/circleblack.png +0 -0
- package/assets/images/icons/copy.png +0 -0
- package/assets/images/icons/cross.png +0 -0
- package/assets/images/icons/delete.png +0 -0
- package/assets/images/icons/delivery.png +0 -0
- package/assets/images/icons/eVoucher.png +0 -0
- package/assets/images/icons/editIcon.png +0 -0
- package/assets/images/icons/email.png +0 -0
- package/assets/images/icons/eye.png +0 -0
- package/assets/images/icons/faq.png +0 -0
- package/assets/images/icons/filtericon.png +0 -0
- package/assets/images/icons/greyDownArrow.png +0 -0
- package/assets/images/icons/help.png +0 -0
- package/assets/images/icons/home.png +0 -0
- package/assets/images/icons/homeinactive.png +0 -0
- package/assets/images/icons/i_blackicon.png +0 -0
- package/assets/images/icons/i_icon.png +0 -0
- package/assets/images/icons/location.png +0 -0
- package/assets/images/icons/logout.png +0 -0
- package/assets/images/icons/minus.png +0 -0
- package/assets/images/icons/myOrders.png +0 -0
- package/assets/images/icons/orders.png +0 -0
- package/assets/images/icons/pencillogo.png +0 -0
- package/assets/images/icons/pending.png +0 -0
- package/assets/images/icons/plus.png +0 -0
- package/assets/images/icons/redCross.png +0 -0
- package/assets/images/icons/redCrossicon.png +0 -0
- package/assets/images/icons/redWarningicon.png +0 -0
- package/assets/images/icons/redeem.png +0 -0
- package/assets/images/icons/redeemactive.png +0 -0
- package/assets/images/icons/redemptionHistory.png +0 -0
- package/assets/images/icons/redhelpicon.png +0 -0
- package/assets/images/icons/search.png +0 -0
- package/assets/images/icons/stopwatch.png +0 -0
- package/assets/images/icons/successTick.gif +0 -0
- package/assets/images/icons/tick.png +0 -0
- package/assets/images/icons/tnc.png +0 -0
- package/assets/images/icons/user.png +0 -0
- package/assets/images/icons/userredicon.png +0 -0
- package/assets/images/icons/wavecorner.png +0 -0
- package/assets/images/logo.png +0 -0
- package/assets/images/myntra_copy.png +0 -0
- package/assets/images/nike.png +0 -0
- package/assets/images/oq3p0u0_1.png +0 -0
- package/assets/images/profileicon.png +0 -0
- package/assets/images/topWave.png +0 -0
- package/assets/images/zagglePropelLogo.png +0 -0
- package/index.ts +23 -0
- package/lib/index.ts +25 -0
- package/package.json +70 -0
- package/src/PropelSDKScreen.tsx +98 -0
- package/src/SDKApp.tsx +540 -0
- package/src/bridge/SDKBridge.ts +104 -0
- package/src/bridge/index.ts +3 -0
- package/src/components/SDKBackHandler.tsx +187 -0
- package/src/components/SDKProfile.tsx +87 -0
- package/src/components/SDKProfileWrapper.tsx +51 -0
- package/src/constants.ts +10 -0
- package/src/contexts/SDKContext.tsx +72 -0
- package/src/hooks/useSDKBackNavigation.ts +61 -0
- package/src/navigation/SDKMainTabNavigator.tsx +315 -0
- package/src/navigation/SDKNavigator.tsx +41 -0
- package/src/redux/store.ts +32 -0
- package/src/screens/Dashboard/index.tsx +531 -0
- package/src/screens/Dashboard/styles.ts +512 -0
- package/src/screens/DeliveryAddress/index.tsx +221 -0
- package/src/screens/DeliveryAddress/styles.ts +122 -0
- package/src/screens/E-Vouchers/index.tsx +157 -0
- package/src/screens/E-Vouchers/styles.ts +106 -0
- package/src/screens/Faq/Faq.constants.ts +164 -0
- package/src/screens/Faq/index.tsx +114 -0
- package/src/screens/Faq/styles.ts +131 -0
- package/src/screens/Help/index.tsx +128 -0
- package/src/screens/Help/styles.ts +121 -0
- package/src/screens/Login/index.tsx +215 -0
- package/src/screens/Login/styles.ts +134 -0
- package/src/screens/MyCart/MyCart.constants.ts +13 -0
- package/src/screens/MyCart/index.tsx +318 -0
- package/src/screens/MyCart/styles.ts +249 -0
- package/src/screens/MyOrders/index.tsx +87 -0
- package/src/screens/MyOrders/styles.ts +281 -0
- package/src/screens/MyProfile/index.tsx +72 -0
- package/src/screens/MyProfile/styles.ts +47 -0
- package/src/screens/NewDeliveryAddress/index.tsx +360 -0
- package/src/screens/NewDeliveryAddress/styles.ts +68 -0
- package/src/screens/Onboarding/index.tsx +57 -0
- package/src/screens/Onboarding/styles.ts +60 -0
- package/src/screens/OrdersDetails/index.tsx +333 -0
- package/src/screens/OrdersDetails/styles.ts +262 -0
- package/src/screens/OtpVerification/index.tsx +283 -0
- package/src/screens/OtpVerification/styles.ts +197 -0
- package/src/screens/PaymentMethod/index.tsx +389 -0
- package/src/screens/PaymentMethod/styles.ts +246 -0
- package/src/screens/PointsLog/index.tsx +286 -0
- package/src/screens/PointsLog/styles.ts +156 -0
- package/src/screens/ProductDetails/index.tsx +682 -0
- package/src/screens/ProductDetails/styles.ts +372 -0
- package/src/screens/Profile/index.tsx +368 -0
- package/src/screens/Profile/styles.ts +158 -0
- package/src/screens/RedemptionHistory/RedemptionHistory.constants.ts +4 -0
- package/src/screens/RedemptionHistory/index.tsx +304 -0
- package/src/screens/RedemptionHistory/styles.ts +84 -0
- package/src/screens/Reedem/index.tsx +345 -0
- package/src/screens/Reedem/styles.ts +269 -0
- package/src/screens/TnC/TnC.constants.ts +169 -0
- package/src/screens/TnC/index.tsx +83 -0
- package/src/screens/TnC/styles.ts +88 -0
- package/src/screens/TransactionSuccessful/index.tsx +77 -0
- package/src/screens/TransactionSuccessful/styles.ts +77 -0
- package/src/screens/Verification/index.tsx +58 -0
- package/src/screens/Verification/styles.ts +74 -0
- package/src/screens/index.ts +23 -0
- package/src/types/index.ts +46 -0
- package/src-app/components/AmountBreakDownModal/index.tsx +86 -0
- package/src-app/components/AmountBreakDownModal/styles.ts +110 -0
- package/src-app/components/BottomNavIcons.tsx +125 -0
- package/src-app/components/Button.tsx +120 -0
- package/src-app/components/Card.tsx +47 -0
- package/src-app/components/ConfirmPopup/ConfirmPopup.constants.ts +25 -0
- package/src-app/components/ConfirmPopup/index.tsx +48 -0
- package/src-app/components/ConfirmPopup/styles.ts +167 -0
- package/src-app/components/CustomButton/index.tsx +67 -0
- package/src-app/components/CustomButton/styles.ts +44 -0
- package/src-app/components/CustomCard/index.tsx +221 -0
- package/src-app/components/CustomCard/styles.ts +184 -0
- package/src-app/components/CustomError/index.tsx +54 -0
- package/src-app/components/CustomError/styles.ts +41 -0
- package/src-app/components/CustomImage/index.tsx +37 -0
- package/src-app/components/CustomImage/styles.ts +5 -0
- package/src-app/components/CustomLoader/index.tsx +45 -0
- package/src-app/components/CustomLoader/styles.ts +35 -0
- package/src-app/components/CustomMessagePopUp/index.tsx +51 -0
- package/src-app/components/CustomMessagePopUp/styles.ts +74 -0
- package/src-app/components/CustomProductCard/index.tsx +13 -0
- package/src-app/components/CustomProductCard/styles.ts +5 -0
- package/src-app/components/FilterModal.tsx +372 -0
- package/src-app/components/Footer/index.tsx +23 -0
- package/src-app/components/Footer/styles.ts +37 -0
- package/src-app/components/Icon.tsx +80 -0
- package/src-app/components/Logout/index.tsx +82 -0
- package/src-app/components/Logout/styles.ts +116 -0
- package/src-app/components/MobileHeader.tsx +141 -0
- package/src-app/components/NoDataFound/index.tsx +18 -0
- package/src-app/components/NoDataFound/styles.ts +26 -0
- package/src-app/components/OTPModal.tsx +747 -0
- package/src-app/components/ProfileField.tsx +47 -0
- package/src-app/components/QuantityModal/index.tsx +113 -0
- package/src-app/components/QuantityModal/styles.ts +84 -0
- package/src-app/components/TabBarIcons.tsx +110 -0
- package/src-app/components/TextInput.tsx +79 -0
- package/src-app/components/ToastConfig.tsx +60 -0
- package/src-app/components/index.ts +18 -0
- package/src-app/config/env.ts +22 -0
- package/src-app/constants/Fonts.ts +12 -0
- package/src-app/constants/Formatter.ts +39 -0
- package/src-app/constants/HtmlSanitization.ts +46 -0
- package/src-app/constants/Images.ts +81 -0
- package/src-app/constants/Labels.ts +8 -0
- package/src-app/constants/Messages.ts +108 -0
- package/src-app/constants/Routes.ts +17 -0
- package/src-app/constants/Scaling.ts +5 -0
- package/src-app/constants/Text.ts +8 -0
- package/src-app/constants/offSets.ts +18 -0
- package/src-app/hooks/useAppDispatch.ts +4 -0
- package/src-app/hooks/useAppSelector.ts +4 -0
- package/src-app/hooks/useBackHandler.ts +47 -0
- package/src-app/hooks/useScreenBackHandler.ts +91 -0
- package/src-app/navigation/AppNavigator.tsx +34 -0
- package/src-app/navigation/MainTabNavigator.tsx +294 -0
- package/src-app/redux/authSaga.ts +605 -0
- package/src-app/redux/authSlice.ts +754 -0
- package/src-app/redux/rootSaga.ts +6 -0
- package/src-app/redux/store.ts +25 -0
- package/src-app/services/api.ts +14 -0
- package/src-app/services/endpoints.ts +33 -0
- package/src-app/services/index.ts +574 -0
- package/src-app/services/sdkCredentials.ts +44 -0
- package/src-app/styles/colors.ts +85 -0
- package/src-app/styles/shared.ts +112 -0
- package/src-app/types/authTypes.ts +155 -0
- package/src-app/types/navigation.ts +99 -0
- package/src-app/utils/Validation.ts +48 -0
- package/src-app/utils/filterPins.ts +29 -0
- package/src-app/utils/navigationUtils.ts +43 -0
- package/src-app/utils/useHardwareBack.ts +21 -0
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { View, StyleSheet, DeviceEventEmitter, NativeModules, BackHandler } from 'react-native';
|
|
3
|
+
import { CommonActions, StackActions, useNavigation, useFocusEffect } from '@react-navigation/native';
|
|
4
|
+
import { useSDKContext } from '../contexts/SDKContext';
|
|
5
|
+
import { useAppDispatch } from '../../src-app/hooks/useAppDispatch';
|
|
6
|
+
import { clearAllAuthState } from '../../src-app/redux/authSlice';
|
|
7
|
+
|
|
8
|
+
// Main visible tabs - these are root-level screens
|
|
9
|
+
const MAIN_TABS = ['DashboardTab', 'Redeem', 'Profile', 'Help'];
|
|
10
|
+
|
|
11
|
+
// Hidden tab screens
|
|
12
|
+
const HIDDEN_TABS = [
|
|
13
|
+
'RedemptionHistory', 'MyOrders', 'OrderDetails', 'FAQ', 'TnC',
|
|
14
|
+
'ProductDetail', 'MyEVouchers', 'MyCart', 'PointsLog',
|
|
15
|
+
'DeliveryAddress', 'NewDeliveryAddress', 'PaymentMethod', 'TransactionSuccessful'
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
const SDKBackHandler: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
|
19
|
+
const navigation = useNavigation();
|
|
20
|
+
const { isDeepLinkEntry } = useSDKContext();
|
|
21
|
+
const dispatch = useAppDispatch();
|
|
22
|
+
|
|
23
|
+
// Helper to exit SDK and clear auth state
|
|
24
|
+
const exitSDK = React.useCallback(() => {
|
|
25
|
+
console.log('🚀 Exiting SDK - clearing auth state');
|
|
26
|
+
dispatch(clearAllAuthState());
|
|
27
|
+
if (NativeModules.PropelSDKBridge?.closeSDK) {
|
|
28
|
+
NativeModules.PropelSDKBridge.closeSDK();
|
|
29
|
+
}
|
|
30
|
+
}, [dispatch]);
|
|
31
|
+
|
|
32
|
+
// Shared back handler logic
|
|
33
|
+
const handleBackPress = React.useCallback(() => {
|
|
34
|
+
console.log('🔍 SDK Back Handler Called');
|
|
35
|
+
|
|
36
|
+
// Get current navigation state - need to look into the nested tab navigator
|
|
37
|
+
const rootState = navigation.getState();
|
|
38
|
+
console.log('🔍 Root navigation state:', JSON.stringify(rootState, null, 2));
|
|
39
|
+
|
|
40
|
+
// Find the MainTabs route (which contains the tab navigator)
|
|
41
|
+
const mainTabsRoute = rootState?.routes?.find(route => route.name === 'MainTabs');
|
|
42
|
+
const tabState = mainTabsRoute?.state;
|
|
43
|
+
|
|
44
|
+
const currentIndex = tabState?.index ?? 0;
|
|
45
|
+
const currentRoute = tabState?.routes?.[currentIndex];
|
|
46
|
+
const currentTabName = currentRoute?.name;
|
|
47
|
+
const tabHistory = tabState?.history as Array<{ type: string; key: string }> | undefined;
|
|
48
|
+
|
|
49
|
+
console.log('🔍 Current tab:', currentTabName, 'index:', currentIndex);
|
|
50
|
+
console.log('🔍 Tab history length:', tabHistory?.length);
|
|
51
|
+
console.log('🔍 Is main tab?', MAIN_TABS.includes(currentTabName || ''));
|
|
52
|
+
console.log('🔍 Is hidden tab?', HIDDEN_TABS.includes(currentTabName || ''));
|
|
53
|
+
|
|
54
|
+
// Check if we're in DashboardTab and have nested stack screens
|
|
55
|
+
let isOnDashboardRoot = false;
|
|
56
|
+
let dashboardStackIndex = 0;
|
|
57
|
+
|
|
58
|
+
if (currentTabName === 'DashboardTab' && currentRoute?.state) {
|
|
59
|
+
const dashboardStackState = currentRoute.state as { routes?: any[]; index?: number };
|
|
60
|
+
dashboardStackIndex = dashboardStackState.index ?? 0;
|
|
61
|
+
isOnDashboardRoot = dashboardStackIndex === 0;
|
|
62
|
+
console.log('🔍 DashboardStack index:', dashboardStackIndex, 'isOnDashboardRoot:', isOnDashboardRoot);
|
|
63
|
+
} else if (currentTabName === 'DashboardTab') {
|
|
64
|
+
isOnDashboardRoot = true;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// CASE 1: We're in DashboardTab with nested screens - pop the stack
|
|
68
|
+
if (currentTabName === 'DashboardTab' && dashboardStackIndex > 0) {
|
|
69
|
+
console.log('🔙 Popping DashboardStack');
|
|
70
|
+
// Use goBack which will pop the stack
|
|
71
|
+
navigation.goBack();
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// CASE 2: We're on Dashboard root - exit SDK
|
|
76
|
+
if (currentTabName === 'DashboardTab' && isOnDashboardRoot) {
|
|
77
|
+
console.log('🚀 On Dashboard root - exiting SDK');
|
|
78
|
+
exitSDK();
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// CASE 3: We're on a hidden tab screen (MyCart, ProductDetail, etc.)
|
|
83
|
+
// These screens should go back to where they came from
|
|
84
|
+
if (HIDDEN_TABS.includes(currentTabName || '')) {
|
|
85
|
+
const fromParam = (currentRoute?.params as any)?.from;
|
|
86
|
+
console.log('🔍 On hidden tab:', currentTabName, 'from:', fromParam);
|
|
87
|
+
|
|
88
|
+
// Check if tab history has previous screens
|
|
89
|
+
if (tabHistory && tabHistory.length > 1) {
|
|
90
|
+
console.log('🔙 Using tab history to go back');
|
|
91
|
+
navigation.goBack();
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// No history - check where we came from
|
|
96
|
+
if (fromParam === 'Profile') {
|
|
97
|
+
console.log('🔙 Going back to Profile');
|
|
98
|
+
navigation.navigate('Profile' as never);
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (fromParam === 'Redeem' || fromParam === 'REDEEM') {
|
|
103
|
+
console.log('🔙 Going back to Redeem');
|
|
104
|
+
navigation.navigate('Redeem' as never);
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Default: exit SDK instead of going to Dashboard
|
|
109
|
+
console.log('🚀 No clear back path from hidden tab - exiting SDK');
|
|
110
|
+
exitSDK();
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// CASE 4: We're on a main tab (Redeem, Profile, Help)
|
|
115
|
+
if (MAIN_TABS.includes(currentTabName || '')) {
|
|
116
|
+
// For main tabs, always go back to Dashboard instead of following tab history
|
|
117
|
+
if (currentTabName !== 'DashboardTab') {
|
|
118
|
+
console.log('🔙 Going back to Dashboard from main tab:', currentTabName);
|
|
119
|
+
// Use dispatch with CommonActions.navigate to reset tab navigation properly
|
|
120
|
+
navigation.dispatch(
|
|
121
|
+
CommonActions.navigate({
|
|
122
|
+
name: 'DashboardTab',
|
|
123
|
+
params: { screen: 'Dashboard' },
|
|
124
|
+
})
|
|
125
|
+
);
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// If we're already on Dashboard (shouldn't happen in this case), exit SDK
|
|
130
|
+
console.log('🚀 Already on Dashboard - exiting SDK');
|
|
131
|
+
exitSDK();
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Fallback: try goBack, then Dashboard
|
|
136
|
+
if (navigation.canGoBack()) {
|
|
137
|
+
console.log('🔙 Fallback: using goBack()');
|
|
138
|
+
navigation.goBack();
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
console.log('� Fallback: no navigation options - exiting SDK');
|
|
143
|
+
exitSDK();
|
|
144
|
+
return true;
|
|
145
|
+
}, [navigation, isDeepLinkEntry, exitSDK]);
|
|
146
|
+
|
|
147
|
+
// Handle custom SDK events
|
|
148
|
+
React.useEffect(() => {
|
|
149
|
+
console.log('🔵 SDKBackHandler MOUNTED');
|
|
150
|
+
const SDK_BACK_PRESS_EVENT = 'propelsdk_hardwareBackPress';
|
|
151
|
+
|
|
152
|
+
// Subscribe to DeviceEventEmitter (native emits SDK-scoped back press event)
|
|
153
|
+
const deviceEventSubscription = DeviceEventEmitter.addListener(SDK_BACK_PRESS_EVENT, () => {
|
|
154
|
+
console.log('🔵 DeviceEventEmitter propelsdk_hardwareBackPress received');
|
|
155
|
+
handleBackPress();
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
return () => {
|
|
159
|
+
console.log('🔴 SDKBackHandler UNMOUNTED');
|
|
160
|
+
deviceEventSubscription.remove();
|
|
161
|
+
};
|
|
162
|
+
}, [handleBackPress]);
|
|
163
|
+
|
|
164
|
+
// Handle standard React Native BackHandler
|
|
165
|
+
useFocusEffect(
|
|
166
|
+
React.useCallback(() => {
|
|
167
|
+
const onBackPress = () => {
|
|
168
|
+
console.log('🔵 Standard BackHandler triggered');
|
|
169
|
+
return handleBackPress();
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
const subscription = BackHandler.addEventListener('hardwareBackPress', onBackPress);
|
|
173
|
+
|
|
174
|
+
return () => subscription.remove();
|
|
175
|
+
}, [handleBackPress])
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
return <View style={styles.container}>{children}</View>;
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
const styles = StyleSheet.create({
|
|
182
|
+
container: {
|
|
183
|
+
flex: 1,
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
export default SDKBackHandler;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { View, StyleSheet } from 'react-native';
|
|
3
|
+
import Profile from '../screens/Profile';
|
|
4
|
+
import { useNavigation } from '@react-navigation/native';
|
|
5
|
+
|
|
6
|
+
// Screens that are registered as hidden tabs in SDK (not inside DashboardStack)
|
|
7
|
+
const HIDDEN_TAB_SCREENS = [
|
|
8
|
+
'RedemptionHistory',
|
|
9
|
+
'MyOrders',
|
|
10
|
+
'OrderDetails',
|
|
11
|
+
'FAQ',
|
|
12
|
+
'TnC',
|
|
13
|
+
'ProductDetail',
|
|
14
|
+
'MyEVouchers',
|
|
15
|
+
'MyCart',
|
|
16
|
+
'PointsLog',
|
|
17
|
+
'DeliveryAddress',
|
|
18
|
+
'NewDeliveryAddress',
|
|
19
|
+
'PaymentMethod',
|
|
20
|
+
'TransactionSuccessful',
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* SDK Profile Wrapper
|
|
25
|
+
*
|
|
26
|
+
* This wrapper ensures the Profile component works correctly within the SDK navigation context.
|
|
27
|
+
* The original Profile component expects to be within a MainTabNavigator, but in the SDK
|
|
28
|
+
* it needs to navigate differently.
|
|
29
|
+
*/
|
|
30
|
+
const SDKProfile: React.FC = () => {
|
|
31
|
+
const navigation = useNavigation();
|
|
32
|
+
|
|
33
|
+
// Create a custom navigation prop that handles SDK-specific navigation
|
|
34
|
+
const sdkNavigation = React.useMemo(() => ({
|
|
35
|
+
...navigation,
|
|
36
|
+
navigate: (routeName: string, params?: any) => {
|
|
37
|
+
console.log('🔍 SDK Profile Navigation:', { routeName, params });
|
|
38
|
+
|
|
39
|
+
// Handle DashboardTab navigation - in SDK, these screens are hidden tabs, not nested in DashboardStack
|
|
40
|
+
if (routeName === 'DashboardTab') {
|
|
41
|
+
const targetScreen = params?.screen;
|
|
42
|
+
const targetParams = params?.params;
|
|
43
|
+
|
|
44
|
+
console.log('🚀 SDK redirecting DashboardTab to:', targetScreen);
|
|
45
|
+
|
|
46
|
+
if (targetScreen && HIDDEN_TAB_SCREENS.includes(targetScreen)) {
|
|
47
|
+
// Navigate to hidden tab screen directly (they're at tab level in SDK)
|
|
48
|
+
console.log('🚀 SDK navigating to hidden tab screen:', targetScreen);
|
|
49
|
+
navigation.navigate(targetScreen as never, targetParams as never);
|
|
50
|
+
} else if (targetScreen === 'Dashboard') {
|
|
51
|
+
// Navigate to DashboardTab which contains Dashboard
|
|
52
|
+
console.log('🚀 SDK navigating to DashboardTab');
|
|
53
|
+
navigation.navigate('DashboardTab' as never, { screen: 'Dashboard' } as never);
|
|
54
|
+
} else if (targetScreen) {
|
|
55
|
+
// Try direct navigation for any other screen
|
|
56
|
+
console.log('🚀 SDK direct navigation to:', targetScreen);
|
|
57
|
+
navigation.navigate(targetScreen as never, targetParams as never);
|
|
58
|
+
} else {
|
|
59
|
+
console.warn('⚠️ No target screen specified for DashboardTab navigation');
|
|
60
|
+
}
|
|
61
|
+
} else {
|
|
62
|
+
// Direct navigation for other routes
|
|
63
|
+
console.log('🚀 SDK direct navigation to:', routeName);
|
|
64
|
+
navigation.navigate(routeName as never, params as never);
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
reset: (options: any) => {
|
|
68
|
+
console.log('🔄 SDK navigation reset:', options);
|
|
69
|
+
navigation.reset(options);
|
|
70
|
+
}
|
|
71
|
+
}), [navigation]);
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
<View style={styles.container}>
|
|
75
|
+
<Profile navigation={sdkNavigation} />
|
|
76
|
+
</View>
|
|
77
|
+
);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const styles = StyleSheet.create({
|
|
81
|
+
container: {
|
|
82
|
+
flex: 1,
|
|
83
|
+
backgroundColor: 'white',
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
export default SDKProfile;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SDK Profile Wrapper
|
|
3
|
+
*
|
|
4
|
+
* With the new Root Stack + Tabs architecture, navigation is simple:
|
|
5
|
+
* - All detail screens are in the root stack
|
|
6
|
+
* - Just navigate directly to screen names
|
|
7
|
+
* - goBack() works correctly because screens are in a stack
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import React from 'react';
|
|
11
|
+
import { useNavigation } from '@react-navigation/native';
|
|
12
|
+
import { Profile } from '../screens';
|
|
13
|
+
|
|
14
|
+
const SDKProfileWrapper: React.FC = () => {
|
|
15
|
+
const navigation = useNavigation();
|
|
16
|
+
|
|
17
|
+
// Create SDK-aware navigation prop - simplified for new architecture
|
|
18
|
+
const sdkNavigation = React.useMemo(() => {
|
|
19
|
+
return {
|
|
20
|
+
...navigation,
|
|
21
|
+
navigate: (routeName: string, params?: any) => {
|
|
22
|
+
console.log('🔍 SDK Profile Navigation:', { routeName, params });
|
|
23
|
+
|
|
24
|
+
// Handle legacy DashboardTab navigation pattern (for backwards compatibility)
|
|
25
|
+
if (routeName === 'DashboardTab') {
|
|
26
|
+
const targetScreen = params?.screen;
|
|
27
|
+
const targetParams = params?.params;
|
|
28
|
+
|
|
29
|
+
if (targetScreen === 'Dashboard') {
|
|
30
|
+
// Go to Dashboard tab
|
|
31
|
+
(navigation as any).navigate('Tabs', { screen: 'DashboardTab' });
|
|
32
|
+
} else if (targetScreen) {
|
|
33
|
+
// Navigate directly to the stack screen
|
|
34
|
+
(navigation as any).navigate(targetScreen, targetParams);
|
|
35
|
+
}
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Direct navigation for all other routes
|
|
40
|
+
(navigation as any).navigate(routeName, params);
|
|
41
|
+
},
|
|
42
|
+
reset: (options: any) => {
|
|
43
|
+
navigation.reset(options);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}, [navigation]);
|
|
47
|
+
|
|
48
|
+
return <Profile navigation={sdkNavigation} />;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export default SDKProfileWrapper;
|
package/src/constants.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import React, { createContext, useContext, ReactNode, useState, useCallback } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* SDK Context
|
|
5
|
+
*
|
|
6
|
+
* This context provides information about whether we're running in the SDK context
|
|
7
|
+
* and allows components to adapt their behavior accordingly.
|
|
8
|
+
*
|
|
9
|
+
* It also tracks deep link entry state so back navigation can behave consistently:
|
|
10
|
+
* - When app is opened via deep link, back navigation should exit to host app
|
|
11
|
+
* - When app is opened normally, back navigation follows standard behavior
|
|
12
|
+
*/
|
|
13
|
+
interface SDKContextType {
|
|
14
|
+
isSDK: boolean;
|
|
15
|
+
sdkNavigation?: any;
|
|
16
|
+
/** Whether the app was opened via a deep link */
|
|
17
|
+
isDeepLinkEntry: boolean;
|
|
18
|
+
/** The screen that was deep linked to */
|
|
19
|
+
deepLinkTarget?: string;
|
|
20
|
+
/** Set the deep link entry state */
|
|
21
|
+
setDeepLinkEntry: (isDeepLink: boolean, target?: string) => void;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const SDKContext = createContext<SDKContextType>({
|
|
25
|
+
isSDK: false,
|
|
26
|
+
isDeepLinkEntry: false,
|
|
27
|
+
deepLinkTarget: undefined,
|
|
28
|
+
setDeepLinkEntry: () => {},
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
export const useSDKContext = () => useContext(SDKContext);
|
|
32
|
+
|
|
33
|
+
interface SDKProviderProps {
|
|
34
|
+
children: ReactNode;
|
|
35
|
+
isSDK?: boolean;
|
|
36
|
+
sdkNavigation?: any;
|
|
37
|
+
initialDeepLinkEntry?: boolean;
|
|
38
|
+
initialDeepLinkTarget?: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const SDKProvider: React.FC<SDKProviderProps> = ({
|
|
42
|
+
children,
|
|
43
|
+
isSDK = false,
|
|
44
|
+
sdkNavigation,
|
|
45
|
+
initialDeepLinkEntry = false,
|
|
46
|
+
initialDeepLinkTarget,
|
|
47
|
+
}) => {
|
|
48
|
+
const [isDeepLinkEntry, setIsDeepLinkEntry] = useState(initialDeepLinkEntry);
|
|
49
|
+
const [deepLinkTarget, setDeepLinkTarget] = useState<string | undefined>(initialDeepLinkTarget);
|
|
50
|
+
|
|
51
|
+
const setDeepLinkEntry = useCallback((isDeepLink: boolean, target?: string) => {
|
|
52
|
+
console.log('🔗 SDKContext: setDeepLinkEntry', { isDeepLink, target });
|
|
53
|
+
setIsDeepLinkEntry(isDeepLink);
|
|
54
|
+
setDeepLinkTarget(target);
|
|
55
|
+
}, []);
|
|
56
|
+
|
|
57
|
+
const contextValue: SDKContextType = {
|
|
58
|
+
isSDK,
|
|
59
|
+
sdkNavigation,
|
|
60
|
+
isDeepLinkEntry,
|
|
61
|
+
deepLinkTarget,
|
|
62
|
+
setDeepLinkEntry,
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<SDKContext.Provider value={contextValue}>
|
|
67
|
+
{children}
|
|
68
|
+
</SDKContext.Provider>
|
|
69
|
+
);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export default SDKContext;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { useCallback } from 'react';
|
|
2
|
+
import { NativeModules } from 'react-native';
|
|
3
|
+
import { useSDKContext } from '../contexts/SDKContext';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Hook that provides deep-link-aware back navigation for SDK screens.
|
|
7
|
+
*
|
|
8
|
+
* When the app is opened via deep link, pressing back should exit to the host app
|
|
9
|
+
* instead of navigating to Home/Dashboard.
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* ```tsx
|
|
13
|
+
* const { getDeepLinkExitHandler } = useSDKBackNavigation();
|
|
14
|
+
*
|
|
15
|
+
* const handleGoBack = () =>
|
|
16
|
+
* handleCustomGoBack(navigation, route, {
|
|
17
|
+
* map: { ... },
|
|
18
|
+
* fallback: ROUTES.DASHBOARD,
|
|
19
|
+
* onDeepLinkExit: getDeepLinkExitHandler(),
|
|
20
|
+
* });
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export const useSDKBackNavigation = () => {
|
|
24
|
+
const { isDeepLinkEntry } = useSDKContext();
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Returns a handler that exits to the host app if this is a deep link entry.
|
|
28
|
+
* Returns undefined if not a deep link entry (so normal navigation continues).
|
|
29
|
+
*/
|
|
30
|
+
const getDeepLinkExitHandler = useCallback(() => {
|
|
31
|
+
if (!isDeepLinkEntry) {
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return () => {
|
|
36
|
+
console.log('🚀 Deep link entry detected - exiting to host app');
|
|
37
|
+
if (NativeModules.PropelSDKBridge?.closeSDK) {
|
|
38
|
+
NativeModules.PropelSDKBridge.closeSDK();
|
|
39
|
+
}
|
|
40
|
+
return true;
|
|
41
|
+
};
|
|
42
|
+
}, [isDeepLinkEntry]);
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Directly exits to host app. Use when you know you want to exit.
|
|
46
|
+
*/
|
|
47
|
+
const exitToHostApp = useCallback(() => {
|
|
48
|
+
console.log('🚀 Exiting to host app');
|
|
49
|
+
if (NativeModules.PropelSDKBridge?.closeSDK) {
|
|
50
|
+
NativeModules.PropelSDKBridge.closeSDK();
|
|
51
|
+
}
|
|
52
|
+
}, []);
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
isDeepLinkEntry,
|
|
56
|
+
getDeepLinkExitHandler,
|
|
57
|
+
exitToHostApp,
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export default useSDKBackNavigation;
|