@told.club/sdk-rn
Version:
Told React Native SDK
225 lines (214 loc) • 12.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = ToldProvider;
var React = _interopRequireWildcard(require("react"));
var _reactNative = require("react-native");
var _client = require("@apollo/client");
var _reactNativeSafeAreaContext = require("react-native-safe-area-context");
var _reactNativeDeviceInfo = require("react-native-device-info");
var _ToldContext = _interopRequireDefault(require("./ToldContext"));
var _graphql = require("./utils/graphql");
var _NavigationListener = _interopRequireDefault(require("./NavigationListener"));
var _triggerConditions = require("./utils/triggerConditions");
var _ToldWidget = _interopRequireDefault(require("./ToldWidget"));
var _ToldStorage = require("./ToldStorage");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
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); }
const SERVER_API_URL = 'https://api.told.club';
const WIDGET_URL = 'https://widget.told.club';
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 _client.ApolloClient({
uri: `${apiUrl}/graphql`,
cache: new _client.InMemoryCache()
}), [apiUrl]);
const timeoutsRef = React.useRef([]);
// INIT: Load triggers
React.useEffect(() => {
const loadVars = {
folderID: sourceID,
type: 'IN_APP_MOBILE',
os: _reactNative.Platform.OS.toUpperCase(),
mobileApp: (0, _reactNativeDeviceInfo.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;
(0, _ToldStorage.loadSurveyData)().then(() => {
client.query({
query: _graphql.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') && (0, _ToldStorage.isSeen)(surveyId)) return;
client.query({
query: _graphql.CHECK_CAN_USE_SURVEY,
variables: {
surveyID: surveyId,
preview: defaultParams !== null && defaultParams !== void 0 && defaultParams.includes('preview') ? true : false,
os: _reactNative.Platform.OS.toUpperCase(),
mobileApp: (0, _reactNativeDeviceInfo.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 && (0, _ToldStorage.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 && (0, _ToldStorage.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) || (0, _triggerConditions.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 && (0, _ToldStorage.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 && (0, _ToldStorage.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]) || !(0, _triggerConditions.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(_reactNativeSafeAreaContext.SafeAreaProvider, null, /*#__PURE__*/React.createElement(_client.ApolloProvider, {
client: client
}, /*#__PURE__*/React.createElement(_NavigationListener.default, {
onScreenChange: onScreenChange
}, /*#__PURE__*/React.createElement(_ToldContext.default.Provider, {
value: {
hiddenFields,
trackScreen: onScreenChange,
sendCustomEvent: checkCustomEvent,
close: onClose,
addHiddenFields
}
}, children, currentSurvey && /*#__PURE__*/React.createElement(_ToldWidget.default, _extends({}, currentSurvey, {
widgetUrl: widgetUrl
}))))));
}
//# sourceMappingURL=ToldProvider.js.map