UNPKG

@polls-platform/react-native

Version:

React Native SDK for Polls Platform

311 lines (247 loc) 8.68 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PollView = void 0; var _react = _interopRequireDefault(require("react")); var _reactNative = require("react-native"); var _internal = require("@polls-platform/core/built/internal"); var _internal2 = require("../../internal"); var _reactNativeWebview = require("react-native-webview"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } // react // @polls-platform/core // @polls-platform/react-native // third party dependencies /** * The `PollView` component is used for both creating and opening polls. * For more information, go to https://docs.pollsplatform.com/react-native. * Before navigating the user to this screen, you must have a poll URL. * You can create a poll using the `createPoll` and `createPollAsync` functions * which will respond with a URL that can be passed here. * Or if you already have the URL of an existing poll you can pass it * @category 3. PollView */ const PollView = _ref => { let { style, pollSource, openPollFlow, theme = _internal.Theme.light, didPressViewDetails, didReceiveAnalyticsEvent } = _ref; // state const [isLoading, setIsLoading] = _react.default.useState(true); const [showWebView, setShowWebView] = _react.default.useState(false); const [loadingTitleOverride, setLoadingTitleOverride] = _react.default.useState(null); const lastLoadTime = _react.default.useRef(null); const webViewRef = _react.default.useRef(null); const themeProperties = (0, _internal.getThemeProperties)(theme); // poll url const pollUrl = _react.default.useMemo(() => { if ((0, _internal.isPollSourcePollId)(pollSource)) { // found poll id, construct url const pollId = pollSource; return (0, _internal.constructPollUrl)({ pollId: pollId, flow: openPollFlow // pollState?: PollState; // themeName?: string; // themeObject?: any; }); } else { // found poll url return pollSource; // Poll Source = Poll URL } }, [pollSource, openPollFlow]); // handle poll url changing _react.default.useEffect(() => { lastLoadTime.current = Date.now(); setIsLoading(true); }, [pollUrl]); // manage loading states const loadingOpacity = _react.default.useRef(new _reactNative.Animated.Value(0)).current; // initial const webViewOpacity = _react.default.useRef(new _reactNative.Animated.Value(0)).current; // initial // show/hide loading _react.default.useEffect(() => { _reactNative.Animated.timing(loadingOpacity, { toValue: isLoading ? 1 : 0, duration: _internal.ANIMATION_DURATION, useNativeDriver: true }).start(); if (isLoading) { setShowWebView(false); } else { setTimeout(() => { setShowWebView(true); }, _internal.ANIMATION_DURATION); } // we do not want to run this if the animation ref changes // eslint-disable-next-line react-hooks/exhaustive-deps }, [isLoading]); // show/hide web view _react.default.useEffect(() => { _reactNative.Animated.timing(webViewOpacity, { toValue: showWebView ? 1 : 0, duration: _internal.ANIMATION_DURATION, useNativeDriver: true }).start(); if (showWebView) { setTimeout(() => { setLoadingTitleOverride(null); }, _internal.ANIMATION_DURATION); } // we do not want to run this if the animation ref changes // eslint-disable-next-line react-hooks/exhaustive-deps }, [showWebView]); // reload when foregrounding after 3m _react.default.useEffect(() => { const subscription = _reactNative.AppState.addEventListener('change', nextAppState => { const activeState = 'active'; const secondsSinceLastLoad = Math.round((Date.now() - (lastLoadTime.current || 0)) / 1000); if (nextAppState === activeState && secondsSinceLastLoad > _internal.REFRESH_POLL_AGE_SECONDS) { var _webViewRef$current; setLoadingTitleOverride('Reloading Poll...'); // TODO: translation setShowWebView(false); setIsLoading(true); lastLoadTime.current = Date.now(); (_webViewRef$current = webViewRef.current) === null || _webViewRef$current === void 0 ? void 0 : _webViewRef$current.reload(); } }); return () => { subscription.remove(); }; }, []); // external callbacks const handleDidPressViewDetails = option => { didPressViewDetails === null || didPressViewDetails === void 0 ? void 0 : didPressViewDetails(option); }; const handleDidReceiveAnalyticsEvent = event => { didReceiveAnalyticsEvent === null || didReceiveAnalyticsEvent === void 0 ? void 0 : didReceiveAnalyticsEvent(event); }; // internal callbacks const handleOnLoadEnd = () => { setTimeout(() => { setIsLoading(false); }, 250); }; const handleOnMessage = event => { const trackInvalidMessage = () => {// console.log('❌ invalid message', event.nativeEvent.data); }; // guards const dataString = event.nativeEvent.data; if (!dataString) { trackInvalidMessage(); return; } const data = JSON.parse(dataString); if (!data) { trackInvalidMessage(); return; } const parseResult = _internal.EmbeddedMessage.safeParse(data); if (!parseResult.success) { trackInvalidMessage(); return; } switch (parseResult.data.event) { case _internal.EmbeddedMessageEvent.VIEW_OPTION_DETAILS: { handleDidPressViewDetails(parseResult.data.payload.option); break; } case _internal.EmbeddedMessageEvent.ANALYTICS_EVENT: { handleDidReceiveAnalyticsEvent(parseResult.data.payload); break; } default: { break; } } }; // render const embeddedPollUrl = (0, _internal.setPollUrlParams)(pollUrl, { embeddedState: (0, _internal2.getEmbeddedState)() }); const subdomain = (0, _internal.getThemeFromPollUrl)(embeddedPollUrl) ?? (0, _internal.getConfig)().domainConfig.subdomain; const loadingLogoImageUrl = `https://polls-platform.s3.amazonaws.com/customer-assets/${subdomain}/mobileLoadingLogo.png`; let loadingTitle; if (loadingTitleOverride) { loadingTitle = loadingTitleOverride; } else { switch (openPollFlow) { case _internal.OpenPollFlow.createPoll: { loadingTitle = 'Creating Poll...'; // TODO: translation break; } default: case _internal.OpenPollFlow.openPoll: { loadingTitle = 'Loading Poll...'; // TODO: translation break; } } } const styles = createStyles({ themeProperties }); return /*#__PURE__*/_react.default.createElement(_reactNative.View, { style: [styles.container, style] }, /*#__PURE__*/_react.default.createElement(_reactNative.View, { style: styles.content }, /*#__PURE__*/_react.default.createElement(_reactNative.Animated.View, { style: { ...styles.webViewContainer, opacity: webViewOpacity } }, /*#__PURE__*/_react.default.createElement(_reactNativeWebview.WebView, { style: styles.webView, source: { uri: embeddedPollUrl }, ref: webViewRef, onLoadEnd: handleOnLoadEnd, originWhitelist: _internal.WEBVIEW_ORIGIN_WHITELIST, onMessage: handleOnMessage })), !showWebView && /*#__PURE__*/_react.default.createElement(_reactNative.Animated.View, { style: { ...styles.loadingContainer, opacity: loadingOpacity } }, /*#__PURE__*/_react.default.createElement(_internal2.LoadingView, { isVisible: isLoading, title: loadingTitle, imageUrl: loadingLogoImageUrl, theme: theme })))); }; exports.PollView = PollView; const createStyles = styleProps => { const { themeProperties } = styleProps; const { colors: themeColors } = themeProperties; const styles = _reactNative.StyleSheet.create({ container: { width: '100%', height: '100%', backgroundColor: themeColors.backgroundColor }, content: { width: '100%', height: '100%', backgroundColor: themeColors.backgroundColor }, loadingContainer: { position: 'absolute', width: '100%', height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'flex-start', backgroundColor: themeColors.backgroundColor }, webViewContainer: { width: '100%', height: '100%' }, webView: { width: '100%', height: '100%' } }); return styles; }; //# sourceMappingURL=index.js.map