mychips-react-sdk
Version:
MyChips Offerwall
235 lines (224 loc) • 8.03 kB
JavaScript
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