From 0861b6875ce2083951cdf94b85de254f669d8451 Mon Sep 17 00:00:00 2001 From: Paul Makles <paulmakles@gmail.com> Date: Mon, 17 Dec 2018 20:32:38 +0000 Subject: [PATCH] Restructure project --- App.js | 397 +----------------------------------------------- app.json | 2 +- src/Arrivals.js | 195 ++++++++++++++++++++++++ src/Request.js | 66 ++++++++ src/Search.js | 98 ++++++++++++ src/Tabs.js | 44 ++++++ src/styles.js | 24 +-- 7 files changed, 419 insertions(+), 407 deletions(-) create mode 100644 src/Arrivals.js create mode 100644 src/Request.js create mode 100644 src/Search.js create mode 100644 src/Tabs.js diff --git a/App.js b/App.js index a271395..8b5bfce 100644 --- a/App.js +++ b/App.js @@ -1,400 +1,9 @@ import React, { Component } from 'react'; -import { ToastAndroid, Button, AsyncStorage, TextInput, ScrollView, Text, View } from 'react-native'; +import { Text, View } from 'react-native'; -import moment, { relativeTimeThreshold, updateLocale } from 'moment'; import Tabs from 'react-native-tabs'; - -import { styles, element_styles } from './src/styles'; - -class BusArrival extends Component { - constructor(props) { - super(props); - let time = moment(props.item.arrival); - this.state = { - id: props.item.id, - line: props.item.line, - destination: props.item.destination, - arrival: time.fromNow(), - next: props.item.next - }; - } - - componentDidMount() { - this.updateInterval = setInterval(() => { - this.setState({arrival: moment(this.props.item.arrival).fromNow()}); - }, 1e3); - } - - componentWillUnmount() { - clearInterval(this.updateInterval); - } - - render() { - return ( - <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> - </View> - ); - } -} - -let cache = {}; -const request = { - bus: { - stop: id => { - return new Promise((resolve, reject) => { - let i = "bus_stop_" + id; - if (cache[i]) { - if (cache[i].expires > +new Date()) { - return resolve(cache[i].data); - } - } - fetch('https://api.tfl.gov.uk/StopPoint/' + id + '/arrivals') - .then(response => response.json()) - .then(data => { - let d = new Date(); - d.setSeconds(d.getSeconds() + 20); - data.updated = new Date(); - cache[i] = { - data, - expires: +d - }; - resolve(data); - }) - .catch(reject); - }); - } - }, - search: query => { - return new Promise((resolve, reject) => { - // avoid stopType = NaptanRailEntrance - // if [NaptanOnstreetBusCoachStopCluster, NaptanOnstreetBusCoachStopPair] get child and process - // add NaptanPublicBusCoachTram [check indicator] = "e.g. Stop Y" - fetch('https://api.tfl.gov.uk/StopPoint/Search/' + query) - .then(response => response.json()) - .then(source => { - let search = []; - source.matches.forEach(res => { - search.push(res.id); - }); - fetch('https://api.tfl.gov.uk/StopPoint/' + search.splice(0, 20).join(',')) - .then(response => response.json()) - .then(source => { - let data = []; - let process = (x, name) => { - if (['NaptanOnstreetBusCoachStopCluster', 'NaptanOnstreetBusCoachStopPair'].indexOf(x.stopType) > -1) { - x.children.forEach(y => process(y)); - } else if (x.stopType == 'NaptanPublicBusCoachTram') { - let name = x.commonName; - if (x.indicator) { - name += ` [${x.indicator}]` - } - data.push({ - id: x.id, - name, - //modes: res.modes, - }); - } - }; - if (search.length > 1) { - source.forEach(res => { - process(res); - }); - } else { - process(source); - } - resolve(data); - }) - .catch(reject); - }) - .catch(reject); - }); - } -}; - -class BusArrivals extends Component { - constructor(props) { - super(props); - this.state = { - name: props.name, - id: props.id, - data: [], - updated: 'never', - visible: true, - }; - } - - render() { - if (!this.state.visible) return null; - return ( - <View> - <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} />); - })} - <View style={styles.button}> - <Button - onPress={() => { - AsyncStorage.getItem('myStops').then(x => { - let arr = JSON.parse(x); - let j = -1; - for (let i=0;i<arr.length;i++) { - if (arr[i].id == this.state.id) j = i; - } - if (j > -1) { - arr.splice(j, 1); - AsyncStorage.setItem('myStops', JSON.stringify(arr)).then(() => { - !this.isCancelled && this.setState({visible: false}); - ToastAndroid.show('Removed stop!', ToastAndroid.SHORT); - }); - } else { - ToastAndroid.show('Could not remove stop!', ToastAndroid.SHORT); - } - }).catch(() => { - ToastAndroid.show('Encountered an error!', ToastAndroid.SHORT); - }); - }} - title="Remove this stop" - color='#d3390a' - /> - </View> - </View> - ); - } - - componentDidMount() { - this.isCancelled = false; - this.updateInterval = setInterval(() => this.update(), 3e4); - this.counterInterval = setInterval(() => { - this.setState({ - updated: this.state.updateTime ? Math.floor(moment(new Date()).diff(this.state.updateTime) / 1000) + ' seconds ago' : 'never' - }); - }, 1e3); - return this.update(this); - } - - componentWillUnmount() { - this.isCancelled = true; - clearInterval(this.updateInterval); - clearInterval(this.counterInterval); - } - - update() { - if (!this.state.visible) return; - return request.bus.stop(this.state.id) - .then(data => { - let list = []; - data.forEach(x => { - list.push({ - key: x.id, - line: x.lineName, - destination: x.destinationName, - arrival: x.expectedArrival - }); - }); - list.sort((a, b) => { - return new Date(a.arrival) > new Date(b.arrival); - }); - let parse = {}; - list.forEach((x, 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, - loaded: 2, - updateTime: data.updated, - updated: Math.floor(moment(new Date()).diff(this.state.updateTime) / 1000) + ' seconds ago' - }); - }); - } -} - -class TabHome extends Component { - constructor(props) { - super(props); - } - - render() { - return ( - <View style={{flex: 1, padding: 24}}> - <Text style={{fontSize: 20, textAlign: 'center'}}>Select a tab above to get started!</Text> - <Text style={{fontSize: 16, color: '#1a1a1a'}}>⦿ My Stops - quick glance at favourites</Text> - <Text style={{fontSize: 16, color: '#1a1a1a'}}>⦿ Search - simple stop search</Text> - <Text style={{fontSize: 16, color: '#1a1a1a'}}>⦿ About - app info and libraries used</Text> - </View> - ); - } -} - -class TabAbout extends Component { - constructor(props) { - super(props); - } - - render() { - return ( - <View style={{flex: 1, padding: 24}}> - <Text style={{fontSize: 20, textAlign: 'center'}}>About</Text> - <Text style={{fontSize: 16, color: '#1a1a1a'}}>Created by Paul Makles (insrt.uk)</Text> - <Text style={{fontSize: 16, color: '#1a1a1a'}}>Libraries used:</Text> - <Text style={{fontSize: 16, color: '#1a1a1a'}}>⦿ react native</Text> - <Text style={{fontSize: 16, color: '#1a1a1a'}}>⦿ moment.js</Text> - <Text style={{fontSize: 16, color: '#1a1a1a'}}>⦿ react tabs</Text> - </View> - ); - } -} - -class TabMyStops extends Component { - constructor(props) { - super(props); - this.state = { - stops: [] - }; - } - - componentDidMount() { - this.isCancelled = false; - AsyncStorage.getItem('myStops').then(x => { - if (x == null) return; - !this.isCancelled && this.setState({ - stops: JSON.parse(x) - }); - }).catch(() => {}); - } - - componentWillUnmount() { - this.isCancelled = true; - } - - render() { - return ( - <ScrollView style={styles.list}> - {this.state.stops.map(i => { - return (<BusArrivals name={i.name} id={i.id} key={i.id} />); - })} - </ScrollView> - ); - } -} - -class SearchEntry extends Component { - constructor(props) { - super(props); - this.state = { - i: props.data.i, - id: props.data.id, - name: props.data.name - }; - } - - render() { - return ( - <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}; - AsyncStorage.getItem('myStops').then(x => { - if (x == null) return AsyncStorage.setItem('myStops', JSON.stringify([d])).then(() => { - ToastAndroid.show('Added to your stops!', ToastAndroid.SHORT); - }); - let arr = JSON.parse(x); - let found = false; - arr.forEach(y => { - if (y.id == this.state.id) found = true; - }); - if (found) { - ToastAndroid.show('Already added!', ToastAndroid.SHORT); - } else { - arr.push(d); - AsyncStorage.setItem('myStops', JSON.stringify(arr)).then(() => { - ToastAndroid.show('Added to your stops!', ToastAndroid.SHORT); - }); - } - }).catch(() => { - ToastAndroid.show('Encountered an error!', ToastAndroid.SHORT); - }); - }} - title="Add" - /> - </View> - ); - } -} - -class TabSearch extends Component { - constructor(props) { - super(props); - this.state = { - query: '', - searching: false, - results: [], - }; - } - - componentDidMount() { - this.isCancelled = false; - } - - search() { - if (this.state.query.length < 1) return this.setState({results: []}); - this.setState({searching: true}); - request.search(this.state.query).then(results => this.setState({results, searching: false})); - } - - componentWillUnmount() { - this.isCancelled = true; - } - - render() { - return ( - <View style={styles.child}> - <View style={styles.header_addon}> - <TextInput - style={{position: 'relative', left: -11, height: 40, backgroundColor: 'white', color: 'black', paddingLeft: 4, paddingRight: 4}} - placeholder="Search for a bus stop." - editable={!this.state.searching} - onChangeText={(query) => this.setState({query})} - onSubmitEditing={() => this.search()} - /> - </View> - <Text style={styles.status}>{this.state.searching ? 'Searching, please wait...' : (this.state.results.length > 0 ? `Displaying ${this.state.results.length} results.` : `Waiting for input...`)}</Text> - <ScrollView style={styles.list}> - {Object.keys(this.state.results).map(i => { - return (<SearchEntry key={this.state.results[i].id} data={this.state.results[i]} />); - })} - </ScrollView> - </View> - ); - } -} +import { styles } from './src/Styles'; +import { TabHome, TabAbout, TabSearch, TabMyStops } from './src/Tabs'; export default class App extends Component { constructor(props) { diff --git a/app.json b/app.json index bbbd460..697a2c0 100644 --- a/app.json +++ b/app.json @@ -8,7 +8,7 @@ "platforms": ["ios", "android"], "version": "1.0.2", "orientation": "default", - "icon": "./assets/icon.png", + "icon": "./assets/icon.png", "splash": { "image": "./assets/splash.png", "resizeMode": "contain", diff --git a/src/Arrivals.js b/src/Arrivals.js new file mode 100644 index 0000000..f8666d0 --- /dev/null +++ b/src/Arrivals.js @@ -0,0 +1,195 @@ +import React, { Component } from 'react'; +import { ToastAndroid, Button, AsyncStorage, ScrollView, Text, View } from 'react-native'; + +import { styles, element_styles } from './Styles'; +import moment from 'moment'; + +import { BusStop } from './Request'; + +export class Entry extends Component { + constructor(props) { + super(props); + let time = moment(props.item.arrival); + this.state = { + id: props.item.id, + line: props.item.line, + destination: props.item.destination, + arrival: time.fromNow(), + next: props.item.next + }; + } + + componentDidMount() { + this.updateInterval = setInterval(() => { + this.setState({arrival: moment(this.props.item.arrival).fromNow()}); + }, 1e3); + } + + componentWillUnmount() { + clearInterval(this.updateInterval); + } + + render() { + return ( + <View style={[element_styles.container, {backgroundColor: this.state.id % 2 ? '#f6f6f6' : '#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> + </View> + ); + } +} + +class BusArrivals extends Component { + constructor(props) { + super(props); + this.state = { + name: props.name, + id: props.id, + data: [], + updated: 'never', + visible: true, + }; + } + + render() { + if (!this.state.visible) return null; + return ( + <View> + <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 (<Entry item={this.state.data[i]} key={this.state.data[i].key} />); + })} + <View style={styles.button}> + <Button + onPress={() => { + AsyncStorage.getItem('myStops').then(x => { + let arr = JSON.parse(x); + let j = -1; + for (let i=0;i<arr.length;i++) { + if (arr[i].id == this.state.id) j = i; + } + if (j > -1) { + arr.splice(j, 1); + AsyncStorage.setItem('myStops', JSON.stringify(arr)).then(() => { + !this.isCancelled && this.setState({visible: false}); + ToastAndroid.show('Removed stop!', ToastAndroid.SHORT); + }); + } else { + ToastAndroid.show('Could not remove stop!', ToastAndroid.SHORT); + } + }).catch(() => { + ToastAndroid.show('Encountered an error!', ToastAndroid.SHORT); + }); + }} + title="Remove this stop" + color='#d3390a' + /> + </View> + </View> + ); + } + + componentDidMount() { + this.isCancelled = false; + this.updateInterval = setInterval(() => this.update(), 3e4); + this.counterInterval = setInterval(() => { + this.setState({ + updated: this.state.updateTime ? Math.floor(moment(new Date()).diff(this.state.updateTime) / 1000) + ' seconds ago' : 'never' + }); + }, 1e3); + return this.update(this); + } + + componentWillUnmount() { + this.isCancelled = true; + clearInterval(this.updateInterval); + clearInterval(this.counterInterval); + } + + update() { + if (!this.state.visible) return; + return BusStop(this.state.id) + .then(data => { + let list = []; + data.forEach(x => { + list.push({ + key: x.id, + line: x.lineName, + destination: x.destinationName, + arrival: x.expectedArrival + }); + }); + list.sort((a, b) => { + return new Date(a.arrival) > new Date(b.arrival); + }); + let parse = {}; + list.forEach((x, 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, + loaded: 2, + updateTime: data.updated, + updated: Math.floor(moment(new Date()).diff(this.state.updateTime) / 1000) + ' seconds ago' + }); + }); + } +} + +export class TabMyStops extends Component { + constructor(props) { + super(props); + this.state = { + stops: [] + }; + } + + componentDidMount() { + this.isCancelled = false; + AsyncStorage.getItem('myStops').then(x => { + if (x == null) return; + !this.isCancelled && this.setState({ + stops: JSON.parse(x) + }); + }).catch(() => {}); + } + + componentWillUnmount() { + this.isCancelled = true; + } + + render() { + return ( + <ScrollView style={styles.list}> + {this.state.stops.map(i => { + return (<BusArrivals name={i.name} id={i.id} key={i.id} />); + })} + </ScrollView> + ); + } +} \ No newline at end of file diff --git a/src/Request.js b/src/Request.js new file mode 100644 index 0000000..9122db6 --- /dev/null +++ b/src/Request.js @@ -0,0 +1,66 @@ +function resolve(...args) { + return 'https://api.tfl.gov.uk/' + args.join(''); +} + +let cache = {}; + +export async function BusStop(id) { + let i = "bus_stop_" + id; + if (cache[i]) { + if (cache[i].expires > +new Date()) { + return cache[i].data; + } + } + let response = await fetch(resolve('StopPoint/', id, '/arrivals')); + let data = await response.json(); + + let d = new Date(); + d.setSeconds(d.getSeconds() + 20); + data.updated = new Date(); + cache[i] = { + data, + expires: +d + }; + + return data; +} + +export async function Search(query) { + let res = await fetch(resolve('StopPoint/Search/', query)); + let source = await res.json(); + + let search = []; + source.matches.forEach(res => { + search.push(res.id); + }); + + res = await fetch(resolve('StopPoint/' + search.splice(0, 20).join(','))); + source = await res.json(); + + let data = []; + let process = x => { + if (['NaptanOnstreetBusCoachStopCluster', 'NaptanOnstreetBusCoachStopPair'].indexOf(x.stopType) > -1) { + x.children.forEach(y => process(y)); + } else if (x.stopType == 'NaptanPublicBusCoachTram') { + let name = x.commonName; + if (x.indicator) { + name += ` [${x.indicator}]` + } + data.push({ + id: x.id, + name, + //modes: res.modes, + }); + } + }; + + if (Array.isArray(search)) { + source.forEach(res => { + process(res); + }); + } else { + process(source); + } + + return data; +} \ No newline at end of file diff --git a/src/Search.js b/src/Search.js new file mode 100644 index 0000000..df384d5 --- /dev/null +++ b/src/Search.js @@ -0,0 +1,98 @@ +import React, { Component } from 'react'; +import { ToastAndroid, Button, AsyncStorage, TextInput, ScrollView, Text, View } from 'react-native'; + +import { styles, element_styles } from './Styles'; + +import { Search } from './Request'; + +class SearchEntry extends Component { + constructor(props) { + super(props); + this.state = { + i: props.data.i, + id: props.data.id, + name: props.data.name + }; + } + + render() { + return ( + <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}; + AsyncStorage.getItem('myStops').then(x => { + if (x == null) return AsyncStorage.setItem('myStops', JSON.stringify([d])).then(() => { + ToastAndroid.show('Added to your stops!', ToastAndroid.SHORT); + }); + let arr = JSON.parse(x); + let found = false; + arr.forEach(y => { + if (y.id == this.state.id) found = true; + }); + if (found) { + ToastAndroid.show('Already added!', ToastAndroid.SHORT); + } else { + arr.push(d); + AsyncStorage.setItem('myStops', JSON.stringify(arr)).then(() => { + ToastAndroid.show('Added to your stops!', ToastAndroid.SHORT); + }); + } + }).catch(() => { + ToastAndroid.show('Encountered an error!', ToastAndroid.SHORT); + }); + }} + title="Add" + /> + </View> + ); + } +} + +export class TabSearch extends Component { + constructor(props) { + super(props); + this.state = { + query: '', + searching: false, + results: [], + }; + } + + componentDidMount() { + this.isCancelled = false; + } + + search() { + if (this.state.query.length < 1) return this.setState({results: []}); + this.setState({searching: true}); + Search(this.state.query).then(results => this.setState({results, searching: false})); + } + + componentWillUnmount() { + this.isCancelled = true; + } + + render() { + return ( + <View style={styles.child}> + <View style={styles.header_extension}> + <TextInput + style={{position: 'relative', left: -11, height: 40, backgroundColor: 'white', color: 'black', paddingLeft: 4, paddingRight: 4}} + placeholder="Search for a bus stop." + editable={!this.state.searching} + onChangeText={(query) => this.setState({query})} + onSubmitEditing={() => this.search()} + /> + </View> + <Text style={styles.status}>{this.state.searching ? 'Searching, please wait...' : (this.state.results.length > 0 ? `Displaying ${this.state.results.length} results.` : `Waiting for input...`)}</Text> + <ScrollView style={styles.list}> + {Object.keys(this.state.results).map(i => { + return (<SearchEntry key={this.state.results[i].id} data={this.state.results[i]} />); + })} + </ScrollView> + </View> + ); + } +} \ No newline at end of file diff --git a/src/Tabs.js b/src/Tabs.js new file mode 100644 index 0000000..68b9bee --- /dev/null +++ b/src/Tabs.js @@ -0,0 +1,44 @@ +import React, { Component } from 'react'; +import { View, Text } from 'react-native'; + +export class TabHome extends Component { + constructor(props) { + super(props); + } + + render() { + return ( + <View style={{flex: 1, padding: 24}}> + <Text style={{fontSize: 20, textAlign: 'center'}}>Select a tab above to get started!</Text> + <Text style={{fontSize: 16, color: '#1a1a1a'}}>⦿ My Stops - quick glance at favourites</Text> + <Text style={{fontSize: 16, color: '#1a1a1a'}}>⦿ Search - simple stop search</Text> + <Text style={{fontSize: 16, color: '#1a1a1a'}}>⦿ About - app info and libraries used</Text> + </View> + ); + } +} + +export class TabAbout extends Component { + constructor(props) { + super(props); + } + + render() { + return ( + <View style={{flex: 1, padding: 24}}> + <Text style={{fontSize: 20, textAlign: 'center'}}>About</Text> + <Text style={{fontSize: 16, color: '#1a1a1a'}}>Created by Paul Makles (insrt.uk)</Text> + <Text style={{fontSize: 16, color: '#1a1a1a'}}>Libraries used:</Text> + <Text style={{fontSize: 16, color: '#1a1a1a'}}>⦿ react native</Text> + <Text style={{fontSize: 16, color: '#1a1a1a'}}>⦿ moment.js</Text> + <Text style={{fontSize: 16, color: '#1a1a1a'}}>⦿ react tabs</Text> + </View> + ); + } +} + +import { TabMyStops } from './Arrivals'; +module.exports.TabMyStops = TabMyStops; + +import { TabSearch } from './Search'; +module.exports.TabSearch = TabSearch; \ No newline at end of file diff --git a/src/styles.js b/src/styles.js index 17021d7..6b11e30 100644 --- a/src/styles.js +++ b/src/styles.js @@ -1,9 +1,11 @@ import { StyleSheet } from 'react-native'; -const element_styles = StyleSheet.create({ +export const element_styles = StyleSheet.create({ container: { width: '100%', - padding: 4, + padding: 2, + paddingLeft: 8, + paddingRight: 8 }, top: { padding: 6, @@ -12,15 +14,15 @@ const element_styles = StyleSheet.create({ }, line: { fontWeight: '900', - fontSize: 26, + fontSize: 22, textAlign: 'left', }, destination: { paddingLeft: 5, - fontSize: 18, + fontSize: 14, }, arrival: { - padding: 4, + padding: 2, fontSize: 14, textAlign: 'right', }, @@ -29,13 +31,13 @@ const element_styles = StyleSheet.create({ color: 'white', fontWeight: '200', textAlign: 'left', - fontSize: 24, + fontSize: 22, padding: 4, - paddingLeft: 8 + paddingLeft: 16 } }); -const styles = StyleSheet.create({ +export const styles = StyleSheet.create({ container: { display: 'flex', flex: 1, @@ -50,7 +52,7 @@ const styles = StyleSheet.create({ width: '100%', backgroundColor: '#d3390a', }, - header_addon: { + header_extension: { paddingLeft: 22, paddingBottom: 8, width: '100%', @@ -78,6 +80,4 @@ const styles = StyleSheet.create({ button: { padding: 6 } -}); - -module.exports = { element_styles, styles }; \ No newline at end of file +}); \ No newline at end of file -- GitLab