diff --git a/android/app/build.gradle b/android/app/build.gradle
index a8e504e4dd..845ac5a0af 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -192,6 +192,7 @@ android {
}
dependencies {
+ implementation project(':react-native-svg')
implementation project(':react-native-webview')
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "com.facebook.react:react-native:+" // From node_modules
diff --git a/android/app/src/main/java/edu/mit/privatekit/MainApplication.java b/android/app/src/main/java/edu/mit/privatekit/MainApplication.java
index 64e6b1d056..2430861f84 100644
--- a/android/app/src/main/java/edu/mit/privatekit/MainApplication.java
+++ b/android/app/src/main/java/edu/mit/privatekit/MainApplication.java
@@ -4,6 +4,7 @@
import android.content.Context;
import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
+import com.horcrux.svg.SvgPackage;
import com.reactnativecommunity.webview.RNCWebViewPackage;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
diff --git a/android/settings.gradle b/android/settings.gradle
index 5efc6884fa..75f01d285e 100644
--- a/android/settings.gradle
+++ b/android/settings.gradle
@@ -1,4 +1,6 @@
rootProject.name = 'PrivateKit'
+include ':react-native-svg'
+project(':react-native-svg').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-svg/android')
include ':react-native-fs'
project(':react-native-fs').projectDir = new File(settingsDir, '../node_modules/react-native-fs/android')
include ':react-native-zip-archive'
diff --git a/app/Entry.js b/app/Entry.js
index 818f2ce272..1760e3fd5f 100644
--- a/app/Entry.js
+++ b/app/Entry.js
@@ -10,6 +10,7 @@ import ExportScreen from './views/Export';
import ImportScreen from './views/Import';
import OverlapScreen from './views/Overlap';
import LicencesScreen from './views/Licenses';
+import NotificationScreen from './views/Notification';
import Slider from './views/welcomeScreens/Slider';
import { GetStoreData } from './helpers/General';
import SettingsScreen from './views/Settings';
@@ -94,7 +95,12 @@ class Entry extends Component {
options={{ headerShown: false }}
/>
+
diff --git a/app/locales/en/index.js b/app/locales/en/index.js
index 4cba49d83d..8e4028faaf 100644
--- a/app/locales/en/index.js
+++ b/app/locales/en/index.js
@@ -4,12 +4,14 @@ import importFile from './import.json';
import exportFile from './exportscreen.json';
import licensesFile from './licensesscreen.json';
import overlapFile from './overlap.json';
+import notificationFile from './notification.json';
export default {
- ...intro,
- ...locationTracking,
- ...importFile,
- ...exportFile,
- ...overlapFile,
- ...licensesFile,
+ ...intro,
+ ...locationTracking,
+ ...importFile,
+ ...exportFile,
+ ...overlapFile,
+ ...licensesFile,
+ ...notificationFile,
};
diff --git a/app/locales/en/notification.json b/app/locales/en/notification.json
new file mode 100644
index 0000000000..750c061e94
--- /dev/null
+++ b/app/locales/en/notification.json
@@ -0,0 +1,7 @@
+{
+ "notification_main_text": "Check your Intersection day wise",
+ "notification_title": "Analyze your intersection",
+ "notification_data_not_available": "\n\nYou do not have any trails downloaded!\n\n",
+ "notification_warning_text": "You can press the following button to generate random intersections.\nWARNING: These are simulated intersections not real",
+ "notification_random_data_button": "Press this button to generate random data",
+}
\ No newline at end of file
diff --git a/app/views/Notification.js b/app/views/Notification.js
new file mode 100644
index 0000000000..b9008f51f1
--- /dev/null
+++ b/app/views/Notification.js
@@ -0,0 +1,289 @@
+import React, { Component } from 'react';
+import {
+ SafeAreaView,
+ StyleSheet,
+ View,
+ Text,
+ Platform,
+ Image,
+ Dimensions,
+ TouchableOpacity,
+ BackHandler,
+ ScrollView,
+} from 'react-native';
+import { WebView } from 'react-native-webview';
+import packageJson from '../../package.json';
+
+import colors from '../constants/colors';
+import backArrow from './../assets/images/backArrow.png';
+import languages from './../locales/languages';
+import AsyncStorage from '@react-native-community/async-storage';
+import { GetStoreData, SetStoreData } from '../helpers/General';
+import {
+ VictoryBar,
+ VictoryAxis,
+ VictoryChart,
+ VictoryTooltip,
+} from 'victory-native';
+
+const width = Dimensions.get('window').width;
+const height = Dimensions.get('window').height;
+var using_random_intersections = false;
+
+class NotificationScreen extends Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ data: [],
+ };
+ this.getInitialState();
+ }
+
+ backToMain() {
+ this.resetState();
+ this.props.navigation.navigate('LocationTrackingScreen', {});
+ }
+
+ handleBackPress = () => {
+ this.resetState();
+ this.props.navigation.navigate('LocationTrackingScreen', {});
+ return true;
+ };
+
+ componentDidMount() {
+ this.refreshState();
+ BackHandler.addEventListener('hardwareBackPress', this.handleBackPress);
+ }
+
+ componentWillUnmount() {
+ BackHandler.removeEventListener('hardwareBackPress', this.handleBackPress);
+ }
+
+ refreshState() {
+ this.getInitialState();
+ }
+
+ resetState() {
+ if (using_random_intersections === true) {
+ using_random_intersections = false;
+ AsyncStorage.removeItem('CROSSED_PATHS');
+ console.log('deleting random intersection data');
+ this.setState({ dataAvailable: false });
+ }
+ }
+
+ generate_random_intersections(length = 28) {
+ using_random_intersections = true;
+ var dayBin = [];
+ for (var i = 0; i < length; i++) {
+ // Random Integer between 0-99
+ const intersections = Math.floor(Math.random() * 100);
+ dayBin.push(intersections);
+ }
+ SetStoreData('CROSSED_PATHS', dayBin);
+ this.refreshState();
+ }
+
+ getInitialState = async () => {
+ GetStoreData('CROSSED_PATHS').then(dayBin => {
+ console.log(dayBin);
+ if (dayBin === null) {
+ this.setState({ dataAvailable: false });
+ console.log("Can't found Crossed Paths");
+ } else {
+ var crossed_path_data = [];
+ console.log('Found Crossed Paths');
+ this.setState({ dataAvailable: true });
+ dayBinParsed = JSON.parse(dayBin);
+ for (var i = 0; i < dayBinParsed.length; i++) {
+ const val = dayBinParsed[i];
+ data = { x: i, y: val, fill: this.colorfill(val) };
+ crossed_path_data.push(data);
+ }
+ this.setState({ data: crossed_path_data });
+ }
+ });
+ };
+
+ colorfill(data) {
+ var color = 'green';
+ if (data > 20) {
+ color = 'yellow';
+ }
+ if (data > 50) {
+ color = 'orange';
+ }
+ if (data > 80) {
+ color = 'red';
+ }
+ return color;
+ }
+
+ render() {
+ return (
+
+
+ this.backToMain()}>
+
+
+
+ {languages.t('label.private_kit')}
+
+
+
+
+
+ {languages.t('label.notification_title')}
+
+ {this.state.dataAvailable ? (
+ <>
+
+
+
+ datum.fill,
+ },
+ }}
+ data={this.state.data}
+ />
+
+
+ {languages.t('label.notification_main_text')}
+
+
+ {this.state.data.map(data => (
+
+
+ {'Day ' +
+ data.x +
+ ': Number of Intersections ' +
+ data.y}
+
+
+ ))}
+
+ >
+ ) : (
+ <>
+
+ {languages.t('label.notification_data_not_available')}
+
+
+ {languages.t('label.notification_warning_text')}
+
+ this.generate_random_intersections()}>
+
+ {languages.t('label.notification_random_data_button')}
+
+
+ >
+ )}
+
+
+ );
+ }
+}
+
+const styles = StyleSheet.create({
+ // Container covers the entire screen
+ container: {
+ flex: 1,
+ flexDirection: 'column',
+ color: colors.PRIMARY_TEXT,
+ backgroundColor: colors.WHITE,
+ },
+ main: {
+ flex: 1,
+ flexDirection: 'column',
+ textAlignVertical: 'top',
+ alignItems: 'center',
+ padding: 20,
+ width: '96%',
+ alignSelf: 'center',
+ },
+
+ contentContainer: {
+ paddingVertical: 20,
+ },
+ row: {
+ flex: 1,
+ flexDirection: 'row',
+ color: colors.PRIMARY_TEXT,
+ backgroundColor: colors.WHITE,
+ },
+ valueName: {
+ fontSize: 20,
+ fontWeight: '800',
+ },
+ value: {
+ fontSize: 20,
+ fontWeight: '200',
+ },
+ buttonTouchable: {
+ borderRadius: 12,
+ backgroundColor: '#665eff',
+ height: 52,
+ alignSelf: 'center',
+ width: width * 0.7866,
+ marginTop: 7,
+ justifyContent: 'center',
+ },
+ buttonText: {
+ fontFamily: 'OpenSans-Bold',
+ fontSize: 14,
+ lineHeight: 19,
+ letterSpacing: 0,
+ textAlign: 'center',
+ color: '#ffffff',
+ },
+ mainText: {
+ fontSize: 18,
+ lineHeight: 24,
+ fontWeight: '400',
+ textAlignVertical: 'center',
+ },
+ smallText: {
+ fontSize: 10,
+ lineHeight: 24,
+ fontWeight: '400',
+ textAlignVertical: 'center',
+ padding: 20,
+ },
+ headerTitle: {
+ fontSize: 24,
+ fontFamily: 'OpenSans-Bold',
+ },
+ headerContainer: {
+ flexDirection: 'row',
+ height: 60,
+ borderBottomWidth: 1,
+ borderBottomColor: 'rgba(189, 195, 199,0.6)',
+ alignItems: 'center',
+ },
+ backArrowTouchable: {
+ width: 60,
+ height: 60,
+ paddingTop: 21,
+ paddingLeft: 20,
+ },
+ backArrow: {
+ height: 18,
+ width: 18.48,
+ },
+ sectionDescription: {
+ fontSize: 16,
+ lineHeight: 24,
+ marginTop: 12,
+ overflow: 'scroll',
+ fontFamily: 'OpenSans-Regular',
+ },
+});
+
+export default NotificationScreen;
diff --git a/ios/Podfile b/ios/Podfile
index ffa7c365c8..5389fcb1fb 100644
--- a/ios/Podfile
+++ b/ios/Podfile
@@ -42,6 +42,8 @@ target 'PrivateKit' do
pod 'GoogleMaps'
pod 'Google-Maps-iOS-Utils'
+ pod 'RNSVG', :path => '../node_modules/react-native-svg'
+
target 'PrivateKitTests' do
inherit! :search_paths
# Pods for testing
diff --git a/package.json b/package.json
index ee07dc926f..1653402c68 100644
--- a/package.json
+++ b/package.json
@@ -10,7 +10,10 @@
"test": "jest test"
},
"lint-staged": {
- "*.js": ["prettier --write", "git add --force"]
+ "*.js": [
+ "prettier --write",
+ "git add --force"
+ ]
},
"husky": {
"hooks": {
@@ -53,10 +56,12 @@
"react-native-safe-area-context": "0.6.0",
"react-native-screens": "2.0.0-alpha.12",
"react-native-share": "^3.1.0",
+ "react-native-svg": "^12.0.3",
"react-native-uuid-generator": "^6.1.1",
"react-native-webview": "^8.1.2",
"react-native-zip-archive": "^5.0.1",
- "rn-fetch-blob": "^0.12.0"
+ "rn-fetch-blob": "^0.12.0",
+ "victory-native": "^34.1.0"
},
"devDependencies": {
"@babel/core": "^7.8.6",