diff --git a/Analytics.js b/Analytics.js new file mode 100644 index 00000000..9624fb00 --- /dev/null +++ b/Analytics.js @@ -0,0 +1,21 @@ +import { getCurrentGlobalState } from './StateManager'; +import analytics from "@react-native-firebase/analytics"; + +const trackEvent = (eventName, eventParams = {}) => { + const globalState = getCurrentGlobalState(); + + const isLoggedIn = globalState.isLoggedIn; + + const usesOfflinePackages = globalState.offlinePackages && globalState.offlinePackages.length > 0; + + const augmentedParams = { + ...eventParams, + is_logged_in: isLoggedIn, + user_uses_offline_packages: usesOfflinePackages, + }; + + analytics().logEvent(eventName, augmentedParams); + console.log(`Event Tracked: ${eventName}`, augmentedParams); +}; + +export { trackEvent }; diff --git a/StateManager.js b/StateManager.js index f49900b1..82ebdaf4 100644 --- a/StateManager.js +++ b/StateManager.js @@ -192,118 +192,142 @@ const saveFieldToAsync = function (field, value) { AsyncStorage.setItem(field, JSON.stringify(value)); }; +let currentGlobalState = DEFAULT_STATE; + const reducer = function (state, action) { if (UPDATE_SETTINGS_ACTIONS[action.type] && !action.fromAsync) { AsyncStorage.setItem('lastSettingsUpdateTime', JSON.stringify(action.time)); } + let newState; switch (action.type) { case STATE_ACTIONS.setTheme: //const theme = action.value === "white" ? themeWhite : themeBlack; //no need to save value in async if that's where it is coming from if (!action.fromAsync) { saveFieldToAsync('color', action.value); } - return { + newState = { ...state, //theme, themeStr: action.value, }; + break; case STATE_ACTIONS.setTextLanguage: if (!action.fromAsync) { saveFieldToAsync('textLanguage', action.value); } - return { + newState = { ...state, textLanguage: action.value, }; + break; case STATE_ACTIONS.setInterfaceLanguage: if (!action.fromAsync) { saveFieldToAsync('interfaceLanguage', action.value); } if (action.value == 'hebrew') { strings.setLanguage('he'); } else if (action.value == 'english') { strings.setLanguage('en'); } - return { + newState = { ...state, interfaceLanguage: action.value, } + break; case STATE_ACTIONS.setEmailFrequency: if (!action.fromAsync) { saveFieldToAsync('emailFrequency', action.value); } - return { + newState = { ...state, emailFrequency: action.value, } + break; case STATE_ACTIONS.setReadingHistory: if (!action.fromAsync) { if (!action.value && state.readingHistory) { Sefaria.history.deleteHistory(false); } saveFieldToAsync('readingHistory', action.value); } - return { + newState = { ...state, readingHistory: action.value, } + break; case STATE_ACTIONS.setPreferredCustom: if (!action.fromAsync) { saveFieldToAsync('preferredCustom', action.value); } - return { + newState = { ...state, preferredCustom: action.value, } + break; case STATE_ACTIONS.setFontSize: if (!action.fromAsync) { saveFieldToAsync('fontSize', action.value); } - return { + newState = { ...state, fontSize: action.value, } + break; case STATE_ACTIONS.setAliyot: if (!action.fromAsync) { saveFieldToAsync('showAliyot', action.value); } - return { + newState = { ...state, showAliyot: action.value, } + break; case STATE_ACTIONS.setVocalization: if (!action.fromAsync) { saveFieldToAsync('vocalization', action.value); } - return { + newState = { ...state, vocalization: action.value, - } + } + break; case STATE_ACTIONS.toggleDebugInterruptingMessage: // toggle if you didn't pass in debug, otherwise you're initializing the value const newDebug = action.value === undefined ? (!state.debugInterruptingMessage) : action.value; if (!action.fromAsync) { saveFieldToAsync('debugInterruptingMessage', newDebug); } - return { + newState = { ...state, debugInterruptingMessage: newDebug, } + break; case STATE_ACTIONS.setBiLayout: if (!action.fromAsync) { saveFieldToAsync('biLayout', action.value); } - return { + newState = { ...state, biLayout: action.value, } + break; case STATE_ACTIONS.setIsLoggedIn: // action can be passed either object or bool const isLoggedIn = !!action.value; if (isLoggedIn && !!action.value.uid) { Sefaria._auth = action.value; } - return { + newState = { ...state, isLoggedIn, } + break; case STATE_ACTIONS.setHasDismissedSyncModal: if (!action.fromAsync) { saveFieldToAsync('hasDismissedSyncModal', action.value); } - return { + newState = { ...state, hasDismissedSyncModal: action.value, } + break; case STATE_ACTIONS.setDownloadNetworkSetting: if (!action.fromAsync) { saveFieldToAsync('downloadNetworkSetting', action.value); } - return { + newState = { ...state, downloadNetworkSetting: action.value, }; + break; case STATE_ACTIONS.setGroggerActive: if (!action.fromAsync) { saveFieldToAsync('groggerActive', action.value); } - return { + newState = { ...state, groggerActive: action.value, }; + break; default: - return state; + newState = state; + break; } + + currentGlobalState = newState; + return newState; }; +const getCurrentGlobalState = () => currentGlobalState; + const initAsyncStorage = dispatch => { // Loads data from each field in `_data` stored in Async storage into local memory for sync access. // Returns a Promise that resolves when all fields are loaded. @@ -338,4 +362,5 @@ export { GlobalStateContext, DispatchContext, getTheme, + getCurrentGlobalState, }; diff --git a/sefaria.js b/sefaria.js index 66147709..049f7df2 100644 --- a/sefaria.js +++ b/sefaria.js @@ -23,6 +23,7 @@ import { import * as FileSystem from 'expo-file-system'; import { Topic } from './Topic'; import {openFileInSources} from "./offline"; +import {trackEvent} from "./Analytics"; Sefaria = { @@ -1022,7 +1023,7 @@ Sefaria = { }, event: function(event, params) { - analytics().logEvent(event, params) + trackEvent(event, params); }, pageview: function(page, customDimensions, contentGroups) {