@told.club/sdk-rn
Version:
Told React Native SDK
163 lines (159 loc) • 5.99 kB
JavaScript
import * as React from 'react';
import { Animated, StyleSheet, useWindowDimensions, KeyboardAvoidingView, Modal, Linking } from 'react-native';
import { WebView } from 'react-native-webview';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import ToldContext from './ToldContext';
import { setReplied, setSeen } from './ToldStorage';
import { Platform } from 'react-native';
import { convertToJSONString } from './utils/hiddenFields';
const transferMessagesToRN = `
window.addEventListener('message', (e) => {
window.ReactNativeWebView.postMessage(JSON.stringify(e.data));
});
window.console.log = (msg, other = '') => window.ReactNativeWebView.postMessage(JSON.stringify({ type: 'LOG', msg: msg + other }));
`;
export default function ToldWidget({
surveyId,
sourceID,
params,
widgetUrl
}) {
const insets = useSafeAreaInsets();
const {
height
} = useWindowDimensions();
const webviewRef = React.useRef(null);
const {
close,
hiddenFields
} = React.useContext(ToldContext);
const [currentHeight, setCurrentHeight] = React.useState(500);
const [urlModalLink, setUrlModalLink] = React.useState(null);
// Animated values
const animatedHeight = React.useRef(new Animated.Value(500)).current;
const animatedOpacity = React.useRef(new Animated.Value(0)).current;
React.useEffect(() => {
// When the widget is mounted, we set the survey as seen
if (surveyId) setSeen(surveyId);
}, [surveyId]);
// METHOD: Animate the webview height
const updateWebviewHeight = React.useCallback((newHeight, animated) => {
Animated.timing(animatedHeight, {
toValue: newHeight,
duration: animated ? 300 : 0,
useNativeDriver: false
}).start();
}, [animatedHeight]);
// EVENT: Message received from the webview
const onMessageReceived = React.useCallback(event => {
var _webviewRef$current, _data$value;
const data = JSON.parse(event.nativeEvent.data);
const type = data === null || data === void 0 ? void 0 : data.type;
switch (type) {
case 'LOG':
if (params.includes('debug')) console.log(`[LOG] ${data.msg}`);
return;
case 'IS_LOADED':
const formattedHiddenFields = convertToJSONString(hiddenFields);
(_webviewRef$current = webviewRef.current) === null || _webviewRef$current === void 0 || _webviewRef$current.injectJavaScript(`
window.postMessage({type: 'OS_TYPE', value: '${Platform.OS.toUpperCase()}'}, '*');
window.postMessage({type: 'DEVICE_TYPE', value: 'phone'}, '*');
window.postMessage({type: 'SAFE_AREA', value: '${insets.bottom}'}, '*');
window.postMessage({type: 'UPDATE_HIDDENFIELDS', value: '${formattedHiddenFields}'}, '*');
`);
break;
case 'HEIGHT_CHANGE':
const value = data === null || data === void 0 ? void 0 : data.value;
const newHeight = value > height ? height - insets.top : value;
updateWebviewHeight(newHeight, /*currentHeight > newHeight*/false);
if (currentHeight === 500) {
Animated.timing(animatedOpacity, {
toValue: 1,
duration: 300,
useNativeDriver: false
}).start();
}
setCurrentHeight(newHeight);
break;
case 'LAUNCH_CALENDAR':
const url = data === null || data === void 0 || (_data$value = data.value) === null || _data$value === void 0 ? void 0 : _data$value.iframeUrl;
// if (url) Linking.openURL(url);
if (url) setUrlModalLink(url);
break;
case 'ADD_COOKIE':
const reply = data === null || data === void 0 ? void 0 : data.reply;
if (reply) setReplied(surveyId);
break;
case 'CLOSE':
Animated.timing(animatedOpacity, {
toValue: 0,
duration: 125,
useNativeDriver: false
}).start(() => close());
break;
default:
break;
}
if (params.includes('debug')) console.log(`[MSG RECEIVED] ${event.nativeEvent.data}`);
}, [params, insets, height, updateWebviewHeight, currentHeight, surveyId, animatedOpacity, close, hiddenFields]);
// EVENT: Open a new window
const onOpenWindow = React.useCallback(event => {
var _event$nativeEvent;
Linking.openURL(event === null || event === void 0 || (_event$nativeEvent = event.nativeEvent) === null || _event$nativeEvent === void 0 ? void 0 : _event$nativeEvent.targetUrl);
}, []);
const onLinkModalClose = React.useCallback(() => {
setUrlModalLink(null);
}, []);
return /*#__PURE__*/React.createElement(Modal, {
transparent: true,
visible: true
}, /*#__PURE__*/React.createElement(KeyboardAvoidingView, {
behavior: "padding",
style: styles.container
}, /*#__PURE__*/React.createElement(Animated.View, {
style: [styles.animatedContainer, {
height: animatedHeight,
opacity: animatedOpacity
}]
}, /*#__PURE__*/React.createElement(WebView, {
ref: webviewRef,
source: {
uri: `${widgetUrl}/?id=${surveyId}&toldProjectID=${sourceID}`
},
bounces: false,
containerStyle: styles.webViewContainer,
style: styles.webView,
injectedJavaScript: transferMessagesToRN,
onMessage: onMessageReceived,
onOpenWindow: onOpenWindow,
scrollEnabled: false
}))), /*#__PURE__*/React.createElement(Modal, {
animationType: "slide",
presentationStyle: "pageSheet",
visible: urlModalLink !== null,
onRequestClose: onLinkModalClose
}, urlModalLink && /*#__PURE__*/React.createElement(WebView, {
source: {
uri: urlModalLink
},
containerStyle: styles.webViewContainer,
onOpenWindow: onOpenWindow,
scrollEnabled: true
})));
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column-reverse'
},
animatedContainer: {
flex: 0
},
webViewContainer: {
flex: 1
},
webView: {
backgroundColor: 'transparent'
}
});
//# sourceMappingURL=ToldWidget.js.map