UNPKG

@told.club/sdk-rn

Version:
216 lines (206 loc) 11.2 kB
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } import * as React from 'react'; import { Platform } from 'react-native'; import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client'; import { SafeAreaProvider } from 'react-native-safe-area-context'; import { getBundleId } from 'react-native-device-info'; import ToldContext from './ToldContext'; import { GET_EVERY_SURVEY_AVAILABLE_TO_BE_TRIGGERED, CHECK_CAN_USE_SURVEY } from './utils/graphql'; import NavigationListener from './NavigationListener'; import { isCustomEventTriggerConditionTrue, isScreenTriggerConditionTrue } from './utils/triggerConditions'; import ToldWidget from './ToldWidget'; import { isReplied, isSeen, loadSurveyData } from './ToldStorage'; const SERVER_API_URL = 'https://api.told.club'; const WIDGET_URL = 'https://widget.told.club'; export default function ToldProvider({ sourceID, appVersion, defaultParams, defaultHiddenFields, language, servers, children }) { const [loaded, setLoaded] = React.useState(false); const [triggers, setTriggers] = React.useState([]); const [currentScreenName, setCurrentScreenName] = React.useState(''); const [currentSurvey, setCurrentSurvey] = React.useState(null); const [hiddenFields, setHiddenFields] = React.useState(defaultHiddenFields || {}); const [lastLoadVars, setLastLoadVars] = React.useState(null); const { apiUrl, widgetUrl } = React.useMemo(() => ({ apiUrl: (servers === null || servers === void 0 ? void 0 : servers.apiUrl) || SERVER_API_URL, widgetUrl: (servers === null || servers === void 0 ? void 0 : servers.widgetUrl) || WIDGET_URL }), [servers]); const client = React.useMemo(() => new ApolloClient({ uri: `${apiUrl}/graphql`, cache: new InMemoryCache() }), [apiUrl]); const timeoutsRef = React.useRef([]); // INIT: Load triggers React.useEffect(() => { const loadVars = { folderID: sourceID, type: 'IN_APP_MOBILE', os: Platform.OS.toUpperCase(), mobileApp: getBundleId(), language: language || 'fr', version: appVersion || '1.0.0', listReplied: [], preview: defaultParams !== null && defaultParams !== void 0 && defaultParams.includes('preview') ? true : false }; if (lastLoadVars && JSON.stringify(lastLoadVars) === JSON.stringify(loadVars)) return; loadSurveyData().then(() => { client.query({ query: GET_EVERY_SURVEY_AVAILABLE_TO_BE_TRIGGERED, variables: loadVars }).then(data => { const { getEverySurveyAvailableToBeTriggered } = data.data; if (defaultParams !== null && defaultParams !== void 0 && defaultParams.includes('debug')) console.log(`Initializing ${getEverySurveyAvailableToBeTriggered === null || getEverySurveyAvailableToBeTriggered === void 0 ? void 0 : getEverySurveyAvailableToBeTriggered.length} survey triggers.`); setLastLoadVars(loadVars); setTriggers(getEverySurveyAvailableToBeTriggered); setLoaded(true); }).catch(error => { console.error(`Told SDK not loaded correctly : ${(error === null || error === void 0 ? void 0 : error.message) ?? '(unknown)'}`); }); }); }, [lastLoadVars, appVersion, defaultParams, language, sourceID, client]); // Method: Start survey const start = React.useCallback(surveyId => { if (defaultParams !== null && defaultParams !== void 0 && defaultParams.includes('seeItOnlyOnce') && isSeen(surveyId)) return; client.query({ query: CHECK_CAN_USE_SURVEY, variables: { surveyID: surveyId, preview: defaultParams !== null && defaultParams !== void 0 && defaultParams.includes('preview') ? true : false, os: Platform.OS.toUpperCase(), mobileApp: getBundleId() } }).then(data => { var _data$data; const canUse = (data === null || data === void 0 || (_data$data = data.data) === null || _data$data === void 0 || (_data$data = _data$data.checkIfCanUseWidgetWithSurvey) === null || _data$data === void 0 ? void 0 : _data$data.canUse) ?? false; if (canUse) { if (defaultParams !== null && defaultParams !== void 0 && defaultParams.includes('debug')) console.log(`Starting survey: ${surveyId}`); // Start survey setCurrentSurvey({ surveyId, sourceID, params: defaultParams || [] }); } else { console.log(`Cannot display survey ${surveyId}. Check if survey is correctly configured and enabled on website. Or already seen ?`); } }).catch(error => { console.error(`Told SDK Error while checking if can use widget : ${(error === null || error === void 0 ? void 0 : error.message) ?? '(unknown)'}`); }); }, [client, defaultParams, sourceID]); // EVENT: On screen change React.useEffect(() => { if (!currentScreenName) return; if (!loaded) return; if (defaultParams !== null && defaultParams !== void 0 && defaultParams.includes('debug')) console.log(`Screen changed to ${currentScreenName}`); checkScreenTriggers(currentScreenName); }, [currentScreenName, loaded, defaultParams]); // eslint-disable-line react-hooks/exhaustive-deps const checkScreenTriggers = React.useCallback((screenName, enableDelayCheck = true) => { const screenTriggers = (triggers === null || triggers === void 0 ? void 0 : triggers.filter(el => (el === null || el === void 0 ? void 0 : el.__typename) === 'SurveyTriggerScreen')) || []; // Clear previously set timeouts for (const timeoutId of timeoutsRef.current) clearTimeout(timeoutId); for (const trigger of screenTriggers) { var _trigger$whenData, _trigger$whenData2; if ((_trigger$whenData = trigger.whenData) !== null && _trigger$whenData !== void 0 && _trigger$whenData.seeItOnlyOnce && isSeen(trigger.survey)) { if (defaultParams !== null && defaultParams !== void 0 && defaultParams.includes('debug')) console.log(`Survey ${trigger.survey} already seen, not triggering again.`); continue; } if ((_trigger$whenData2 = trigger.whenData) !== null && _trigger$whenData2 !== void 0 && _trigger$whenData2.replyOnlyOnce && isReplied(trigger.survey)) { if (defaultParams !== null && defaultParams !== void 0 && defaultParams.includes('debug')) console.log(`Survey ${trigger.survey} already replied, not triggering again.`); continue; } if ((trigger.onAllScreen ?? false) || isScreenTriggerConditionTrue(trigger.condition, screenName)) { var _trigger$delay, _trigger$delay2; const delayEnabled = enableDelayCheck ? ((_trigger$delay = trigger.delay) === null || _trigger$delay === void 0 ? void 0 : _trigger$delay.active) ?? false : false; const delayValue = delayEnabled ? ((_trigger$delay2 = trigger.delay) === null || _trigger$delay2 === void 0 ? void 0 : _trigger$delay2.value) ?? 0 : 0; if (delayEnabled) { const timeoutId = setTimeout(() => { // Because of js closure, we're using a function to get the current screen name setCurrentScreenName(_screenName => { checkScreenTriggers(_screenName, false); return _screenName; }); }, delayValue * 1000); timeoutsRef.current.push(timeoutId); } else { if (defaultParams !== null && defaultParams !== void 0 && defaultParams.includes('debug')) console.log(`Triggered survey: ${trigger.survey} on screen ${screenName}`); start(trigger.survey); // Start survey } } } }, [start, triggers, defaultParams]); const onScreenChange = React.useCallback(screenName => { setCurrentScreenName(screenName); }, []); // EVENT: On custom event const checkCustomEvent = React.useCallback((eventName, eventProperties) => { var _customEventTrigger$w, _customEventTrigger$w2; const customEventTrigger = triggers === null || triggers === void 0 ? void 0 : triggers.find(el => (el === null || el === void 0 ? void 0 : el.__typename) === 'SurveyTriggerCustomEvent' && el.eventName === eventName); if (!customEventTrigger) return; // Check whenData conditions if ((_customEventTrigger$w = customEventTrigger.whenData) !== null && _customEventTrigger$w !== void 0 && _customEventTrigger$w.seeItOnlyOnce && isSeen(customEventTrigger.survey)) { if (defaultParams !== null && defaultParams !== void 0 && defaultParams.includes('debug')) console.log(`Survey ${customEventTrigger.survey} already seen, not triggering again.`); return; } if ((_customEventTrigger$w2 = customEventTrigger.whenData) !== null && _customEventTrigger$w2 !== void 0 && _customEventTrigger$w2.replyOnlyOnce && isReplied(customEventTrigger.survey)) { if (defaultParams !== null && defaultParams !== void 0 && defaultParams.includes('debug')) console.log(`Survey ${customEventTrigger.survey} already replied, not triggering again.`); return; } const conditions = customEventTrigger.conditions || []; let conditionsMet = true; // Check if all conditions are met for (const condition of conditions) { if (condition && condition.key) { if (!(eventProperties !== null && eventProperties !== void 0 && eventProperties[condition.key]) || !isCustomEventTriggerConditionTrue(condition, (eventProperties === null || eventProperties === void 0 ? void 0 : eventProperties[condition.key]) ?? '')) conditionsMet = false; } } if (conditionsMet) { if (defaultParams !== null && defaultParams !== void 0 && defaultParams.includes('debug')) console.log(`Triggered survey: ${customEventTrigger.survey} on custom event ${eventName}`); start(customEventTrigger.survey); } }, [defaultParams, start, triggers]); // EVENT: On survey close callback const onClose = React.useCallback(() => { setCurrentSurvey(null); }, []); // EVENT: Add hidden field const addHiddenFields = React.useCallback((newHiddenFields, setData) => { if (setData) { // If we want to set the hidden fields, we clear the previous ones setHiddenFields(newHiddenFields || {}); } else { // If we want to add hidden fields, we merge them setHiddenFields(prevHiddenFields => ({ ...prevHiddenFields, ...newHiddenFields })); } }, []); return /*#__PURE__*/React.createElement(SafeAreaProvider, null, /*#__PURE__*/React.createElement(ApolloProvider, { client: client }, /*#__PURE__*/React.createElement(NavigationListener, { onScreenChange: onScreenChange }, /*#__PURE__*/React.createElement(ToldContext.Provider, { value: { hiddenFields, trackScreen: onScreenChange, sendCustomEvent: checkCustomEvent, close: onClose, addHiddenFields } }, children, currentSurvey && /*#__PURE__*/React.createElement(ToldWidget, _extends({}, currentSurvey, { widgetUrl: widgetUrl })))))); } //# sourceMappingURL=ToldProvider.js.map