diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f8ca1e10..b1b93ef5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,7 +21,7 @@ jobs: run: npm publish --dry-run assert-lint: - name: Assert lint check passes and no lint warnings exist + name: Assert lint check passes and no lint errors exist runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 @@ -37,7 +37,7 @@ jobs: with: check-name: 'eslint results' only-pr-files: false - fail-on-warning: true + fail-on-warning: false fail-on-error: true markdown-report-on-step-summary: true repo-token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/Apps/APN/App.js b/Apps/APN/App.js index 3fbe14e0..531b656f 100644 --- a/Apps/APN/App.js +++ b/Apps/APN/App.js @@ -1,13 +1,21 @@ -import React, {useEffect, useRef, useState} from 'react'; -import { ActivityIndicator,Linking,StyleSheet} from 'react-native'; +import React, { useEffect, useRef, useState, useCallback } from 'react'; +import { ActivityIndicator, Linking, StyleSheet } from 'react-native'; import Login from './components/Login'; -import { NavigationContainer, useNavigationContainerRef } from '@react-navigation/native'; +import { + NavigationContainer, + useNavigationContainerRef, +} from '@react-navigation/native'; import { createNativeStackNavigator } from '@react-navigation/native-stack'; -import { CustomerIO, CustomerioConfig, CioLogLevel, CustomerIOEnv } from "customerio-reactnative"; +import { + CustomerIO, + CustomerioConfig, + CioLogLevel, + CustomerIOEnv, +} from 'customerio-reactnative'; import Dashboard from './components/Dashboard'; import CustomDataScreen from './components/CustomDataScreen'; -import SettingsScreen from './components/SettingsScreen' -import Env from "./env"; +import SettingsScreen from './components/SettingsScreen'; +import Env from './env'; import CioManager from './manager/CioManager'; import CioKeyValueStorage from './manager/KeyValueStorage'; import Deeplinks from './components/Deeplink'; @@ -16,29 +24,28 @@ import DefaultConstants from './util/DefaultConstants'; const Stack = createNativeStackNavigator(); export default function App() { - - const [firstScreen, setFirstScreen] = useState(undefined) + const [firstScreen, setFirstScreen] = useState(undefined); const [loading, setLoading] = useState(true); -const [isScreenTrackEnabled, setIsScreenTrackEnabled] = useState(null) -const [isDeviceAttrTrackEnabled, setIsDeviceAttrTrackEnabled] = useState(null) -const [isDebugModeEnabled, setIsDebugModeEnabled] = useState(null) -const [bgDelayValue, setBgDelayValue] = useState(null) -const [bgTasksValue, setBgTasksValue] = useState(null) -const [trackingUrl, setTrackingUrl] = useState(null) + const [isScreenTrackEnabled, setIsScreenTrackEnabled] = useState(null); + const [isDeviceAttrTrackEnabled, setIsDeviceAttrTrackEnabled] = + useState(null); + const [isDebugModeEnabled, setIsDebugModeEnabled] = useState(null); + const [bgDelayValue, setBgDelayValue] = useState(null); + const [bgTasksValue, setBgTasksValue] = useState(null); + const [trackingUrl, setTrackingUrl] = useState(null); useEffect(() => { (async () => { - const keyStorageObj = new CioKeyValueStorage() - const status = await keyStorageObj.getLoginStatus() - setLoading(false) + const keyStorageObj = new CioKeyValueStorage(); + const status = await keyStorageObj.getLoginStatus(); + setLoading(false); if (JSON.parse(status)) { - setFirstScreen("Dashboard") - return + setFirstScreen('Dashboard'); + return; } - setFirstScreen("Login") - + setFirstScreen('Login'); })(); - }, []) + }, []); // Automatic screen tracking const navigationRef = useNavigationContainerRef(); @@ -50,69 +57,111 @@ const [trackingUrl, setTrackingUrl] = useState(null) }; const linking = { prefixes: ['apn-rn-sample://'], - config + config, }; useEffect(() => { - fetchConfigsOrSetDefault() - }, []) + fetchConfigsOrSetDefault(); + }, []); useEffect(() => { - if(isDeviceAttrTrackEnabled !== null && isScreenTrackEnabled !== null && isDebugModeEnabled != null && bgDelayValue !== null && bgTasksValue !== null) - initialiseCioPackage() - }, [isDeviceAttrTrackEnabled, isScreenTrackEnabled, isDebugModeEnabled, bgDelayValue, bgTasksValue]) - - const fetchConfigsOrSetDefault = async() => { - const keyStorageObj = new CioKeyValueStorage() - const bgDelayValue = await keyStorageObj.getBGQSecondsDelay() - const bgTasksValue = await keyStorageObj.getBGQMinTasksInQueue() - const screenTrackValue = await keyStorageObj.getScreenTrack() - const deviceAttrValue = await keyStorageObj.getDeviceAttributesTrack() - const debugModeValue = await keyStorageObj.getDebugModeConfig() - const trackUrl = await keyStorageObj.getTrackingUrl() + if ( + isDeviceAttrTrackEnabled !== null && + isScreenTrackEnabled !== null && + isDebugModeEnabled != null && + bgDelayValue !== null && + bgTasksValue !== null + ) + initialiseCioPackage(); + }, [ + isDeviceAttrTrackEnabled, + isScreenTrackEnabled, + isDebugModeEnabled, + bgDelayValue, + bgTasksValue, + initialiseCioPackage, + ]); + + const fetchConfigsOrSetDefault = async () => { + const keyStorageObj = new CioKeyValueStorage(); + const bgDelayValue = await keyStorageObj.getBGQSecondsDelay(); + const bgTasksValue = await keyStorageObj.getBGQMinTasksInQueue(); + const screenTrackValue = await keyStorageObj.getScreenTrack(); + const deviceAttrValue = await keyStorageObj.getDeviceAttributesTrack(); + const debugModeValue = await keyStorageObj.getDebugModeConfig(); + const trackUrl = await keyStorageObj.getTrackingUrl(); // Setting values here to show default values on Settings screens if (screenTrackValue === null) { - await keyStorageObj.saveScreenTrack(DefaultConstants.SCREEN_TRACK_STATUS) + await keyStorageObj.saveScreenTrack(DefaultConstants.SCREEN_TRACK_STATUS); } if (bgDelayValue === null) { - await keyStorageObj.saveBGQSecondsDelay(`${DefaultConstants.BGQ_SECONDS_DELAY}`) + await keyStorageObj.saveBGQSecondsDelay( + `${DefaultConstants.BGQ_SECONDS_DELAY}` + ); } if (bgTasksValue === null) { - await keyStorageObj.saveBGQMinTasksInQueue(`${DefaultConstants.BGQ_MIN_TASKS_IN_QUEUE}`) + await keyStorageObj.saveBGQMinTasksInQueue( + `${DefaultConstants.BGQ_MIN_TASKS_IN_QUEUE}` + ); } if (deviceAttrValue === null) { - await keyStorageObj.saveDeviceAttributesTrack(`${DefaultConstants.TRACK_DEVICE_ATTRIBUTES_STATUS}`) + await keyStorageObj.saveDeviceAttributesTrack( + `${DefaultConstants.TRACK_DEVICE_ATTRIBUTES_STATUS}` + ); } if (debugModeValue === null) { - await keyStorageObj.saveDebugModeConfig(`${DefaultConstants.DEBUG_MODE_STATUS}`) + await keyStorageObj.saveDebugModeConfig( + `${DefaultConstants.DEBUG_MODE_STATUS}` + ); } - setIsDeviceAttrTrackEnabled(deviceAttrValue === null ? true : JSON.parse(deviceAttrValue)) - setIsScreenTrackEnabled(screenTrackValue === null ? true : JSON.parse(screenTrackValue)) - setIsDebugModeEnabled(debugModeValue === null ? true : JSON.parse(debugModeValue)) - setBgDelayValue(bgDelayValue === null ? DefaultConstants.BGQ_SECONDS_DELAY : parseInt(bgDelayValue)) - setBgTasksValue(bgTasksValue === null ? DefaultConstants.BGQ_MIN_TASKS_IN_QUEUE : parseInt(bgTasksValue)) - setTrackingUrl(trackUrl) - } - - const initialiseCioPackage = () => { + setIsDeviceAttrTrackEnabled( + deviceAttrValue === null ? true : JSON.parse(deviceAttrValue) + ); + setIsScreenTrackEnabled( + screenTrackValue === null ? true : JSON.parse(screenTrackValue) + ); + setIsDebugModeEnabled( + debugModeValue === null ? true : JSON.parse(debugModeValue) + ); + setBgDelayValue( + bgDelayValue === null + ? DefaultConstants.BGQ_SECONDS_DELAY + : parseInt(bgDelayValue) + ); + setBgTasksValue( + bgTasksValue === null + ? DefaultConstants.BGQ_MIN_TASKS_IN_QUEUE + : parseInt(bgTasksValue) + ); + setTrackingUrl(trackUrl); + }; - const configuration = new CustomerioConfig() - configuration.logLevel = isDebugModeEnabled === null ? CioLogLevel.debug : isDebugModeEnabled - configuration.autoTrackDeviceAttributes = isDeviceAttrTrackEnabled === null ? true : isDeviceAttrTrackEnabled - configuration.backgroundQueueMinNumberOfTasks = bgTasksValue - configuration.backgroundQueueSecondsDelay = bgDelayValue - if(trackingUrl != null) { - configuration.trackingApiUrl = trackingUrl + const initialiseCioPackage = useCallback(() => { + const configuration = new CustomerioConfig(); + configuration.logLevel = + isDebugModeEnabled === null ? CioLogLevel.debug : isDebugModeEnabled; + configuration.autoTrackDeviceAttributes = + isDeviceAttrTrackEnabled === null ? true : isDeviceAttrTrackEnabled; + configuration.backgroundQueueMinNumberOfTasks = bgTasksValue; + configuration.backgroundQueueSecondsDelay = bgDelayValue; + if (trackingUrl != null) { + configuration.trackingApiUrl = trackingUrl; } - - const env = new CustomerIOEnv() - env.siteId = Env.siteId - env.apiKey = Env.apiKey - const cioManager = new CioManager() - cioManager.initializeCio(env, configuration) - } + const env = new CustomerIOEnv(); + env.siteId = Env.siteId; + env.apiKey = Env.apiKey; + + const cioManager = new CioManager(); + cioManager.initializeCio(env, configuration); + }, [ + isDebugModeEnabled, + isDeviceAttrTrackEnabled, + bgTasksValue, + bgDelayValue, + trackingUrl, + ]); useEffect(() => { const getUrlAsync = async () => { @@ -129,13 +178,10 @@ const [trackingUrl, setTrackingUrl] = useState(null) getUrlAsync(); }, []); - if (loading == true ) { - return ( - - ) + if (loading == true) { + return ; } else { - return ( - + return ( // MARK:- AUTO SCREEN TRACKING // Start - - - - - - - - - - + > + + + + + + + + ); - } + } } const styles = StyleSheet.create({ mainView: { flex: 1, flexDirection: 'row', - paddingTop : 50, - justifyContent:'center' + paddingTop: 50, + justifyContent: 'center', }, }); - diff --git a/Apps/APN/babel.config.js b/Apps/APN/babel.config.js index 9496d67d..d872de3f 100644 --- a/Apps/APN/babel.config.js +++ b/Apps/APN/babel.config.js @@ -1,7 +1,7 @@ -module.exports = function(api) { +module.exports = function (api) { api.cache(true); return { presets: ['babel-preset-expo'], - plugins: ['react-native-reanimated/plugin'] + plugins: ['react-native-reanimated/plugin'], }; }; diff --git a/Apps/APN/components/CustomDataScreen.js b/Apps/APN/components/CustomDataScreen.js index 242e8f59..a1213daf 100644 --- a/Apps/APN/components/CustomDataScreen.js +++ b/Apps/APN/components/CustomDataScreen.js @@ -1,213 +1,207 @@ -import React, {useLayoutEffect, useState, useEffect} from 'react' -import { View, Text, TextInput, StyleSheet} from 'react-native' -import CioManager from '../manager/CioManager' -import ThemedButton from './common/Button' - -const CustomDataScreen = ({route, navigation}) => { - const { featureType } = route.params - - // Labels - const [title, setTitle] = useState('') - const [propertyLabel, setPropertyLabel] = useState('') - const [showEventName, setShowEventName] = useState(true) - const [buttonText, setButtonText] = useState('') - - // Values - const [eventName, setEventName] = useState('') - const [propertyName, setPropertyName] = useState('') - const [propertyValue, setPropertyValue] = useState('') - - useEffect(() => { - switch (featureType){ - case "Custom Event": - setTitle("Send Custom Events") - setPropertyLabel("Property") - setShowEventName(true) - setButtonText("event") - break - case "Device Attributes": - setTitle("Set Custom Device Attributes") - setPropertyLabel("Attribute") - setShowEventName(false) - setButtonText("device attributes") - break - case "Profile Attributes": - setTitle("Set Custom Profile Attributes") - setPropertyLabel("Attribute") - setShowEventName(false) - setButtonText("profile attributes") - break - default: - break - } - }, [featureType]) - - useLayoutEffect(() => { - navigation.setOptions({ - headerShadowVisible: false, - }) - }, [navigation]) - - const sendEventTapped = () => { - if (!IsFormValid()) { - alert("Please fill in all fields") - return - } - - const cioManager = new CioManager() - switch (featureType){ - case "Custom Event": - sendCustomEvent(cioManager) - break - case "Device Attributes": - sendDeviceAttributes(cioManager) - break - case "Profile Attributes": - sendProfileAttributes(cioManager) - break - default: - break - } - alert(`${featureType} sent`) - resetValues() +import React, { useLayoutEffect, useState, useEffect } from 'react'; +import { View, Text, TextInput, StyleSheet } from 'react-native'; +import CioManager from '../manager/CioManager'; +import ThemedButton from './common/Button'; + +const CustomDataScreen = ({ route, navigation }) => { + const { featureType } = route.params; + + // Labels + const [title, setTitle] = useState(''); + const [propertyLabel, setPropertyLabel] = useState(''); + const [showEventName, setShowEventName] = useState(true); + const [buttonText, setButtonText] = useState(''); + + // Values + const [eventName, setEventName] = useState(''); + const [propertyName, setPropertyName] = useState(''); + const [propertyValue, setPropertyValue] = useState(''); + + useEffect(() => { + switch (featureType) { + case 'Custom Event': + setTitle('Send Custom Events'); + setPropertyLabel('Property'); + setShowEventName(true); + setButtonText('event'); + break; + case 'Device Attributes': + setTitle('Set Custom Device Attributes'); + setPropertyLabel('Attribute'); + setShowEventName(false); + setButtonText('device attributes'); + break; + case 'Profile Attributes': + setTitle('Set Custom Profile Attributes'); + setPropertyLabel('Attribute'); + setShowEventName(false); + setButtonText('profile attributes'); + break; + default: + break; } - - const sendCustomEvent = (cioManager) => { - const data = {propertyName: propertyValue} - cioManager.customEvent(eventName, data) - } - - const sendDeviceAttributes = (cioManager) => { - const data = {propertyName: propertyValue} - cioManager.deviceAttributes(data) + }, [featureType]); + + useLayoutEffect(() => { + navigation.setOptions({ + headerShadowVisible: false, + }); + }, [navigation]); + + const sendEventTapped = () => { + if (!IsFormValid()) { + alert('Please fill in all fields'); + return; } - const sendProfileAttributes = (cioManager) => { - const data = {propertyName: propertyValue} - cioManager.profileAttributes(data) + const cioManager = new CioManager(); + switch (featureType) { + case 'Custom Event': + sendCustomEvent(cioManager); + break; + case 'Device Attributes': + sendDeviceAttributes(cioManager); + break; + case 'Profile Attributes': + sendProfileAttributes(cioManager); + break; + default: + break; } - - const resetValues = () => { - setEventName("") - setPropertyName("") - setPropertyValue("") + alert(`${featureType} sent`); + resetValues(); + }; + + const sendCustomEvent = (cioManager) => { + const data = { propertyName: propertyValue }; + cioManager.customEvent(eventName, data); + }; + + const sendDeviceAttributes = (cioManager) => { + const data = { propertyName: propertyValue }; + cioManager.deviceAttributes(data); + }; + + const sendProfileAttributes = (cioManager) => { + const data = { propertyName: propertyValue }; + cioManager.profileAttributes(data); + }; + + const resetValues = () => { + setEventName(''); + setPropertyName(''); + setPropertyValue(''); + }; + + const IsFormValid = () => { + if (featureType == 'Custom Event' && eventName.trim() == '') { + return false; } - - const IsFormValid = () => { - if (featureType == "Custom Event" && eventName.trim() == "") { - return false - } - if (propertyName.trim() == "" || propertyValue.trim() == "") - { - return false - } - return true + if (propertyName.trim() == '' || propertyValue.trim() == '') { + return false; } - - - return ( - - - - - {title} - - - { showEventName && - - - Event Name - - - setEventName(e)} - value={eventName} - placeholder='purchase' - /> - - - } - - - - {propertyLabel} Name - - - setPropertyName(e)} - value={propertyName} - placeholder='item' - /> - - - - - {propertyLabel} Value - - - setPropertyValue(e)} - value={propertyValue} - placeholder='socks' - /> - - - sendEventTapped()}> - - + return true; + }; + + return ( + + + + {title} + + {showEventName && ( + + + Event Name + + + setEventName(e)} + value={eventName} + placeholder="purchase" + /> + + + )} + + + {propertyLabel} Name + + + setPropertyName(e)} + value={propertyName} + placeholder="item" + /> + + + + + {propertyLabel} Value + + + setPropertyValue(e)} + value={propertyValue} + placeholder="socks" + /> + + sendEventTapped()} + /> - ) -} + + + ); +}; const styles = StyleSheet.create({ - container : { - flex : 1, - backgroundColor: '#fff' - }, - innerContainer: { - flex: 1, - alignContent: 'center', - alignItems: 'center', - justifyContent: 'center', - }, - title: { - fontSize: 22, - fontWeight: '700', - paddingBottom: 40 - }, - eventView:{ - width: '80%', - alignContent:'center', - justifyContent:"center", - bottom: 50 - }, - eventRowView: { - flexDirection: 'row', - alignItems:'center', - paddingBottom: 9, - }, - input: { - height: 40, - marginLeft: 20, - marginTop:3, - borderWidth: 1, - borderRadius:5, - borderColor:"#ebecf2", - padding: 10, - fontFamily:'Avenir', - color: '#4b4b60', - width: '100%', - }, - eventTitle: { - fontSize: 15 - } -}) - - -export default CustomDataScreen; \ No newline at end of file + container: { + flex: 1, + backgroundColor: '#fff', + }, + innerContainer: { + flex: 1, + alignContent: 'center', + alignItems: 'center', + justifyContent: 'center', + }, + title: { + fontSize: 22, + fontWeight: '700', + paddingBottom: 40, + }, + eventView: { + width: '80%', + alignContent: 'center', + justifyContent: 'center', + bottom: 50, + }, + eventRowView: { + flexDirection: 'row', + alignItems: 'center', + paddingBottom: 9, + }, + input: { + height: 40, + marginLeft: 20, + marginTop: 3, + borderWidth: 1, + borderRadius: 5, + borderColor: '#ebecf2', + padding: 10, + fontFamily: 'Avenir', + color: '#4b4b60', + width: '100%', + }, + eventTitle: { + fontSize: 15, + }, +}); + +export default CustomDataScreen; diff --git a/Apps/APN/components/Dashboard.js b/Apps/APN/components/Dashboard.js index 5cf3310c..dee9084e 100644 --- a/Apps/APN/components/Dashboard.js +++ b/Apps/APN/components/Dashboard.js @@ -1,208 +1,233 @@ -import React, {useState} from 'react' -import { View, Text, FlatList, StyleSheet, Image, Alert, TouchableOpacity} from 'react-native' -import CioManager from '../manager/CioManager' -import ThemedButton from './common/Button' -import PushNotification from "react-native-push-notification"; -import CioKeyValueStorage from '../manager/KeyValueStorage' -import { CustomerIO } from 'customerio-reactnative' - -const Dashboard = ({navigation}) => { - - const [deviceToken, setDeviceToken] = useState(null) - // To get device token - PushNotification.configure({ - onRegister: function (token) { - setDeviceToken(token["token"]) - } +import React, { useState } from 'react'; +import { + View, + Text, + FlatList, + StyleSheet, + Image, + Alert, + TouchableOpacity, +} from 'react-native'; +import CioManager from '../manager/CioManager'; +import ThemedButton from './common/Button'; +import PushNotification from 'react-native-push-notification'; +import CioKeyValueStorage from '../manager/KeyValueStorage'; +import { CustomerIO } from 'customerio-reactnative'; + +const Dashboard = ({ navigation }) => { + const [deviceToken, setDeviceToken] = useState(null); + // To get device token + PushNotification.configure({ + onRegister: function (token) { + setDeviceToken(token.token); + }, + }); + + const sendRandomEventTapped = () => { + const cioManager = new CioManager(); + cioManager.randomEvent(); + alert('Random event tracked successfully.'); + }; + + const settingsTapped = () => { + navigation.navigate('SettingsScreen'); + }; + const sendCustomEventTapped = () => { + navigation.navigate('CustomDataScreen', { + featureType: 'Custom Event', }); - - - const sendRandomEventTapped = () => { - const cioManager = new CioManager() - cioManager.randomEvent() - alert("Random event tracked successfully.") - } - - const settingsTapped = () => { - navigation.navigate("SettingsScreen") - } - const sendCustomEventTapped = () => { - navigation.navigate("CustomDataScreen", { - featureType : "Custom Event" - }) - } - - const setDeviceAttributesTapped = () => { - navigation.navigate("CustomDataScreen", { - featureType : "Device Attributes" - }) - } - - const setProfileAttributesTapped = () => { - navigation.navigate("CustomDataScreen", { - featureType : "Profile Attributes" - }) - } - - const logoutTapped = async() => { - const cioManager = new CioManager() - cioManager.clearUserIdentity() - - const keyStorageObj = new CioKeyValueStorage() - await keyStorageObj.saveLoginStatus(false) - navigation.navigate("Login") - } - - const renderDashboardButtons = (item) => { - return ( - - ) - } - - const showPushPrompt = () => { - var options = {"ios" : {"sound" : true, "badge" : true}} - - CustomerIO.showPromptForPushNotifications(options).then(status => { - alert("Push permission " + status) - console.log("Push permission " + status) - }).catch(error => { - alert("Could not show prompt.") - }) - } - - const getCurrentPushPermission = () => { - CustomerIO.getPushPermissionStatus().then(status => { - alert("Push permission status is - " + status) - console.log("Push permission status is - " + status) - }) - } + }; - const registerDeviceToken = () => { - if(deviceToken !== null) { - CustomerIO.registerDeviceToken(deviceToken) - alert("Device token registered successfully") - return - } - alert("Could not register device. Device token unavailable.") - } + const setDeviceAttributesTapped = () => { + navigation.navigate('CustomDataScreen', { + featureType: 'Device Attributes', + }); + }; - const userIconTapped = async () => { - const keyStorageObj = new CioKeyValueStorage() - const userDetail = JSON.parse(await keyStorageObj.getLoginDetail()) + const setProfileAttributesTapped = () => { + navigation.navigate('CustomDataScreen', { + featureType: 'Profile Attributes', + }); + }; + + const logoutTapped = async () => { + const cioManager = new CioManager(); + cioManager.clearUserIdentity(); + + const keyStorageObj = new CioKeyValueStorage(); + await keyStorageObj.saveLoginStatus(false); + navigation.navigate('Login'); + }; + + const renderDashboardButtons = (item) => { + return ; + }; + + const showPushPrompt = () => { + var options = { ios: { sound: true, badge: true } }; + + CustomerIO.showPromptForPushNotifications(options) + .then((status) => { + alert('Push permission ' + status); + console.log('Push permission ' + status); + }) + .catch((error) => { + alert('Could not show prompt.'); + }); + }; + + const getCurrentPushPermission = () => { + CustomerIO.getPushPermissionStatus().then((status) => { + alert('Push permission status is - ' + status); + console.log('Push permission status is - ' + status); + }); + }; - Alert.alert('User Info', "Name - " + userDetail.name + "\n\nEmailId - " + userDetail.id, [ - {text: 'OK'} - ]); + const registerDeviceToken = () => { + if (deviceToken !== null) { + CustomerIO.registerDeviceToken(deviceToken); + alert('Device token registered successfully'); + return; } - - PushNotification.configure({ - /** - * (optional) default: true - * - Specified if permissions (ios) and token (android and ios) will requested or not, - * - if not, you must call PushNotificationsHandler.requestPermissions() later - * - if you are not using remote notification or do not have Firebase installed, use this: - * requestPermissions: Platform.OS === 'ios' - */ - requestPermissions: true, - }) - - return ( - - - - - - userIconTapped()}> - - - - - - - - - settingsTapped()}> - - - - - - - - - - What would you like to test? - - - - showPushPrompt()}, - {key: 'Get current push permissions', onClick: () => getCurrentPushPermission()}, - {key: 'Register device token', onClick: () => registerDeviceToken()}, - {key: 'Send Random Event', onClick: () => sendRandomEventTapped()}, - {key: 'Send Custom Event', onClick: () => sendCustomEventTapped()}, - {key: 'Set Device Attributes', onClick: () => setDeviceAttributesTapped()}, - {key: 'Set Profile Attributes', onClick: () => setProfileAttributesTapped()}, - {key: 'Logout', onClick: () => logoutTapped()}, - ]} - renderItem={({item}) => renderDashboardButtons(item)} - /> - - + alert('Could not register device. Device token unavailable.'); + }; + + const userIconTapped = async () => { + const keyStorageObj = new CioKeyValueStorage(); + const userDetail = JSON.parse(await keyStorageObj.getLoginDetail()); + + Alert.alert( + 'User Info', + 'Name - ' + userDetail.name + '\n\nEmailId - ' + userDetail.id, + [{ text: 'OK' }] + ); + }; + + PushNotification.configure({ + /** + * (optional) default: true + * - Specified if permissions (ios) and token (android and ios) will requested or not, + * - if not, you must call PushNotificationsHandler.requestPermissions() later + * - if you are not using remote notification or do not have Firebase installed, use this: + * requestPermissions: Platform.OS === 'ios' + */ + requestPermissions: true, + }); + + return ( + + + + + + userIconTapped()}> + + + + + + + + settingsTapped()}> + + + - ) -} + + What would you like to test? + + + showPushPrompt() }, + { + key: 'Get current push permissions', + onClick: () => getCurrentPushPermission(), + }, + { + key: 'Register device token', + onClick: () => registerDeviceToken(), + }, + { + key: 'Send Random Event', + onClick: () => sendRandomEventTapped(), + }, + { + key: 'Send Custom Event', + onClick: () => sendCustomEventTapped(), + }, + { + key: 'Set Device Attributes', + onClick: () => setDeviceAttributesTapped(), + }, + { + key: 'Set Profile Attributes', + onClick: () => setProfileAttributesTapped(), + }, + { key: 'Logout', onClick: () => logoutTapped() }, + ]} + renderItem={({ item }) => renderDashboardButtons(item)} + /> + + + + + ); +}; const styles = StyleSheet.create({ - container : { - flex : 1 - }, - innerContainer: { - flex:1, - alignItems:'center', - alignSelf:'stretch', - margin:5, - marginTop: 15 - }, - title: { - fontSize: 22 - }, - featuresView: { - width: '80%' - }, - featureTitleText:{ - color:'#fff', - textAlign:'center', - fontWeight: '600', - paddingLeft : 10, - fontSize: 17, - paddingRight : 10 - }, - settingsView: { - alignItems: 'flex-end', - height: 50, - flex: 1, - paddingRight: 10, - }, - settingsImage: { - width: 40, - height: 40 - }, - flexRow: { - top: 75, - flexDirection: 'row', - }, - userIconView: { - paddingLeft: 10 - } -}) - -export default Dashboard; \ No newline at end of file + container: { + flex: 1, + }, + innerContainer: { + flex: 1, + alignItems: 'center', + alignSelf: 'stretch', + margin: 5, + marginTop: 15, + }, + title: { + fontSize: 22, + }, + featuresView: { + width: '80%', + }, + featureTitleText: { + color: '#fff', + textAlign: 'center', + fontWeight: '600', + paddingLeft: 10, + fontSize: 17, + paddingRight: 10, + }, + settingsView: { + alignItems: 'flex-end', + height: 50, + flex: 1, + paddingRight: 10, + }, + settingsImage: { + width: 40, + height: 40, + }, + flexRow: { + top: 75, + flexDirection: 'row', + }, + userIconView: { + paddingLeft: 10, + }, +}); + +export default Dashboard; diff --git a/Apps/APN/components/Deeplink.js b/Apps/APN/components/Deeplink.js index f5157650..61aac299 100644 --- a/Apps/APN/components/Deeplink.js +++ b/Apps/APN/components/Deeplink.js @@ -1,24 +1,25 @@ -import React from 'react' -import { View, StyleSheet, Text} from 'react-native'; +import React from 'react'; +import { View, StyleSheet, Text } from 'react-native'; const Deeplinks = () => { return ( - - Welcome! You see this screen because you tapped on a push notification that had a deep link in it's payload. - + + Welcome! You see this screen because you tapped on a push notification + that had a deep link in it's payload. + - ) -} + ); +}; const styles = StyleSheet.create({ - container: { - flex:1, - backgroundColor: "#e3e3e3" - }, - textLabel: { - padding: 20, - color: '#000', - lineHeight: 25 - } -}) -export default Deeplinks; \ No newline at end of file + container: { + flex: 1, + backgroundColor: '#e3e3e3', + }, + textLabel: { + padding: 20, + color: '#000', + lineHeight: 25, + }, +}); +export default Deeplinks; diff --git a/Apps/APN/components/Login.js b/Apps/APN/components/Login.js index ae0e91d6..5ca9ae01 100644 --- a/Apps/APN/components/Login.js +++ b/Apps/APN/components/Login.js @@ -1,225 +1,235 @@ -import React, {useState} from 'react' -import { View, Text, TextInput, StyleSheet, Image, TouchableOpacity} from 'react-native' -import CioManager from '../manager/CioManager' -import CioKeyValueStorage from '../manager/KeyValueStorage' +import React, { useState } from 'react'; +import { + View, + Text, + TextInput, + StyleSheet, + Image, + TouchableOpacity, +} from 'react-native'; +import CioManager from '../manager/CioManager'; +import CioKeyValueStorage from '../manager/KeyValueStorage'; -const Login = ({navigation}) => { +const Login = ({ navigation }) => { + const [email, setEmail] = useState(''); + const [name, setName] = useState(''); + const [isLoginTapped, setIsLoginTapped] = useState(false); - const [email, setEmail] = useState('') - const [name, setName] = useState('') - const [isLoginTapped, setIsLoginTapped] = useState(false) + const loginTapped = () => { + setIsLoginTapped(true); - const loginTapped = () => { - setIsLoginTapped(true) - - if (!IsAllFieldsFilled()) { - alert("Please enter name and email") - return - } - if (!validateEmail(email)) { - alert("Please enter a valid email") - return - } - const cioManager = new CioManager() - const data = {"firstName": name.trim()} - cioManager.identifyUser(email.trim(), data) - - // Save login status - const keyStorageObj = new CioKeyValueStorage() - keyStorageObj.saveLoginStatus(true) - keyStorageObj.saveLoginDetail({"name" : name.trim(), "id" : email.trim()}) - navigation.navigate("Dashboard") + if (!IsAllFieldsFilled()) { + alert('Please enter name and email'); + return; } - - const settingsTapped = () => { - navigation.navigate("SettingsScreen") + if (!validateEmail(email)) { + alert('Please enter a valid email'); + return; } - const IsAllFieldsFilled = () => { - if (name.trim() == "" || email.trim() == "") { - return false - } - return true + const cioManager = new CioManager(); + const data = { firstName: name.trim() }; + cioManager.identifyUser(email.trim(), data); + + // Save login status + const keyStorageObj = new CioKeyValueStorage(); + keyStorageObj.saveLoginStatus(true); + keyStorageObj.saveLoginDetail({ name: name.trim(), id: email.trim() }); + navigation.navigate('Dashboard'); + }; + + const settingsTapped = () => { + navigation.navigate('SettingsScreen'); + }; + const IsAllFieldsFilled = () => { + if (name.trim() == '' || email.trim() == '') { + return false; } + return true; + }; - const validateEmail = (email) => { - let reg = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/ - if (reg.test(email) === false) { - return false; - } - return true + const validateEmail = (email) => { + let reg = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/; + if (reg.test(email) === false) { + return false; } + return true; + }; - const generateUniqueUser = () => { - const char = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890'; - const random = Array.from( - {length: 15}, - () => char[Math.floor(Math.random() * char.length)] - ); - const randomString = random.join(""); - setName(randomString) - setEmail(randomString+"@customer.io") - alert("New User Created") - } + const generateUniqueUser = () => { + const char = + 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890'; + const random = Array.from( + { length: 15 }, + () => char[Math.floor(Math.random() * char.length)] + ); + const randomString = random.join(''); + setName(randomString); + setEmail(randomString + '@customer.io'); + alert('New User Created'); + }; return ( - - - - - settingsTapped()}> - - - - - - - - - - - Ami App - React Native APN - - setName(e)} - value={name} - placeholder='First Name' + + + + + settingsTapped()}> + + + + + + + + Ami App + React Native APN - setEmail(e)} - value={email} - placeholder='Email' - /> + setName(e)} + value={name} + placeholder="First Name" + /> + + + setEmail(e)} + value={email} + placeholder="Email" + /> loginTapped()} - underlayColor='#f194ff'> - LOGIN - + style={styles.loginButton} + onPress={() => loginTapped()} + underlayColor="#f194ff" + > + LOGIN + - generateUniqueUser()} + generateUniqueUser()} > - Generate random login - + + Generate random login + + - {/* */} - + {/* */} + - ) -} - + ); +}; const styles = StyleSheet.create({ - settingsView: { + settingsView: { alignItems: 'flex-end', height: 50, paddingRight: 30, -}, -settingsImage: { - width: 50, - height: 50 -}, - container: { - flex: 1, - }, - headerSubText: { - fontFamily:'Avenir', - fontSize: 15, - color:'#343446', - alignSelf: 'center', - bottom : 100, - }, - headerText : { - fontFamily:'Avenir', - fontSize: 30, - color:'#343446', - fontWeight: '700', - alignSelf: 'center', - bottom : 100, - }, - loginView: { - alignItems: 'center', - justifyContent: 'center', - alignSelf: 'center', - width: '80%', - flex: 0.9, - }, - generateRandomLoginButton: { - alignSelf:'center', - paddingBottom:10, - marginBottom: 40, - }, - loginViewContainer: { - flex: 1, - alignContent: 'center', - justifyContent:'center' - }, - innerContainer:{ - flex:1, - margin: 30, - }, - nameView: { - flexDirection: 'column', - }, - labelText: { - padding: 20, - paddingBottom:0, - color: '#6f7488', - fontFamily:'Avenir', - fontWeight: '600' - }, - input: { - height: 40, - margin: 20, - marginTop:3, - borderWidth: 1, - borderRadius:5, - borderColor:"#ebecf2", - padding: 10, - fontFamily:'Avenir', - color: '#4b4b60', - borderWidth: 0, - borderBottomWidth: 1, - borderColor: '#E0E0E0' - }, - loginButton:{ - padding:10, - alignSelf:'center', - paddingBottom:10, - backgroundColor:'#3C437D', - borderRadius:10, - borderWidth: 1, - borderColor: '#fff', - marginTop: 20, - marginBottom: 20, - width: '90%' - }, - loginText:{ - color:'#fff', - textAlign:'center', - fontWeight: '600', - paddingLeft : 10, - paddingRight : 10 - }, - footer:{ - justifyContent: 'flex-end', - alignItems: 'center', - marginTop: 35, - marginLeft:-20 - } -}) + }, + settingsImage: { + width: 50, + height: 50, + }, + container: { + flex: 1, + }, + headerSubText: { + fontFamily: 'Avenir', + fontSize: 15, + color: '#343446', + alignSelf: 'center', + bottom: 100, + }, + headerText: { + fontFamily: 'Avenir', + fontSize: 30, + color: '#343446', + fontWeight: '700', + alignSelf: 'center', + bottom: 100, + }, + loginView: { + alignItems: 'center', + justifyContent: 'center', + alignSelf: 'center', + width: '80%', + flex: 0.9, + }, + generateRandomLoginButton: { + alignSelf: 'center', + paddingBottom: 10, + marginBottom: 40, + }, + loginViewContainer: { + flex: 1, + alignContent: 'center', + justifyContent: 'center', + }, + innerContainer: { + flex: 1, + margin: 30, + }, + nameView: { + flexDirection: 'column', + }, + labelText: { + padding: 20, + paddingBottom: 0, + color: '#6f7488', + fontFamily: 'Avenir', + fontWeight: '600', + }, + input: { + height: 40, + margin: 20, + marginTop: 3, + borderRadius: 5, + padding: 10, + fontFamily: 'Avenir', + color: '#4b4b60', + borderWidth: 0, + borderBottomWidth: 1, + borderColor: '#E0E0E0', + }, + loginButton: { + padding: 10, + alignSelf: 'center', + paddingBottom: 10, + backgroundColor: '#3C437D', + borderRadius: 10, + borderWidth: 1, + borderColor: '#fff', + marginTop: 20, + marginBottom: 20, + width: '90%', + }, + loginText: { + color: '#fff', + textAlign: 'center', + fontWeight: '600', + paddingLeft: 10, + paddingRight: 10, + }, + footer: { + justifyContent: 'flex-end', + alignItems: 'center', + marginTop: 35, + marginLeft: -20, + }, +}); -export default Login; \ No newline at end of file +export default Login; diff --git a/Apps/APN/components/RegisterDeviceToken.js b/Apps/APN/components/RegisterDeviceToken.js index c925baf5..050ec290 100644 --- a/Apps/APN/components/RegisterDeviceToken.js +++ b/Apps/APN/components/RegisterDeviceToken.js @@ -1,81 +1,80 @@ -import React, {useState} from "react"; -import { StyleSheet, View, Text, Platform } from "react-native"; -import FeatureButton from "./common/FeatureButton"; -import { SubHeaderText } from "./common/Text"; +import React, { useState } from 'react'; +import { StyleSheet, View, Text, Platform } from 'react-native'; +import FeatureButton from './common/FeatureButton'; +import { SubHeaderText } from './common/Text'; import { CustomerIO } from 'customerio-reactnative'; - const RegisterDeviceToken = (props) => { + const [deviceToken, setDeviceToken] = useState(''); + const registerDevice = () => { + // For the sake of testing, we are generating a random + // alphanumeric string and passing it as a token. + // Customer.io expects a valid token to send push notifications + // to the user. + const token = generateRandomToken(); + // MARK:- REGISTER DEVICE TOKEN + CustomerIO.registerDeviceToken(token); + setDeviceToken(token); + alert('Device token registered'); + }; - const [deviceToken, setDeviceToken] = useState('') - const registerDevice = () => { - - // For the sake of testing, we are generating a random - // alphanumeric string and passing it as a token. - // Customer.io expects a valid token to send push notifications - // to the user. - const token = generateRandomToken() - // MARK:- REGISTER DEVICE TOKEN - CustomerIO.registerDeviceToken(token) - setDeviceToken(token) - alert("Device token registered") + const generateRandomToken = () => { + let length = 163; + if (Platform.OS == 'ios') { + length = 64; } + const char = + 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890'; + const random = Array.from( + { length: 64 }, + () => char[Math.floor(Math.random() * char.length)] + ); + const randomString = random.join(''); + return randomString; + }; - const generateRandomToken = () => { - let length = 163 - if (Platform.OS == "ios"){ - length = 64 - } - const char = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890'; - const random = Array.from( - {length: 64}, - () => char[Math.floor(Math.random() * char.length)] - ); - const randomString = random.join(""); - return randomString - } - - return ( - - - - registerDevice()}> - - - {deviceToken} - - - ) -} + return ( + + + + registerDevice()} + /> + + + {deviceToken} + + + ); +}; const styles = StyleSheet.create({ - container : { - backgroundColor: 'white', - marginTop: 20, - borderRadius: 25 - }, - innerContainer: { - marginTop: 5, - }, - input: { - height: 40, - marginLeft: 12, - marginRight: 12, - marginBottom: 12, - borderWidth: 1, - padding: 10, - backgroundColor: 'white', - borderColor: '#e6e6e6', - borderRadius: 10 - }, - deviceTokenText:{ - flex:1, - paddingLeft:25, - paddingRight:25 - } -}) + container: { + backgroundColor: 'white', + marginTop: 20, + borderRadius: 25, + }, + innerContainer: { + marginTop: 5, + }, + input: { + height: 40, + marginLeft: 12, + marginRight: 12, + marginBottom: 12, + borderWidth: 1, + padding: 10, + backgroundColor: 'white', + borderColor: '#e6e6e6', + borderRadius: 10, + }, + deviceTokenText: { + flex: 1, + paddingLeft: 25, + paddingRight: 25, + }, +}); -export default RegisterDeviceToken; \ No newline at end of file +export default RegisterDeviceToken; diff --git a/Apps/APN/components/SettingsScreen.js b/Apps/APN/components/SettingsScreen.js index 345c9a76..89499607 100644 --- a/Apps/APN/components/SettingsScreen.js +++ b/Apps/APN/components/SettingsScreen.js @@ -1,42 +1,57 @@ -import React, {useLayoutEffect, useState, useEffect, useRef} from 'react' -import { View, StyleSheet, Text, Alert, Image, Switch, Linking, AppState, TouchableOpacity } from 'react-native'; +import React, { useLayoutEffect, useState, useEffect, useRef } from 'react'; +import { + View, + StyleSheet, + Text, + Alert, + Image, + Switch, + Linking, + AppState, + TouchableOpacity, +} from 'react-native'; import Clipboard from '@react-native-clipboard/clipboard'; import { ScrollView, TextInput } from 'react-native-gesture-handler'; import Env from '../env'; -import PushNotification from "react-native-push-notification"; +import PushNotification from 'react-native-push-notification'; import ThemedButton from './common/Button'; import CioKeyValueStorage from '../manager/KeyValueStorage'; import { CustomerIO } from 'customerio-reactnative'; import { set } from 'react-native-reanimated'; import DefaultConstants from '../util/DefaultConstants'; -const SettingsScreen = ({navigation}) => { -const [deviceToken, setDeviceToken] = useState('') -const [trackUrl, setTrackUrl] = useState('') -const [isDebugModeEnabled, setIsDebugModeEnabled] = useState(true) -const [pushStatus, setPushStatus] = useState('') -const [isPushEnabled, setIsPushEnabled] = useState(false) -const [isTrackDeviceAttributesEnabled, setIsTrackDeviceAttributesEnabled] = useState(true) -const [isTrackScreensEnabled, setIsTrackScreensEnabled] = useState(false) -const [bgQDelay, setBgQDelay] = useState(`${DefaultConstants.BGQ_SECONDS_DELAY}`) -const [bgQMinNumTasks, setBgQMinNumTasks] = useState(`${DefaultConstants.BGQ_MIN_TASKS_IN_QUEUE}`) +const SettingsScreen = ({ navigation }) => { + const [deviceToken, setDeviceToken] = useState(''); + const [trackUrl, setTrackUrl] = useState(''); + const [isDebugModeEnabled, setIsDebugModeEnabled] = useState(true); + const [pushStatus, setPushStatus] = useState(''); + const [isPushEnabled, setIsPushEnabled] = useState(false); + const [isTrackDeviceAttributesEnabled, setIsTrackDeviceAttributesEnabled] = + useState(true); + const [isTrackScreensEnabled, setIsTrackScreensEnabled] = useState(false); + const [bgQDelay, setBgQDelay] = useState( + `${DefaultConstants.BGQ_SECONDS_DELAY}` + ); + const [bgQMinNumTasks, setBgQMinNumTasks] = useState( + `${DefaultConstants.BGQ_MIN_TASKS_IN_QUEUE}` + ); -useLayoutEffect(() => { + useLayoutEffect(() => { navigation.setOptions({ headerShadowVisible: false, - }) - }, [navigation]) + }); + }, [navigation]); const appState = useRef(AppState.currentState); // This useEffect registeres an event listener to notify the states of the app useEffect(() => { - const subscription = AppState.addEventListener('change', nextAppState => { + const subscription = AppState.addEventListener('change', (nextAppState) => { if ( appState.current.match(/inactive|background/) && nextAppState === 'active' ) { - getPushStatus() + getPushStatus(); } appState.current = nextAppState; }); @@ -46,165 +61,169 @@ useLayoutEffect(() => { }; }, []); - - useEffect(() => { - getConfigurationsFromStorage() - getPushStatus() - }, []) - + getConfigurationsFromStorage(); + getPushStatus(); + }, []); + const getConfigurationsFromStorage = async () => { - const keyStorageObj = new CioKeyValueStorage() + const keyStorageObj = new CioKeyValueStorage(); // Tracking url - const trackingUrl = await keyStorageObj.getTrackingUrl() - setTrackUrl(trackingUrl) + const trackingUrl = await keyStorageObj.getTrackingUrl(); + setTrackUrl(trackingUrl); // Screen track - const screenTrackStatus = await keyStorageObj.getScreenTrack() - setIsTrackScreensEnabled(JSON.parse(screenTrackStatus)) + const screenTrackStatus = await keyStorageObj.getScreenTrack(); + setIsTrackScreensEnabled(JSON.parse(screenTrackStatus)); // Track device attribute - const deviceTrackStatus = await keyStorageObj.getDeviceAttributesTrack() - setIsTrackDeviceAttributesEnabled(JSON.parse(deviceTrackStatus)) + const deviceTrackStatus = await keyStorageObj.getDeviceAttributesTrack(); + setIsTrackDeviceAttributesEnabled(JSON.parse(deviceTrackStatus)); // Debug mode - const debugModeStatus = await keyStorageObj.getDebugModeConfig() - setIsDebugModeEnabled(JSON.parse(debugModeStatus)) + const debugModeStatus = await keyStorageObj.getDebugModeConfig(); + setIsDebugModeEnabled(JSON.parse(debugModeStatus)); // BGQ Seconds delay - const bgDelayValue = await keyStorageObj.getBGQSecondsDelay() - setBgQDelay(bgDelayValue) + const bgDelayValue = await keyStorageObj.getBGQSecondsDelay(); + setBgQDelay(bgDelayValue); // BGQ min tasks - const minTasksValue = await keyStorageObj.getBGQMinTasksInQueue() - setBgQMinNumTasks(minTasksValue) - } + const minTasksValue = await keyStorageObj.getBGQMinTasksInQueue(); + setBgQMinNumTasks(minTasksValue); + }; const getPushStatus = () => { CustomerIO.getPushPermissionStatus().then((status) => { - setPushStatus(status) - if (status == "Granted") { - setIsPushEnabled(true) - return + setPushStatus(status); + if (status == 'Granted') { + setIsPushEnabled(true); + return; } - setIsPushEnabled(false) - }) - } + setIsPushEnabled(false); + }); + }; const toggleSwitch = async (type) => { - switch(type) { - case "Push": + switch (type) { + case 'Push': // Case 1: Open settings to update push permissions if (isPushEnabled === true || pushStatus == 'Denied') { - Linking.openSettings() - return + Linking.openSettings(); + return; } // Case 2: Show prompt if permissions have not been determined yet - if (pushStatus == "Notdetermined") { - var options = {ios : {sound : true, badge: true}} - CustomerIO.showPromptForPushNotifications(options).then((status) => { - alert("Push permission " + status) - console.log("Push permission " + status) - }).catch(error => { - alert("Could not show prompt.") - }) + if (pushStatus == 'Notdetermined') { + var options = { ios: { sound: true, badge: true } }; + CustomerIO.showPromptForPushNotifications(options) + .then((status) => { + alert('Push permission ' + status); + console.log('Push permission ' + status); + }) + .catch((error) => { + alert('Could not show prompt.'); + }); } - break - case "Debug": - setIsDebugModeEnabled(previousState => !previousState); - break - case "DeviceAttr": - setIsTrackDeviceAttributesEnabled(previousState => !previousState); - break - case "Screens": - setIsTrackScreensEnabled(previousState => !previousState); - break + break; + case 'Debug': + setIsDebugModeEnabled((previousState) => !previousState); + break; + case 'DeviceAttr': + setIsTrackDeviceAttributesEnabled((previousState) => !previousState); + break; + case 'Screens': + setIsTrackScreensEnabled((previousState) => !previousState); + break; default: - break + break; } - } + }; const copyToClipboard = () => { - Clipboard.setString(deviceToken) - alert("Copied device token to clipboard.") - } + Clipboard.setString(deviceToken); + alert('Copied device token to clipboard.'); + }; PushNotification.configure({ onRegister: function (token) { - setDeviceToken(token["token"]) - } + setDeviceToken(token.token); + }, }); const saveSettings = async () => { - const keyStorageObj = new CioKeyValueStorage() - if(trackUrl != null) { await keyStorageObj.saveTrackingUrl(trackUrl.trim()) } - - await keyStorageObj.saveBGQSecondsDelay(bgQDelay) - await keyStorageObj.saveBGQMinTasksInQueue(bgQMinNumTasks) - await keyStorageObj.saveIsPushEnabledConfig(isPushEnabled) - await keyStorageObj.saveScreenTrack(!isTrackScreensEnabled) - await keyStorageObj.saveDebugModeConfig(!isDebugModeEnabled) - await keyStorageObj.saveDeviceAttributesTrack(!isTrackDeviceAttributesEnabled) + const keyStorageObj = new CioKeyValueStorage(); + if (trackUrl != null) { + await keyStorageObj.saveTrackingUrl(trackUrl.trim()); + } + + await keyStorageObj.saveBGQSecondsDelay(bgQDelay); + await keyStorageObj.saveBGQMinTasksInQueue(bgQMinNumTasks); + await keyStorageObj.saveIsPushEnabledConfig(isPushEnabled); + await keyStorageObj.saveScreenTrack(!isTrackScreensEnabled); + await keyStorageObj.saveDebugModeConfig(!isDebugModeEnabled); + await keyStorageObj.saveDeviceAttributesTrack( + !isTrackDeviceAttributesEnabled + ); Alert.alert('Info', 'Settings have been updated successfully.', [ - {text: 'OK', onPress: () => navigation.goBack()}, + { text: 'OK', onPress: () => navigation.goBack() }, ]); - } + }; const alertUserBeforeSaving = () => { Alert.alert('Info', 'Saving settings will require an app restart.', [ - {text: 'OK', onPress: () => saveSettings()}, + { text: 'OK', onPress: () => saveSettings() }, { text: 'Cancel', onPress: () => console.log('Saving cancelled by the user'), style: 'cancel', }, ]); - } - + }; + return ( - - - Settings - - - - Device Token - - copyToClipboard()}> - - - - - - - {/* CIO Track URL */} - - - CIO Track URL - setTrackUrl(e)} - value={trackUrl} - placeholder="track.customer.io" - editable={true} - /> - - - + + + Settings + + + + Device Token + + copyToClipboard()} + > + + + + + {/* CIO Track URL */} + + + CIO Track URL + setTrackUrl(e)} + value={trackUrl} + placeholder="track.customer.io" + editable={true} + /> + + + - {/* Gist Environment + {/* Gist Environment Gist Environment @@ -218,189 +237,193 @@ useLayoutEffect(() => { */} + {/* Section #2 */} + + + Site Id + + + + + {/* API Key */} + + + API Key + + + + + {/* Section #3 */} + + + backgroundQueueSecondsDelay + setBgQDelay(e)} + /> + + + + {/* Org Id */} + + + + backgroundQueueMinNumberOfTasks + + setBgQMinNumTasks(e)} + /> + + + - {/* Section #2 */} - - - Site Id - - - - - {/* API Key */} - - - API Key - - - - - {/* Section #3 */} - - - backgroundQueueSecondsDelay - setBgQDelay(e)} - /> - - - - {/* Org Id */} - - - backgroundQueueMinNumberOfTasks - setBgQMinNumTasks(e)} - /> - - - - - {/* Features Header */} - - Features - - - - Enable Push Notifications - toggleSwitch('Push')} - value={isPushEnabled} - /> - - - {/* CIO Track Screen */} - - - Track Screens - toggleSwitch('Screens')} - value={isTrackScreensEnabled} - /> - - + {/* Features Header */} + + Features + + + + Enable Push Notifications + toggleSwitch('Push')} + value={isPushEnabled} + /> + + + {/* CIO Track Screen */} + + + Track Screens + toggleSwitch('Screens')} + value={isTrackScreensEnabled} + /> + + - - - Track Device Attributes - toggleSwitch('DeviceAttr')} - value={isTrackDeviceAttributesEnabled} - /> - - - - - Debug mode - toggleSwitch('Debug')} - value={isDebugModeEnabled} - /> - - - - - - alertUserBeforeSaving()} title="SAVE"/> - Editing settings will require an app restart. + + + Track Device Attributes + toggleSwitch('DeviceAttr')} + value={isTrackDeviceAttributesEnabled} + /> + + + + + Debug mode + toggleSwitch('Debug')} + value={isDebugModeEnabled} + /> + + + + alertUserBeforeSaving()} title="SAVE" /> + + Editing settings will require an app restart. + + - ) -} + ); +}; const styles = StyleSheet.create({ - container: { - flex:1, - backgroundColor: "white", - }, - sectionView: { - flexDirection: 'row', - marginTop: 30 - }, - trackColor: { - false: "#32BD54", - true: "#32BD54" - }, - copyToClipboardButton:{ - alignContent: 'flex-end', - justifyContent: 'flex-end', - alignSelf:'flex-end', - height: 30, - width: 25 - }, - copyToClipboardImage: { - width: 20, - height: 20, + container: { + flex: 1, + backgroundColor: 'white', }, - rowView:{ - flexDirection: 'row', - paddingTop: 10 - }, - stackColumnView: { - flexDirection: 'row', - justifyContent:'space-between', - alignItems: 'stretch', - alignSelf: 'stretch', - width: '100%', - }, - textLabel:{ - fontSize: 14, - alignContent: 'flex-end', - justifyContent: 'flex-end', - alignSelf:'flex-end', - color: "#404040" - }, - headerView:{ - justifyContent:'space-around', - }, - textHeaderLabel: { - color: '#000', - fontSize: 18, - fontWeight: 'bold' - }, - innerContainer:{ - flex:1, - backgroundColor:'white', - padding: 20 - }, - input: { - flex: 1, - borderWidth: 1, - padding: 5, - marginLeft: 10, - backgroundColor: 'white', - borderColor: '#fff', - borderBottomColor: '#e6e6e6', - borderRadius: 10, - }, - settingsInfoText: { - alignSelf: 'center' - } -}) -export default SettingsScreen; \ No newline at end of file + sectionView: { + flexDirection: 'row', + marginTop: 30, + }, + trackColor: { + false: '#32BD54', + true: '#32BD54', + }, + copyToClipboardButton: { + alignContent: 'flex-end', + justifyContent: 'flex-end', + alignSelf: 'flex-end', + height: 30, + width: 25, + }, + copyToClipboardImage: { + width: 20, + height: 20, + }, + rowView: { + flexDirection: 'row', + paddingTop: 10, + }, + stackColumnView: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'stretch', + alignSelf: 'stretch', + width: '100%', + }, + textLabel: { + fontSize: 14, + alignContent: 'flex-end', + justifyContent: 'flex-end', + alignSelf: 'flex-end', + color: '#404040', + }, + headerView: { + justifyContent: 'space-around', + }, + textHeaderLabel: { + color: '#000', + fontSize: 18, + fontWeight: 'bold', + }, + innerContainer: { + flex: 1, + backgroundColor: 'white', + padding: 20, + }, + input: { + flex: 1, + borderWidth: 1, + padding: 5, + marginLeft: 10, + backgroundColor: 'white', + borderColor: '#fff', + borderBottomColor: '#e6e6e6', + borderRadius: 10, + }, + settingsInfoText: { + alignSelf: 'center', + }, +}); +export default SettingsScreen; diff --git a/Apps/APN/components/common/Button.js b/Apps/APN/components/common/Button.js index aef097a6..5f737ad8 100644 --- a/Apps/APN/components/common/Button.js +++ b/Apps/APN/components/common/Button.js @@ -1,43 +1,53 @@ -import React from 'react' -import { StyleSheet, Text, FlatList, View, Image, Button, ImageBackground, TouchableHighlight} from 'react-native'; +import React from 'react'; +import { + StyleSheet, + Text, + FlatList, + View, + Image, + Button, + ImageBackground, + TouchableHighlight, +} from 'react-native'; const ThemedButton = (props) => { return ( - - {props.title} - - - ) -} + underlayColor="#f194ff" + onPress={props.onPress} + > + {props.title} + + + ); +}; const styles = StyleSheet.create({ - container: { - alignItems: 'center', - }, - button: { - padding:10, - alignSelf:'center', - paddingBottom:10, - backgroundColor:'#3C437D', - borderRadius:10, - borderWidth: 1, - borderColor: '#fff', - marginTop: 20, - marginBottom: 10, - minWidth: '75%' - }, - text : { - color:'#fff', - textAlign:'center', - fontWeight: '600', - paddingLeft : 10, - fontSize: 17, - paddingRight : 10 - } -}) + container: { + alignItems: 'center', + }, + button: { + padding: 10, + alignSelf: 'center', + paddingBottom: 10, + backgroundColor: '#3C437D', + borderRadius: 10, + borderWidth: 1, + borderColor: '#fff', + marginTop: 20, + marginBottom: 10, + minWidth: '75%', + }, + text: { + color: '#fff', + textAlign: 'center', + fontWeight: '600', + paddingLeft: 10, + fontSize: 17, + paddingRight: 10, + }, +}); -export default ThemedButton; \ No newline at end of file +export default ThemedButton; diff --git a/Apps/APN/components/common/Text.js b/Apps/APN/components/common/Text.js index b1564ee8..9e52e1db 100644 --- a/Apps/APN/components/common/Text.js +++ b/Apps/APN/components/common/Text.js @@ -1,33 +1,25 @@ -import React from "react"; -import { Text, StyleSheet, View } from "react-native"; +import React from 'react'; +import { Text, StyleSheet, View } from 'react-native'; const SubHeaderText = (props) => { - return ( - - {props.label} - - ) -} + return {props.label}; +}; const SimpleText = (props) => { - return( - - {props.label} - - ) -} + return {props.label}; +}; const styles = StyleSheet.create({ - subHeaderText : { - padding : 20, - fontSize: 15, - fontWeight : 'bold' - }, - simpleText: { - fontSize: 15, - paddingLeft : 20, - paddingRight: 20 - } -}) + subHeaderText: { + padding: 20, + fontSize: 15, + fontWeight: 'bold', + }, + simpleText: { + fontSize: 15, + paddingLeft: 20, + paddingRight: 20, + }, +}); -export {SubHeaderText, SimpleText}; +export { SubHeaderText, SimpleText }; diff --git a/Apps/APN/env.sample.js b/Apps/APN/env.sample.js index c5b3acec..80945a00 100644 --- a/Apps/APN/env.sample.js +++ b/Apps/APN/env.sample.js @@ -1,7 +1,6 @@ const Env = { - siteId: "YourSiteId", - apiKey: "YourApiKey", -} + siteId: 'YourSiteId', + apiKey: 'YourApiKey', +}; - -export default Env; \ No newline at end of file +export default Env; diff --git a/Apps/APN/index.js b/Apps/APN/index.js index c0709b30..3931f3f1 100644 --- a/Apps/APN/index.js +++ b/Apps/APN/index.js @@ -1,9 +1,8 @@ import 'react-native-gesture-handler'; import { AppRegistry } from 'react-native'; import PushNotificationIOS from '@react-native-community/push-notification-ios'; -import PushNotification from "react-native-push-notification"; -import {name as appName} from './app.json'; +import PushNotification from 'react-native-push-notification'; +import { name as appName } from './app.json'; import App from './App'; - AppRegistry.registerComponent(appName, () => App); diff --git a/Apps/APN/manager/CioManager.js b/Apps/APN/manager/CioManager.js index abb40261..5d867ec2 100644 --- a/Apps/APN/manager/CioManager.js +++ b/Apps/APN/manager/CioManager.js @@ -1,34 +1,33 @@ -import {CustomerIO} from 'customerio-reactnative' +import { CustomerIO } from 'customerio-reactnative'; class CioManager { - - randomEvent() { - CustomerIO.track("RandomEvent") - } - - customEvent(name, data) { - CustomerIO.track(name, data) - } - - deviceAttributes(data) { - CustomerIO.setDeviceAttributes(data) - } - - profileAttributes(data) { - CustomerIO.setProfileAttributes(data) - } - - identifyUser(emailId, data) { - CustomerIO.identify(emailId, data) - } - - clearUserIdentity() { - CustomerIO.clearIdentify() - } - - initializeCio(env, config) { - CustomerIO.initialize(env, config) - } + randomEvent() { + CustomerIO.track('RandomEvent'); + } + + customEvent(name, data) { + CustomerIO.track(name, data); + } + + deviceAttributes(data) { + CustomerIO.setDeviceAttributes(data); + } + + profileAttributes(data) { + CustomerIO.setProfileAttributes(data); + } + + identifyUser(emailId, data) { + CustomerIO.identify(emailId, data); + } + + clearUserIdentity() { + CustomerIO.clearIdentify(); + } + + initializeCio(env, config) { + CustomerIO.initialize(env, config); + } } -export default CioManager \ No newline at end of file +export default CioManager; diff --git a/Apps/APN/manager/KeyValueStorage.js b/Apps/APN/manager/KeyValueStorage.js index 263e2c23..62daf3fd 100644 --- a/Apps/APN/manager/KeyValueStorage.js +++ b/Apps/APN/manager/KeyValueStorage.js @@ -1,106 +1,107 @@ import AsyncStorage from '@react-native-async-storage/async-storage'; -import Constants from './../util/StorageConstants' +import Constants from './../util/StorageConstants'; class CioKeyValueStorage { - async saveToStorage(key, value) { try { - await AsyncStorage.setItem(key, value) + await AsyncStorage.setItem(key, value); } catch (e) { - console.log(e) + console.log(e); } } async getFromStorage(key) { try { - const value = await AsyncStorage.getItem(key) - return value - } catch(e) { - console.log(e) + const value = await AsyncStorage.getItem(key); + return value; + } catch (e) { + console.log(e); } } // Tracking URL async saveTrackingUrl(value) { - this.saveToStorage(Constants.TRACKING_URL_KEY, value) + this.saveToStorage(Constants.TRACKING_URL_KEY, value); } - async getTrackingUrl(){ - return this.getFromStorage(Constants.TRACKING_URL_KEY) + async getTrackingUrl() { + return this.getFromStorage(Constants.TRACKING_URL_KEY); } // BGQ-DELAY async saveBGQSecondsDelay(value) { - this.saveToStorage(Constants.BGQ_SECONDS_DELAY, value) + this.saveToStorage(Constants.BGQ_SECONDS_DELAY, value); } - async getBGQSecondsDelay(){ - return this.getFromStorage(Constants.BGQ_SECONDS_DELAY) + async getBGQSecondsDelay() { + return this.getFromStorage(Constants.BGQ_SECONDS_DELAY); } // BGQ-MinTasks async saveBGQMinTasksInQueue(value) { - this.saveToStorage(Constants.BGQ_MIN_TASKS_IN_QUEUE, value) + this.saveToStorage(Constants.BGQ_MIN_TASKS_IN_QUEUE, value); } - async getBGQMinTasksInQueue(){ - return this.getFromStorage(Constants.BGQ_MIN_TASKS_IN_QUEUE) + async getBGQMinTasksInQueue() { + return this.getFromStorage(Constants.BGQ_MIN_TASKS_IN_QUEUE); } // Login Status async saveLoginStatus(value) { - this.saveToStorage(Constants.LOGIN_STATUS, JSON.stringify(value)) + this.saveToStorage(Constants.LOGIN_STATUS, JSON.stringify(value)); } async getLoginStatus(value) { - return this.getFromStorage(Constants.LOGIN_STATUS) + return this.getFromStorage(Constants.LOGIN_STATUS); } // Login details async saveLoginDetail(value) { - this.saveToStorage(Constants.LOGIN_DETAIL, JSON.stringify(value)) + this.saveToStorage(Constants.LOGIN_DETAIL, JSON.stringify(value)); } async getLoginDetail(value) { - return this.getFromStorage(Constants.LOGIN_DETAIL) - } + return this.getFromStorage(Constants.LOGIN_DETAIL); + } // Track Screen async saveScreenTrack(value) { - this.saveToStorage(Constants.SCREEN_TRACK_STATUS, JSON.stringify(value)) + this.saveToStorage(Constants.SCREEN_TRACK_STATUS, JSON.stringify(value)); } - async getScreenTrack(){ - return this.getFromStorage(Constants.SCREEN_TRACK_STATUS) + async getScreenTrack() { + return this.getFromStorage(Constants.SCREEN_TRACK_STATUS); } // Track device attributes async saveDeviceAttributesTrack(value) { - this.saveToStorage(Constants.TRACK_DEVICE_ATTRIBUTES_STATUS, JSON.stringify(value)) + this.saveToStorage( + Constants.TRACK_DEVICE_ATTRIBUTES_STATUS, + JSON.stringify(value) + ); } - async getDeviceAttributesTrack(){ - return this.getFromStorage(Constants.TRACK_DEVICE_ATTRIBUTES_STATUS) + async getDeviceAttributesTrack() { + return this.getFromStorage(Constants.TRACK_DEVICE_ATTRIBUTES_STATUS); } -// Debug mode -async saveDebugModeConfig(value) { - this.saveToStorage(Constants.DEBUG_MODE_STATUS, JSON.stringify(value)) -} + // Debug mode + async saveDebugModeConfig(value) { + this.saveToStorage(Constants.DEBUG_MODE_STATUS, JSON.stringify(value)); + } -async getDebugModeConfig(){ - return this.getFromStorage(Constants.DEBUG_MODE_STATUS) -} + async getDebugModeConfig() { + return this.getFromStorage(Constants.DEBUG_MODE_STATUS); + } // Push notifications async saveIsPushEnabledConfig(value) { - this.saveToStorage(Constants.PUSH_ENABLED_STATUS, JSON.stringify(value)) + this.saveToStorage(Constants.PUSH_ENABLED_STATUS, JSON.stringify(value)); } - - async getIsPushEnabledConfig(){ - return this.getFromStorage(Constants.PUSH_ENABLED_STATUS) + + async getIsPushEnabledConfig() { + return this.getFromStorage(Constants.PUSH_ENABLED_STATUS); } } - -export default CioKeyValueStorage; \ No newline at end of file +export default CioKeyValueStorage; diff --git a/Apps/APN/metro.config.js b/Apps/APN/metro.config.js index dfbf26dc..232262b2 100644 --- a/Apps/APN/metro.config.js +++ b/Apps/APN/metro.config.js @@ -3,7 +3,7 @@ const { getDefaultConfig } = require('expo/metro-config'); module.exports = getDefaultConfig(__dirname); -const path = require("path"); +const path = require('path'); // const watchFolders = [ // //Relative path to packages directory because I'm in yarn workpspaces // path.resolve(__dirname + "/../.."), @@ -20,4 +20,4 @@ module.exports = { }, }), }, -}; \ No newline at end of file +}; diff --git a/Apps/APN/util/DefaultConstants.js b/Apps/APN/util/DefaultConstants.js index fce99e62..d033e674 100644 --- a/Apps/APN/util/DefaultConstants.js +++ b/Apps/APN/util/DefaultConstants.js @@ -1,10 +1,9 @@ - const DefaultConstants = { - BGQ_SECONDS_DELAY: 30, - BGQ_MIN_TASKS_IN_QUEUE: 10, - TRACK_DEVICE_ATTRIBUTES_STATUS: true, - DEBUG_MODE_STATUS: true, - SCREEN_TRACK_STATUS: true -} + BGQ_SECONDS_DELAY: 30, + BGQ_MIN_TASKS_IN_QUEUE: 10, + TRACK_DEVICE_ATTRIBUTES_STATUS: true, + DEBUG_MODE_STATUS: true, + SCREEN_TRACK_STATUS: true, +}; - export default DefaultConstants; \ No newline at end of file +export default DefaultConstants; diff --git a/Apps/APN/util/StorageConstants.js b/Apps/APN/util/StorageConstants.js index 87a1279c..749ff8b1 100644 --- a/Apps/APN/util/StorageConstants.js +++ b/Apps/APN/util/StorageConstants.js @@ -1,14 +1,13 @@ - const Constants = { - TRACKING_URL_KEY: "tracking_url", - BGQ_SECONDS_DELAY: 'bgQSecondsDelay', - BGQ_MIN_TASKS_IN_QUEUE: 'bgQMinTasksInQueue', - LOGIN_STATUS : 'loginStatus', - LOGIN_DETAIL: 'loginDetail', - SCREEN_TRACK_STATUS: 'screen_track', - TRACK_DEVICE_ATTRIBUTES_STATUS: 'device_attributes_track', - DEBUG_MODE_STATUS: 'debug_mode', - PUSH_ENABLED_STATUS: 'push_enabled' - } + TRACKING_URL_KEY: 'tracking_url', + BGQ_SECONDS_DELAY: 'bgQSecondsDelay', + BGQ_MIN_TASKS_IN_QUEUE: 'bgQMinTasksInQueue', + LOGIN_STATUS: 'loginStatus', + LOGIN_DETAIL: 'loginDetail', + SCREEN_TRACK_STATUS: 'screen_track', + TRACK_DEVICE_ATTRIBUTES_STATUS: 'device_attributes_track', + DEBUG_MODE_STATUS: 'debug_mode', + PUSH_ENABLED_STATUS: 'push_enabled', +}; - export default Constants; \ No newline at end of file +export default Constants; diff --git a/package.json b/package.json index d22953dc..e75b0738 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "example": "yarn --cwd example", "pods": "cd example && pod-install --quiet", "bootstrap": "yarn example && yarn && yarn pods", - "postinstall": "node src/postInstall.js && npx lefthook install", + "postinstall": "node src/postInstall.js", "format": "npx prettier --write \"src/**/*.tsx\" && (npm run lint || true)" }, "keywords": [ @@ -60,7 +60,7 @@ "eslint-config-prettier": "^7.0.0", "eslint-plugin-prettier": "^3.1.3", "jest": "^26.0.1", - "lefthook": "^1.2.8", + "lefthook": "^1.4.1", "prettier": "^2.0.5", "react": "16.13.1", "react-native": "0.63.4", diff --git a/yarn.lock b/yarn.lock index a51f31c6..405ed893 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5419,59 +5419,59 @@ kleur@^3.0.3: resolved "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== -lefthook-darwin-arm64@1.2.8: - version "1.2.8" - resolved "https://registry.yarnpkg.com/lefthook-darwin-arm64/-/lefthook-darwin-arm64-1.2.8.tgz#14797478ea5d5ce78e61659d964eb4b69f16632c" - integrity sha512-4gmZpcPPDo9NQYwHdDAoPv0Ho0V1xa5GPGYOrpKzmgA4MogLMmtp2AUUQt8ekgfoUfiXn6Zh2Ww83J+kIW04Ww== +lefthook-darwin-arm64@1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/lefthook-darwin-arm64/-/lefthook-darwin-arm64-1.4.1.tgz#8c57fccfae3c71b0d2570755d46da96816c568a3" + integrity sha512-j3Egr/oNu8JKZDtwtKZrU+34c4DDNy8sKuagZrfFpmwhZEqSFUMxjxUC/J8QnX0Bc60Wo+UAUfv/Oe6g+s4QSA== -lefthook-darwin-x64@1.2.8: - version "1.2.8" - resolved "https://registry.yarnpkg.com/lefthook-darwin-x64/-/lefthook-darwin-x64-1.2.8.tgz#607617fd1185c42bc977ce2a2b8eef8741081f49" - integrity sha512-5QyHU2YyJmNpiorxXqKPYlhlYQSBjx+0DOLKOtd20aCQIZXQFMhgJUSe3s5WGNyxEzoVIzZ05rxBbsIqnNXliQ== +lefthook-darwin-x64@1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/lefthook-darwin-x64/-/lefthook-darwin-x64-1.4.1.tgz#063cb0d962c7f62f19142d59b7c194d8ac75e964" + integrity sha512-gGzltha7Fo3CDavDUF9l8VVcrMCb8Dm3x/Bax4+Pjs3ZUTTgIxZZe89ORYqVlet0egh9GUx/L20r8+kwdTDwAg== -lefthook-freebsd-arm64@1.2.8: - version "1.2.8" - resolved "https://registry.yarnpkg.com/lefthook-freebsd-arm64/-/lefthook-freebsd-arm64-1.2.8.tgz#0a85a839a5ebfd92bca1de845a6cde9347006773" - integrity sha512-LwCYN2B6nNIv+4LLFYMNbMJYUI3xvF6tN+y9gY13yanOVdbMcJDHTVFP4l0yEpeAy93UDzvGIPXo0RX99CEpRg== +lefthook-freebsd-arm64@1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/lefthook-freebsd-arm64/-/lefthook-freebsd-arm64-1.4.1.tgz#d0cf88ba05190fab38b80ec3bb25a6a8bced7551" + integrity sha512-OzpkXzOeRjTjXT+f+AjZxxBhaSA6QTqWMlrkgnFJuNZOVKT6bfgkusvpyC1KAYlKxlRGHnvfTRPAv3Ouub/vaw== -lefthook-freebsd-x64@1.2.8: - version "1.2.8" - resolved "https://registry.yarnpkg.com/lefthook-freebsd-x64/-/lefthook-freebsd-x64-1.2.8.tgz#a5d80738ae7bb5b10e00b442d0c3a477c8fc22ed" - integrity sha512-Jojivv39Ocp/Z78cagLdJkp2z//h01nCMNHYo5Hf2vBkL9oBDxSg3arJSc7C5h8tTk6WZG4zZgVHF+FF8RqTcQ== +lefthook-freebsd-x64@1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/lefthook-freebsd-x64/-/lefthook-freebsd-x64-1.4.1.tgz#c3914c6b10d0ca7771fb57933f236287b90e2878" + integrity sha512-6befhXE64XOyt1XLg5Wf1/rVMvwzOf0BaEvQoBXX8fn6/3q1e+86fcejUi4doMngeagpm03XWMqNiy592NqfZw== -lefthook-linux-arm64@1.2.8: - version "1.2.8" - resolved "https://registry.yarnpkg.com/lefthook-linux-arm64/-/lefthook-linux-arm64-1.2.8.tgz#4fbc9f4384c2273f2527856731685b9b021b20b1" - integrity sha512-KkOC56fpVQ6baZFZXr9ReMvSHDW8mClhAxSHM99UY2p7vBk63fP7SXvq0QBMVxtqZr8pzVV0fReuL4N47H3kMA== +lefthook-linux-arm64@1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/lefthook-linux-arm64/-/lefthook-linux-arm64-1.4.1.tgz#d0c511a59c495327eff5fd98864d629b57c50cea" + integrity sha512-j8p2BukrsFAC4fGQVqCFVE6CfwE7d21nh3WUMWqISk8qMO5+OTkdohZViPeOPk9sxxC05aXvFDgWDKW0VXs1og== -lefthook-linux-x64@1.2.8: - version "1.2.8" - resolved "https://registry.yarnpkg.com/lefthook-linux-x64/-/lefthook-linux-x64-1.2.8.tgz#96076a2869b7e8b31158cd072e53783a3fd3a701" - integrity sha512-iNAHyhNr3th9ESFDjEcXjVfl83QXP8422LRX+oQnr6WHQSZ+pn5FN7SptKovw7+M0WqvjBHyj4Pw7OXA+NZXLg== +lefthook-linux-x64@1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/lefthook-linux-x64/-/lefthook-linux-x64-1.4.1.tgz#be2696535b009cdaab4a897a06076db3c4da24ee" + integrity sha512-0cYddhIjT8FtrFB47rKLYi7FLmYRi3NRexpyj6FRiTWkN8Joz10MpCqFPnZOfZRPgUm4sg5HqoTdxiDmaYV2kQ== -lefthook-windows-arm64@1.2.8: - version "1.2.8" - resolved "https://registry.yarnpkg.com/lefthook-windows-arm64/-/lefthook-windows-arm64-1.2.8.tgz#62601e4f5f4fdd9964202e1ba0233d36c59be96c" - integrity sha512-BmIQ+M6jJUcT5QQyOaF8UvIK3vtk+a9XH/MQwgqZ8ou8T1vQR0aF7xcjHK/4wGtlwUP2+Qye9+n6xYvkwl/6+A== +lefthook-windows-arm64@1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/lefthook-windows-arm64/-/lefthook-windows-arm64-1.4.1.tgz#d8ec6020543541c4cebf0478bd1cff7075b2b419" + integrity sha512-jgY/m6+g9ofr+ePx0tUoo63ItunVBYamCY16wLnXVI6xyYmP5wEy83u0lnBS4wQ8zcH22YUCDrL8KtrQFfLsjg== -lefthook-windows-x64@1.2.8: - version "1.2.8" - resolved "https://registry.yarnpkg.com/lefthook-windows-x64/-/lefthook-windows-x64-1.2.8.tgz#28f6c6813607b4a967284359374bfb97d8c40b9f" - integrity sha512-7ONLOkd/Un/zEU9WdOHL0fgOy7WRdIMzHuk+TNwqzoAO8G/qaFSPfsIteN2GifZ0cDBSLGE8x5rfxRv2nUuzcA== +lefthook-windows-x64@1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/lefthook-windows-x64/-/lefthook-windows-x64-1.4.1.tgz#a91619b11481f7fa3a4697f1021e19672a60f290" + integrity sha512-lvTpayQkBmOp5czolntESM2uWRG0I5r0HkOnFfhGEaqEFm45sUjKZsxNj/EPQLAXlWlXqLe363UNcSnmUf/g3g== -lefthook@^1.2.8: - version "1.2.8" - resolved "https://registry.yarnpkg.com/lefthook/-/lefthook-1.2.8.tgz#917ef3d13bf8de12bcbdd6a1f6d52d1058e0baaa" - integrity sha512-dB6sA3SxMxUvZjUN+pjQrEapJppqERO8DJMdpJvDsymIIKJLQY/iG5H9bR/J4+kE+trho+wC8F+zsuuOhtlSxQ== +lefthook@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/lefthook/-/lefthook-1.4.1.tgz#d4cf5165c358902b09644ad404c58a3d5a2c42b2" + integrity sha512-05jULu8iGCOfUnONImG3MJOtmMG9W1ihlnWWDJ6vmmC6eZqtb4yFBw5Dt/fD0H3ZFeYa9Yb2quvaU3y88W5GCw== optionalDependencies: - lefthook-darwin-arm64 "1.2.8" - lefthook-darwin-x64 "1.2.8" - lefthook-freebsd-arm64 "1.2.8" - lefthook-freebsd-x64 "1.2.8" - lefthook-linux-arm64 "1.2.8" - lefthook-linux-x64 "1.2.8" - lefthook-windows-arm64 "1.2.8" - lefthook-windows-x64 "1.2.8" + lefthook-darwin-arm64 "1.4.1" + lefthook-darwin-x64 "1.4.1" + lefthook-freebsd-arm64 "1.4.1" + lefthook-freebsd-x64 "1.4.1" + lefthook-linux-arm64 "1.4.1" + lefthook-linux-x64 "1.4.1" + lefthook-windows-arm64 "1.4.1" + lefthook-windows-x64 "1.4.1" leven@^3.1.0: version "3.1.0"