UNPKG

mychips-react-sdk

Version:
235 lines (224 loc) 8.03 kB
import * as React from 'react'; import { WebView } from 'react-native-webview'; import { Linking, BackHandler, View, Text, StyleSheet, ActivityIndicator } from 'react-native'; import UriBuilderService from '../services/UriBuilderService'; import { UserService } from '../services/UserService'; import { RateLimitService } from '../services/RatelimitService'; import { getDefaultNetInfoProvider } from '../services/ConnectivityService'; // Props and ref handle types exposed for external use (minimal change, fully backward compatible) // to allow external access via ref export const MCOfferwallView = /*#__PURE__*/React.forwardRef(function MCOfferwallView({ adunitId, connectivityProvider // external connectivity provider can be injected }, ref) { //about:blank url will break compilation on ios const [currentUrl, setCurrentUrl] = React.useState(''); // State for the current URL const [isConnected, setIsConnected] = React.useState(true); const [isLoading, setIsLoading] = React.useState(true); const mychipsDomain = 'mychips.io'; const webViewRef = React.useRef(null); const currentUrlRef = React.useRef(currentUrl); // Ref to keep track of the current URL const getUserData = async () => { const userService = new UserService(); const userId = await userService.getOrCreateId(); const gaid = await userService.getGaid(); const idfa = await userService.getIdfa(); const age = await userService.getAge(); const gender = await userService.getGender(); const totalVirtualCurrency = await userService.getCurrentTotalCurrency(); const aff_sub1 = await userService.getAffSub1(); const aff_sub2 = await userService.getAffSub2(); const aff_sub3 = await userService.getAffSub3(); const aff_sub4 = await userService.getAffSub4(); const aff_sub5 = await userService.getAffSub5(); return { userId, gaid, idfa, age, gender, totalVirtualCurrency, aff_sub1, aff_sub2, aff_sub3, aff_sub4, aff_sub5 }; }; const buildUrl = async () => { const userData = await getUserData(); const uriBuilderService = new UriBuilderService(); return uriBuilderService.buildOfferwallUrl(adunitId, userData.userId, userData.gaid, userData.idfa, userData.gender, userData.age, userData.totalVirtualCurrency, userData.aff_sub1, userData.aff_sub2, userData.aff_sub3, userData.aff_sub4, userData.aff_sub5); }; const fetchUserDataAndBuildUrl = async () => { try { const url = await buildUrl(); setCurrentUrl(url); } catch (error) { console.error('Failed to build offerwall URL', error); } }; ///get the current navigation url and keep it updated const onNavigationStateChange = navState => { const { url } = navState; if (url !== currentUrlRef.current) { setCurrentUrl(url); currentUrlRef.current = url; console.log('onNavigationStateChange:' + url); } }; ///handle logic for specific link const onShouldStartLoadWithRequest = request => { const { url } = request; console.log("onShouldStartLoadWithRequest:" + url); if (url.includes('blank') || url.includes('file:')) { return false; } if (url.includes('/redirect')) { Linking.openURL(url).catch(err => console.error("Couldn't load page", err)); return false; // Prevent the WebView from loading the URL } if (url.includes('mychips://')) { return false; } return true; // Allow the WebView to load the URL }; const onLoadStart = () => { //console.log("WebView Load Started"); }; const onLoad = () => { //console.log("WebView Loaded"); }; const onLoadEnd = () => { if (currentUrl == '' || currentUrl == 'about:blank') { fetchUserDataAndBuildUrl(); console.log("onLoadEnd: fetchUserDataAndBuildUrl"); } console.log("WebView Load Ended"); if (isLoading && currentUrl.includes(mychipsDomain)) { setIsLoading(false); } }; const onError = error => { console.error("WebView Error: ", error); }; //handle navigation logic const onBackPress = () => { const url = currentUrlRef.current; // Use if (url.includes('page=home') || !url.includes('page=')) { return false; // Allow default back button behavior if URL contains 'page=home' } else { var _webViewRef$current; (_webViewRef$current = webViewRef.current) === null || _webViewRef$current === void 0 || _webViewRef$current.goBack(); return true; // Prevent default back button behavior } }; // Expose methods via ref (same as hardware back button, no behavior change) React.useImperativeHandle(ref, () => ({ requestBack: onBackPress }), [onBackPress]); React.useEffect(() => { RateLimitService.enableRequest(); setTimeout(() => { if (currentUrlRef.current == 'about:blank' || currentUrlRef.current == '') { fetchUserDataAndBuildUrl(); console.log("01"); } }, 1000); // Delay to ensure WebView is ready setTimeout(() => { if (isLoading) setIsLoading(false); }, 5000); /** * Connectivity strategy (explicit & backward compatible) * 1) Use externally injected connectivityProvider if provided. * 2) Otherwise, try dynamic NetInfo (if installed in the host app). * 3) If neither is available, THROW an error (publisher must choose one). */ const provider = connectivityProvider ?? getDefaultNetInfoProvider(); let unsubscribe; // explicit error if no provider at all if (!provider) { throw new Error('[MyChips SDK] No connectivity provider available. Please either install "@react-native-community/netinfo" or provide a custom connectivityProvider.'); } (async () => { try { if (provider.getCurrentStatus) { const s = await provider.getCurrentStatus(); if (typeof s === 'boolean') setIsConnected(s); } } catch { // ignore one-off fetch errors; live subscription below will update the state } })(); unsubscribe = provider.subscribe(online => { setIsConnected(Boolean(online)); }); const backHandlerSubscription = BackHandler.addEventListener('hardwareBackPress', onBackPress); return () => { backHandlerSubscription.remove(); if (typeof unsubscribe === 'function') unsubscribe(); }; }, []); return /*#__PURE__*/React.createElement(View, { style: { flex: 1 } }, /*#__PURE__*/React.createElement(WebView // key={currentUrl} // Use URL as key to force re-render , { ref: webViewRef, source: { uri: currentUrl }, onNavigationStateChange: onNavigationStateChange, onShouldStartLoadWithRequest: onShouldStartLoadWithRequest, onLoadStart: onLoadStart, onLoad: onLoad, onLoadEnd: onLoadEnd, onError: onError }), isLoading && /*#__PURE__*/React.createElement(View, { style: styles.loaderContainer }, /*#__PURE__*/React.createElement(ActivityIndicator, { size: "large", style: styles.loader })), !isConnected && /*#__PURE__*/React.createElement(View, { style: styles.offlineContainer }, /*#__PURE__*/React.createElement(Text, { style: styles.offlineText }, "No Internet Connection"))); }); const styles = StyleSheet.create({ offlineContainer: { position: 'absolute', top: 0, left: 0, right: 0, height: 30, justifyContent: 'center', alignItems: 'center', backgroundColor: '#b52424', zIndex: 1 // Ensure the offline message is on top }, offlineText: { color: '#fff' }, loaderContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', position: 'absolute', width: '100%', height: '100%', zIndex: 1, // Ensures loader is above other content backgroundColor: 'rgba(255, 255, 255, 0.8)' // Optional: Adds a semi-transparent background }, loader: { // Additional styles if needed } }); //# sourceMappingURL=MCOfferwallView.js.map