From ec94255dea7f3addc87aacdeb021f44c525dc3e9 Mon Sep 17 00:00:00 2001
From: Paul Makles <paulmakles@gmail.com>
Date: Fri, 14 Dec 2018 20:23:15 +0000
Subject: [PATCH] Started organising, condensing bus arrivals into one entry.

---
 .gitlab-ci.yml    |   2 +-
 App.js            | 130 ++++++++++++-----------------------------
 app.json          |   4 +-
 package-lock.json | 145 ++++++++++++++++++++++++++++++++++++----------
 package.json      |   3 +-
 src/styles.js     |  83 ++++++++++++++++++++++++++
 6 files changed, 239 insertions(+), 128 deletions(-)
 create mode 100644 src/styles.js

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index b9eb57a..1e5be05 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -3,7 +3,7 @@ image: timbru31/node-alpine-git
 stages:
   - deploy
 before_script:
-  - npm ci
+  - npm i
 deploy:
   stage: deploy
   script:
diff --git a/App.js b/App.js
index d42ce3c..a271395 100644
--- a/App.js
+++ b/App.js
@@ -1,44 +1,10 @@
 import React, { Component } from 'react';
-import { ToastAndroid, Button, AsyncStorage, TextInput, ScrollView, StyleSheet, Text, View } from 'react-native';
+import { ToastAndroid, Button, AsyncStorage, TextInput, ScrollView, Text, View } from 'react-native';
 
 import moment, { relativeTimeThreshold, updateLocale } from 'moment';
 import Tabs from 'react-native-tabs';
-	
-const estyles = StyleSheet.create({
-	container: {
-		width: '100%',
-		padding: 4,
-	},
-	top: {
-		padding: 6,
-		display: 'flex',
-		flexDirection: 'row',
-	},
-	line: {
-		fontWeight: '900',
-		fontSize: 26,
-		textAlign: 'left',
-	},
-	destination: {
-		paddingLeft: 5,
-		fontSize: 18,
-	},
-	arrival: {
-		padding: 8,
-		fontSize: 14,
-		flex: 1,
-		textAlign: 'right',
-	},
-	header: {
-		backgroundColor: '#d3390a',
-		color: 'white',
-		fontWeight: '200',
-		textAlign: 'left',
-		fontSize: 24,
-		padding: 4,
-		paddingLeft: 8
-	}
-});
+
+import { styles, element_styles } from './src/styles';
 
 class BusArrival extends Component {
 	constructor(props) {
@@ -48,7 +14,8 @@ class BusArrival extends Component {
 			id: props.item.id,
 			line: props.item.line,
 			destination: props.item.destination,
-			arrival: time.fromNow()
+			arrival: time.fromNow(),
+			next: props.item.next
 		};
 	}
 
@@ -64,12 +31,23 @@ class BusArrival extends Component {
 
 	render() {
 		return (
-			<View style={[estyles.container, {backgroundColor: this.state.id % 2 ? '#fafafa' : '#fefefe'}]}>
-				<View style={estyles.top}>
-					<Text style={estyles.line}>{this.state.line}</Text>
-					<Text style={estyles.arrival}>{this.state.arrival}</Text>
+			<View style={[element_styles.container, {backgroundColor: this.state.id % 2 ? '#fafafa' : '#fefefe'}]}>
+				<View style={element_styles.top}>
+					<View>
+						<Text style={element_styles.line}>{this.state.line}</Text>
+						<Text style={element_styles.destination}>{this.state.destination}</Text>
+					</View>
+					<View style={{flex: 1, paddingTop: 3}}>
+						<Text style={element_styles.arrival}>{this.state.arrival}</Text>
+						{ this.state.next.length > 0 ?
+							<Text style={[element_styles.arrival, {fontSize: 11}]}>then {
+								this.state.next.map(i => {
+									return Math.max(Math.floor(moment.duration(moment(i).diff(moment())).asMinutes()), 1);
+							  	}).join(', ')
+							} min</Text>
+							: null }
+					</View>
 				</View>
-				<Text style={estyles.destination}>{this.state.destination}</Text>
 			</View>
 		);
 	}
@@ -165,7 +143,7 @@ class BusArrivals extends Component {
 		if (!this.state.visible) return null;
 		return (
 			<View>
-				<Text style={estyles.header}>{this.state.name}</Text>
+				<Text style={element_styles.header}>{this.state.name}</Text>
 				<Text style={styles.status}>Updated {this.state.updated}.</Text>
 				{Object.keys(this.state.data).map(i => {
           			return (<BusArrival item={this.state.data[i]} key={this.state.data[i].key} />);
@@ -233,8 +211,19 @@ class BusArrivals extends Component {
 				list.sort((a, b) => {
 					return new Date(a.arrival) > new Date(b.arrival);
 				});
+				let parse = {};
 				list.forEach((x, i) => {
-					list[i].id = i;
+					x.id = i;
+					if (parse[x.line + x.destination]) {
+						parse[x.line + x.destination].next.push(x.arrival);
+					} else {
+						x.next = [];
+						parse[x.line + x.destination] = x;
+					}
+				});
+				list = [];
+				Object.keys(parse).forEach(x => {
+					list.push(parse[x]);
 				});
 				!this.isCancelled && this.setState({
 					data: list,
@@ -327,8 +316,8 @@ class SearchEntry extends Component {
 
 	render() {
 		return (
-			<View style={[estyles.container, {backgroundColor: this.state.i % 2 ? '#fafafa' : '#fefefe'}]}>
-				<Text style={estyles.destination}>{this.state.name}</Text>
+			<View style={[element_styles.container, {backgroundColor: this.state.i % 2 ? '#fafafa' : '#fefefe'}]}>
+				<Text style={element_styles.destination}>{this.state.name}</Text>
 				<Button
 					onPress={() => {
 						let d = {id: this.state.id, name: this.state.name};
@@ -435,49 +424,4 @@ export default class App extends Component {
 			</View>
 		);
 	}
-}
-	
-const styles = StyleSheet.create({
-	container: {
-		display: 'flex',
-		flex: 1,
-		flexDirection: 'column',
-		backgroundColor: '#fff',
-		alignItems: 'center',
-	},
-	header: {
-		paddingLeft: 22,
-		paddingTop: 28,
-		paddingBottom: 8,
-		width: '100%',
-		backgroundColor: '#d3390a',
-	},
-	header_addon: {
-		paddingLeft: 22,
-		paddingBottom: 8,
-		width: '100%',
-		backgroundColor: '#d3390a',
-	},
-	child: {
-		width: '100%',
-		flex: 1,
-	},
-	title: {
-		fontSize: 22,
-		color: 'white',
-		paddingBottom: 8,
-	},
-	list: {
-		width: '100%',
-		maxHeight: '100%',
-	},
-	status: {
-		backgroundColor: '#d3390a',
-		color: 'white',
-		padding: 2,
-		paddingLeft: 24
-	},
-	button: {
-		padding: 6
-	}
-});
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/app.json b/app.json
index 2a13c24..bbbd460 100644
--- a/app.json
+++ b/app.json
@@ -6,8 +6,8 @@
     "privacy": "public",
     "sdkVersion": "31.0.0",
     "platforms": ["ios", "android"],
-    "version": "1.0.1",
-    "orientation": "portrait",
+    "version": "1.0.2",
+    "orientation": "default",
     "icon": "./assets/icon.png",
     "splash": {
       "image": "./assets/splash.png",
diff --git a/package-lock.json b/package-lock.json
index 74a5b62..2f8d35b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,5 +1,5 @@
 {
-  "name": "empty-project-template",
+  "name": "bustimes",
   "requires": true,
   "lockfileVersion": 1,
   "dependencies": {
@@ -1912,6 +1912,19 @@
         "resolve": "^1.4.0"
       }
     },
+    "babel-plugin-react-transform": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/babel-plugin-react-transform/-/babel-plugin-react-transform-2.0.2.tgz",
+      "integrity": "sha1-UVu/qZaJOYEULZCx+bFjXeKZUQk=",
+      "requires": {
+        "lodash": "^4.6.1"
+      }
+    },
+    "babel-plugin-syntax-async-functions": {
+      "version": "6.13.0",
+      "resolved": "http://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz",
+      "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU="
+    },
     "babel-plugin-syntax-class-properties": {
       "version": "6.13.0",
       "resolved": "http://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz",
@@ -2118,6 +2131,14 @@
         "babel-runtime": "^6.22.0"
       }
     },
+    "babel-plugin-transform-object-assign": {
+      "version": "6.22.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-assign/-/babel-plugin-transform-object-assign-6.22.0.tgz",
+      "integrity": "sha1-+Z0vZvGgsNSY40bFNZaEdAyqILo=",
+      "requires": {
+        "babel-runtime": "^6.22.0"
+      }
+    },
     "babel-plugin-transform-object-rest-spread": {
       "version": "6.26.0",
       "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz",
@@ -2145,6 +2166,35 @@
         "babel-runtime": "^6.22.0"
       }
     },
+    "babel-plugin-transform-react-jsx-source": {
+      "version": "6.22.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz",
+      "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=",
+      "requires": {
+        "babel-plugin-syntax-jsx": "^6.8.0",
+        "babel-runtime": "^6.22.0"
+      }
+    },
+    "babel-plugin-transform-regenerator": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz",
+      "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=",
+      "requires": {
+        "regenerator-transform": "^0.10.0"
+      },
+      "dependencies": {
+        "regenerator-transform": {
+          "version": "0.10.1",
+          "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz",
+          "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==",
+          "requires": {
+            "babel-runtime": "^6.18.0",
+            "babel-types": "^6.19.0",
+            "private": "^0.1.6"
+          }
+        }
+      }
+    },
     "babel-plugin-transform-strict-mode": {
       "version": "6.24.1",
       "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz",
@@ -2224,6 +2274,42 @@
         "babel-plugin-transform-flow-strip-types": "^6.22.0"
       }
     },
+    "babel-preset-react-native": {
+      "version": "1.9.0",
+      "resolved": "http://registry.npmjs.org/babel-preset-react-native/-/babel-preset-react-native-1.9.0.tgz",
+      "integrity": "sha1-A1/AbGX08qAtAzahALLaFC822rE=",
+      "requires": {
+        "babel-plugin-check-es2015-constants": "^6.5.0",
+        "babel-plugin-react-transform": "2.0.2",
+        "babel-plugin-syntax-async-functions": "^6.5.0",
+        "babel-plugin-syntax-class-properties": "^6.5.0",
+        "babel-plugin-syntax-flow": "^6.5.0",
+        "babel-plugin-syntax-jsx": "^6.5.0",
+        "babel-plugin-syntax-trailing-function-commas": "^6.5.0",
+        "babel-plugin-transform-class-properties": "^6.5.0",
+        "babel-plugin-transform-es2015-arrow-functions": "^6.5.0",
+        "babel-plugin-transform-es2015-block-scoping": "^6.5.0",
+        "babel-plugin-transform-es2015-classes": "^6.5.0",
+        "babel-plugin-transform-es2015-computed-properties": "^6.5.0",
+        "babel-plugin-transform-es2015-destructuring": "^6.5.0",
+        "babel-plugin-transform-es2015-for-of": "^6.5.0",
+        "babel-plugin-transform-es2015-function-name": "^6.5.0",
+        "babel-plugin-transform-es2015-literals": "^6.5.0",
+        "babel-plugin-transform-es2015-modules-commonjs": "^6.5.0",
+        "babel-plugin-transform-es2015-parameters": "^6.5.0",
+        "babel-plugin-transform-es2015-shorthand-properties": "^6.5.0",
+        "babel-plugin-transform-es2015-spread": "^6.5.0",
+        "babel-plugin-transform-es2015-template-literals": "^6.5.0",
+        "babel-plugin-transform-flow-strip-types": "^6.5.0",
+        "babel-plugin-transform-object-assign": "^6.5.0",
+        "babel-plugin-transform-object-rest-spread": "^6.5.0",
+        "babel-plugin-transform-react-display-name": "^6.5.0",
+        "babel-plugin-transform-react-jsx": "^6.5.0",
+        "babel-plugin-transform-react-jsx-source": "^6.5.0",
+        "babel-plugin-transform-regenerator": "^6.5.0",
+        "react-transform-hmr": "^1.0.4"
+      }
+    },
     "babel-register": {
       "version": "6.26.0",
       "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz",
@@ -3464,6 +3550,7 @@
         "qs": "^6.5.0",
         "react-native-branch": "2.2.5",
         "react-native-gesture-handler": "1.0.8",
+        "react-native-maps": "github:expo/react-native-maps#cb9d9ec23d4d176bddd6d465a583462f9c1056a0",
         "react-native-reanimated": "1.0.0-alpha.10",
         "react-native-screens": "1.0.0-alpha.15",
         "react-native-svg": "8.0.8",
@@ -3471,6 +3558,16 @@
         "serialize-error": "^2.1.0",
         "uuid-js": "^0.7.5",
         "whatwg-fetch": "^2.0.4"
+      },
+      "dependencies": {
+        "react-native-maps": {
+          "version": "github:expo/react-native-maps#cb9d9ec23d4d176bddd6d465a583462f9c1056a0",
+          "from": "github:expo/react-native-maps#v0.22.0-exp.0",
+          "requires": {
+            "babel-plugin-module-resolver": "^3.1.0",
+            "babel-preset-react-native": "1.9.0"
+          }
+        }
       }
     },
     "expo-ads-admob": {
@@ -4323,8 +4420,7 @@
         },
         "ansi-regex": {
           "version": "2.1.1",
-          "bundled": true,
-          "optional": true
+          "bundled": true
         },
         "aproba": {
           "version": "1.2.0",
@@ -4342,13 +4438,11 @@
         },
         "balanced-match": {
           "version": "1.0.0",
-          "bundled": true,
-          "optional": true
+          "bundled": true
         },
         "brace-expansion": {
           "version": "1.1.11",
           "bundled": true,
-          "optional": true,
           "requires": {
             "balanced-match": "^1.0.0",
             "concat-map": "0.0.1"
@@ -4361,18 +4455,15 @@
         },
         "code-point-at": {
           "version": "1.1.0",
-          "bundled": true,
-          "optional": true
+          "bundled": true
         },
         "concat-map": {
           "version": "0.0.1",
-          "bundled": true,
-          "optional": true
+          "bundled": true
         },
         "console-control-strings": {
           "version": "1.1.0",
-          "bundled": true,
-          "optional": true
+          "bundled": true
         },
         "core-util-is": {
           "version": "1.0.2",
@@ -4475,8 +4566,7 @@
         },
         "inherits": {
           "version": "2.0.3",
-          "bundled": true,
-          "optional": true
+          "bundled": true
         },
         "ini": {
           "version": "1.3.5",
@@ -4486,7 +4576,6 @@
         "is-fullwidth-code-point": {
           "version": "1.0.0",
           "bundled": true,
-          "optional": true,
           "requires": {
             "number-is-nan": "^1.0.0"
           }
@@ -4499,20 +4588,17 @@
         "minimatch": {
           "version": "3.0.4",
           "bundled": true,
-          "optional": true,
           "requires": {
             "brace-expansion": "^1.1.7"
           }
         },
         "minimist": {
           "version": "0.0.8",
-          "bundled": true,
-          "optional": true
+          "bundled": true
         },
         "minipass": {
           "version": "2.2.4",
           "bundled": true,
-          "optional": true,
           "requires": {
             "safe-buffer": "^5.1.1",
             "yallist": "^3.0.0"
@@ -4529,7 +4615,6 @@
         "mkdirp": {
           "version": "0.5.1",
           "bundled": true,
-          "optional": true,
           "requires": {
             "minimist": "0.0.8"
           }
@@ -4602,8 +4687,7 @@
         },
         "number-is-nan": {
           "version": "1.0.1",
-          "bundled": true,
-          "optional": true
+          "bundled": true
         },
         "object-assign": {
           "version": "4.1.1",
@@ -4613,7 +4697,6 @@
         "once": {
           "version": "1.4.0",
           "bundled": true,
-          "optional": true,
           "requires": {
             "wrappy": "1"
           }
@@ -4689,8 +4772,7 @@
         },
         "safe-buffer": {
           "version": "5.1.1",
-          "bundled": true,
-          "optional": true
+          "bundled": true
         },
         "safer-buffer": {
           "version": "2.1.2",
@@ -4720,7 +4802,6 @@
         "string-width": {
           "version": "1.0.2",
           "bundled": true,
-          "optional": true,
           "requires": {
             "code-point-at": "^1.0.0",
             "is-fullwidth-code-point": "^1.0.0",
@@ -4738,7 +4819,6 @@
         "strip-ansi": {
           "version": "3.0.1",
           "bundled": true,
-          "optional": true,
           "requires": {
             "ansi-regex": "^2.0.0"
           }
@@ -4777,13 +4857,11 @@
         },
         "wrappy": {
           "version": "1.0.2",
-          "bundled": true,
-          "optional": true
+          "bundled": true
         },
         "yallist": {
           "version": "3.0.2",
-          "bundled": true,
-          "optional": true
+          "bundled": true
         }
       }
     },
@@ -7785,6 +7863,11 @@
         "prop-types": "^15.5.10"
       }
     },
+    "react-native-maps": {
+      "version": "0.22.1",
+      "resolved": "https://registry.npmjs.org/react-native-maps/-/react-native-maps-0.22.1.tgz",
+      "integrity": "sha512-JjBpAXjzZY8AW4HTcAZxX+cGk6e6i+J5Vd//DViMUe0bRkKKv92ds1W9rqZ+o9PhUqdP++3DvKv0jrB05icqKA=="
+    },
     "react-native-reanimated": {
       "version": "1.0.0-alpha.10",
       "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-1.0.0-alpha.10.tgz",
diff --git a/package.json b/package.json
index 4357305..ce83b29 100644
--- a/package.json
+++ b/package.json
@@ -1,5 +1,5 @@
 {
-  "name": "empty-project-template",
+  "name": "bustimes",
   "main": "node_modules/expo/AppEntry.js",
   "private": true,
   "scripts": {
@@ -14,6 +14,7 @@
     "moment": "^2.22.2",
     "react": "16.5.0",
     "react-native": "https://github.com/expo/react-native/archive/sdk-31.0.0.tar.gz",
+    "react-native-maps": "^0.22.1",
     "react-native-tabs": "^1.0.9"
   },
   "devDependencies": {
diff --git a/src/styles.js b/src/styles.js
new file mode 100644
index 0000000..17021d7
--- /dev/null
+++ b/src/styles.js
@@ -0,0 +1,83 @@
+import { StyleSheet } from 'react-native';
+
+const element_styles = StyleSheet.create({
+	container: {
+		width: '100%',
+		padding: 4,
+	},
+	top: {
+		padding: 6,
+		display: 'flex',
+		flexDirection: 'row',
+	},
+	line: {
+		fontWeight: '900',
+		fontSize: 26,
+		textAlign: 'left',
+	},
+	destination: {
+		paddingLeft: 5,
+		fontSize: 18,
+	},
+	arrival: {
+		padding: 4,
+		fontSize: 14,
+		textAlign: 'right',
+	},
+	header: {
+		backgroundColor: '#d3390a',
+		color: 'white',
+		fontWeight: '200',
+		textAlign: 'left',
+		fontSize: 24,
+		padding: 4,
+		paddingLeft: 8
+	}
+});
+	
+const styles = StyleSheet.create({
+	container: {
+		display: 'flex',
+		flex: 1,
+		flexDirection: 'column',
+		backgroundColor: '#fff',
+		alignItems: 'center',
+	},
+	header: {
+		paddingLeft: 22,
+		paddingTop: 28,
+		paddingBottom: 8,
+		width: '100%',
+		backgroundColor: '#d3390a',
+	},
+	header_addon: {
+		paddingLeft: 22,
+		paddingBottom: 8,
+		width: '100%',
+		backgroundColor: '#d3390a',
+	},
+	child: {
+		width: '100%',
+		flex: 1,
+	},
+	title: {
+		fontSize: 22,
+		color: 'white',
+		paddingBottom: 8,
+	},
+	list: {
+		width: '100%',
+		maxHeight: '100%',
+	},
+	status: {
+		backgroundColor: '#d3390a',
+		color: 'white',
+		padding: 2,
+		paddingLeft: 24
+	},
+	button: {
+		padding: 6
+	}
+});
+
+module.exports = { element_styles, styles };
\ No newline at end of file
-- 
GitLab