@polls-platform/react-native
Version:
React Native SDK for Polls Platform
311 lines (247 loc) • 8.68 kB
JavaScript
"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