summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander NeonXP Kiryukhin <a.kiryukhin@mail.ru>2019-06-11 02:51:30 +0300
committerAlexander NeonXP Kiryukhin <a.kiryukhin@mail.ru>2019-06-11 02:51:30 +0300
commitf12a3bccd8c726e59e92123a3d8ef1f5a73d7253 (patch)
treed4b6e126c0f216972562621608a4ba97800a94bf
parentb7810c3d6c0164def328c60244bfbd20d7935bc3 (diff)
Fixes
-rw-r--r--App.js16
-rw-r--r--app.json2
-rw-r--r--package.json1
-rw-r--r--src/Actions/entity.ts16
-rw-r--r--src/Actions/settings.ts6
-rw-r--r--src/Components/Map.tsx17
-rw-r--r--src/Components/MapObjects.tsx32
-rw-r--r--src/Components/MapOverlay.tsx177
-rw-r--r--src/Components/PortalPanel.tsx1
-rw-r--r--src/Components/Settings.tsx49
-rw-r--r--src/Store/store.ts53
-rw-r--r--src/helper.js43
-rw-r--r--yarn.lock5
13 files changed, 260 insertions, 158 deletions
diff --git a/App.js b/App.js
index c73914b..77d5f78 100644
--- a/App.js
+++ b/App.js
@@ -1,8 +1,18 @@
import React from 'react';
import { Provider } from 'react-redux';
+import { PersistGate } from 'redux-persist/integration/react';
+import createStore from './src/Store/store';
import Main from './src/Main';
-import store from './src/Store/store'
+import { ActivityIndicator, Text, View } from 'react-native';
-const App = () => (<Provider store={store}><Main /></Provider>)
+const { store, persistor } = createStore();
-export default App \ No newline at end of file
+const loading = (<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}><ActivityIndicator /><Text>Загрузка состояния...</Text></View>);
+
+const App = () => (<Provider store={store}>
+ <PersistGate loading={loading} persistor={persistor}>
+ <Main />
+ </PersistGate>
+</Provider>);
+
+export default App; \ No newline at end of file
diff --git a/app.json b/app.json
index 2702486..9c10b67 100644
--- a/app.json
+++ b/app.json
@@ -15,7 +15,7 @@
"android": {
"package": "ru.neonxp.ingresshelper"
},
- "version": "1.0.0",
+ "version": "1.0.1",
"orientation": "portrait",
"icon": "./assets/icon.png",
"splash": {
diff --git a/package.json b/package.json
index 225cb47..e00b5ca 100644
--- a/package.json
+++ b/package.json
@@ -18,6 +18,7 @@
"react-redux": "^6.0.1",
"redux": "^4.0.1",
"redux-devtools-extension": "^2.13.8",
+ "redux-persist": "^5.10.0",
"redux-su": "^0.3.4",
"redux-thunk": "^2.3.0"
},
diff --git a/src/Actions/entity.ts b/src/Actions/entity.ts
index 8b01ea6..2b85ffe 100644
--- a/src/Actions/entity.ts
+++ b/src/Actions/entity.ts
@@ -15,7 +15,7 @@ const entity = {
...queue,
] : []
const tiles = getTilesToLoad(region, width).filter(t => loadedAlready.indexOf(t) == -1)
- dispatch(entity.setLoadQueue([...queue, ...tiles]))
+ dispatch(entity.setLoadQueue(tiles))
setImmediate(() => dispatch(entity.loadRutine()))
},
@@ -52,21 +52,11 @@ const entity = {
const portal = decodePortal(j.result)
portal.fullLoad = true
dispatch(entity.portalSet(guid, portal))
- let addr = "нет"
- try {
- addr = await fetch(`https://nominatim.openstreetmap.org/reverse?format=json&polygon_geojson=1&lat=${portal.coords.latitude}&lon=${portal.coords.longitude}`)
- .then(r => r.json())
- .then(j => [j.address.city, j.address.road, j.address.house_number].filter(p => !!p).join(', ') || 'нет')
- } catch (e) {
- addr = "ошибка"
- }
- portal.address = addr
- dispatch(entity.portalSet(guid, portal))
})
},
- 'setLoadQueue': (queue: string[][]) => ({
+ 'setLoadQueue': (queue: string[]) => ({
type: 'setLoad',
- queue
+ queue,
}),
'portalsSet': (portals: { [guid: string]: Portal }) => ({
type: 'portalsSet',
diff --git a/src/Actions/settings.ts b/src/Actions/settings.ts
index 8dfc3fc..ef18c9e 100644
--- a/src/Actions/settings.ts
+++ b/src/Actions/settings.ts
@@ -1,3 +1,5 @@
+import { Region } from "react-native-maps";
+
const settings = {
'setLevelFrom': (level: Number) => ({
type: 'setLevelFrom',
@@ -6,6 +8,10 @@ const settings = {
'setLevelTo': (level: Number) => ({
type: 'setLevelTo',
level
+ }),
+ 'setRegion': (region: Region) => ({
+ type: 'setRegion',
+ region
})
}
export default settings \ No newline at end of file
diff --git a/src/Components/Map.tsx b/src/Components/Map.tsx
index db0bed9..6c3ebab 100644
--- a/src/Components/Map.tsx
+++ b/src/Components/Map.tsx
@@ -1,5 +1,5 @@
import React, { Component } from 'react';
-import { StyleSheet, View, Dimensions, ActivityIndicator } from 'react-native';
+import { StyleSheet, View, Dimensions, ActivityIndicator, StatusBar } from 'react-native';
import MapView, { Marker, Region } from 'react-native-maps';
import { connect } from 'redux-su';
import { NavigationActions } from 'react-navigation';
@@ -7,7 +7,7 @@ import { NavigationActions } from 'react-navigation';
import MapOverlay from './MapOverlay';
import MapObjects from './MapObjects';
import PortalPanel from './PortalPanel';
-import { getBottomSpace } from '../helper';
+import debounce, { getBottomSpace } from '../helper';
import actions from '../Actions/actions';
import { LatLng } from '../Api/interfaces';
import { getZoomByRegion, getDataZoomForMapZoom } from '../Api/api';
@@ -35,6 +35,7 @@ class Map extends Component<Props, State> {
region: null,
dataZoom: 15,
}
+ this.load = debounce(this.load, 300)
}
componentDidMount() {
this.refreshTimer = setInterval(() => {
@@ -68,6 +69,7 @@ class Map extends Component<Props, State> {
const zoom = getZoomByRegion(width, region)
const dataZoom = getDataZoomForMapZoom(zoom);
this.setState({ region, dataZoom })
+ this.props.actions.setRegion(region)
setImmediate(() => this.load(false))
}
@@ -110,9 +112,13 @@ class Map extends Component<Props, State> {
if (!this.state.user) {
return <View style={styles.spinnerContainer}><ActivityIndicator size={'large'} /></View>
}
- const initialRegion = { ...this.state.user, latitudeDelta: 0.002, longitudeDelta: 0.002 }
+ const initialRegion = this.props.settings.region || { ...this.state.user, latitudeDelta: 0.002, longitudeDelta: 0.002 }
return (
<>
+ <StatusBar
+ backgroundColor="blue"
+ barStyle="dark-content"
+ />
<MapView
ref={r => (r != null) ? this.map = r : null}
style={styles.container}
@@ -121,6 +127,7 @@ class Map extends Component<Props, State> {
showsCompass={false}
showsScale
showsUserLocation
+ userLocationAnnotationTitle=""
showsMyLocationButton
loadingEnabled
type={'hybrid'}
@@ -131,9 +138,9 @@ class Map extends Component<Props, State> {
onPortalClick={this.onPortalClick}
region={this.state.region || initialRegion}
levels={this.props.settings.filterLevel}
+ selectedPortal={this.state.selectedPortal}
zoom={this.state.dataZoom}
/>
- {this.state.selectedPortal && <Marker cluster={false} coordinate={this.state.selectedPortal.coords} onPress={this.onPortalDismiss} />}
</MapView>
<MapOverlay
goToMe={this.goToMe}
@@ -141,6 +148,8 @@ class Map extends Component<Props, State> {
loading={this.props.entities.loadQueue.length}
selectedPortal={this.state.selectedPortal}
onOpenPortal={this.onOpenPortal}
+ getPortalDetails={this.props.actions.getPortalDetails}
+ portal={this.state.selectedPortal && this.props.entities.portals[this.state.selectedPortal.guid]}
/>
</>
);
diff --git a/src/Components/MapObjects.tsx b/src/Components/MapObjects.tsx
index 2a5e1df..6e9b053 100644
--- a/src/Components/MapObjects.tsx
+++ b/src/Components/MapObjects.tsx
@@ -1,5 +1,5 @@
import React, { PureComponent } from 'react';
-import { View, StyleSheet, Text } from 'react-native';
+import { View, StyleSheet, Text, Image } from 'react-native';
import { Polyline, Polygon, Marker, Region } from 'react-native-maps';
import Icon from 'react-native-vector-icons/FontAwesome';
import { Link, Portal, Field } from '../Api/types';
@@ -43,27 +43,28 @@ type Props = {
class MapObjects extends PureComponent<Props> {
render() {
- const region = this.props.region
- const lat1 = region.latitude - region.latitudeDelta / 2
- const lat2 = region.latitude + region.latitudeDelta / 2
- const lng1 = region.longitude - region.longitudeDelta / 2
- const lng2 = region.longitude + region.longitudeDelta / 2
const portals = this.props.portals
const fields = this.props.fields
const links = this.props.links
- const zoom = this.props.zoom
- const renderPortal = this.props.renderPortal.map(guid => this.drawPortal(guid, portals[guid], this.props.onPortalClick))
+ const renderPortal = this.props.renderPortal.map(guid => guid && this.drawPortal(guid, portals[guid], this.props.onPortalClick))
const renderLink = this.props.renderLink.map(guid => this.drawLink(guid, links[guid]))
const renderField = this.props.renderField.map(guid => this.drawField(guid, fields[guid]))
return [...renderField, ...renderLink, ...renderPortal]
}
drawPortal = (guid: string, entity: Portal, onPortalClick: Function) => {
+ const selected = this.props.selectedPortal && this.props.selectedPortal.guid == guid
return (<Marker
key={guid}
coordinate={entity.coords}
onPress={() => onPortalClick(guid, entity.coords)}
- image={PORTALS[entity.fraction + entity.level]}
- />);
+ style={[selected ? { borderColor: 'red', borderWidth: 4, borderRadius: 13 } : null, { height: 26, width: 26, flex: 1, justifyContent: "center", alignItems: 'center' }]}
+ zIndex={selected ? 10 : entity.level}
+ >
+ <Image
+ source={PORTALS[entity.fraction + entity.level]}
+ style={{ height: 22, width: 22 }}
+ />
+ </Marker>);
}
drawField = (guid: string, entity: Field) => {
return <Polygon
@@ -96,11 +97,12 @@ export default connect((store, props: Props) => {
const lng2 = region.longitude + region.longitudeDelta / 2
const minlvl = DEFAULT_ZOOM_TO_LEVEL[Math.min(props.zoom - 1, DEFAULT_ZOOM_TO_LEVEL.length - 1)]
const minlen = DEFAULT_ZOOM_TO_LINK_LENGTH[Math.min(props.zoom - 1, DEFAULT_ZOOM_TO_LINK_LENGTH.length - 1)] / 1000
- const renderPortal = Object
- .keys(store.entities.portals)
- .filter(guid => store.entities.portals[guid].level >= props.levels[0] && store.entities.portals[guid].level <= props.levels[1])
- .filter(guid => store.entities.portals[guid].coords.latitude > lat1 && store.entities.portals[guid].coords.latitude < lat2 && store.entities.portals[guid].coords.longitude > lng1 && store.entities.portals[guid].coords.longitude < lng2)
-
+ const renderPortal = props.zoom > 14
+ ? Object
+ .keys(store.entities.portals)
+ .filter(guid => store.entities.portals[guid].level >= props.levels[0] && store.entities.portals[guid].level <= props.levels[1])
+ .filter(guid => store.entities.portals[guid].coords.latitude > lat1 && store.entities.portals[guid].coords.latitude < lat2 && store.entities.portals[guid].coords.longitude > lng1 && store.entities.portals[guid].coords.longitude < lng2)
+ : [props.selectedPortal ? props.selectedPortal.guid : null]
const renderLink = Object
.keys(store.entities.links)
.filter(guid => {
diff --git a/src/Components/MapOverlay.tsx b/src/Components/MapOverlay.tsx
index 0e3624b..28da324 100644
--- a/src/Components/MapOverlay.tsx
+++ b/src/Components/MapOverlay.tsx
@@ -1,87 +1,108 @@
import React from 'react';
-import { StyleSheet, View, Text, GestureResponderEvent, ActivityIndicator, Linking, TextInput, Slider } from 'react-native';
+import { StyleSheet, View, Text, GestureResponderEvent, ActivityIndicator, Linking, TextInput, Slider, Image, Dimensions } from 'react-native';
import { FontAwesome } from '@expo/vector-icons';
import { getStatusBarHeight, getBottomSpace } from '../helper';
import { LatLng } from '../Api/interfaces';
+import { COLORS_FRACTION, COLORS_LVL, RESO_NRG } from '../constants';
+
+const { width, height } = Dimensions.get("screen")
type Props = {
goToMe: (e: GestureResponderEvent) => void;
refresh: (e: GestureResponderEvent) => void;
onOpenPortal: (guid: string, coords: LatLng) => void;
+ getPortalDetails: (guid: string) => void;
loading: Number;
selectedPortal: any;
+ portal: any;
}
-export default (props: Props) => (
- <>
- <View style={styles.overlayLeft}>
- {props.selectedPortal ? (
- <>
+export default class extends React.Component<Props> {
+ componentWillReceiveProps(next) {
+ if (this.props.selectedPortal !== next.selectedPortal && next.selectedPortal && next.selectedPortal.guid) {
+ this.props.getPortalDetails(next.selectedPortal.guid)
+ }
+ }
+ render() {
+ const props = this.props
+ const portal = this.props.portal
+ return (
+ <>
+ <View style={styles.overlayLeft}>
+ {props.loading > 0 ? (
+ <View style={styles.loader}>
+ <ActivityIndicator color={"#000"} />
+ </View>
+ ) : null}
+ </View>
+
+ <View style={styles.overlayRight}>
<View style={styles.buttonWrapper}>
<FontAwesome.Button
style={styles.button}
- name={'info'}
- onPress={() => {
- props.onOpenPortal(props.selectedPortal.guid, props.selectedPortal.coords)
- }}
+ name={'crosshairs'}
+ onPress={props.goToMe}
iconStyle={styles.icon}
color={"#000"}
size={25}
- backgroundColor={"#e3e3e3"}
+ backgroundColor={"#fff"}
/>
</View>
- {/* <View style={styles.buttonWrapper}>
+ <View style={styles.buttonWrapper}>
<FontAwesome.Button
style={styles.button}
- name={'location-arrow'}
- onPress={() => Linking.openURL(`geo:${props.selectedPortal.coords.latitude},${props.selectedPortal.coords.longitude}`)}
+ name={'refresh'}
+ onPress={props.refresh}
iconStyle={styles.icon}
color={"#000"}
size={25}
- backgroundColor={"#e3e3e3"}
+ backgroundColor={"#fff"}
/>
- </View> */}
- </>
- ) : null}
- {props.loading > 0 ? (
- <View style={styles.loader}>
- <ActivityIndicator color={"#000"} />
+ </View>
</View>
- ) : null}
- </View>
-
- <View style={styles.overlayRight}>
- <View style={styles.buttonWrapper}>
- <FontAwesome.Button
- style={styles.button}
- name={'crosshairs'}
- onPress={props.goToMe}
- iconStyle={styles.icon}
- color={"#000"}
- size={25}
- backgroundColor={"#e3e3e3"}
- />
- </View>
- <View style={styles.buttonWrapper}>
- <FontAwesome.Button
- style={styles.button}
- name={'refresh'}
- onPress={props.refresh}
- iconStyle={styles.icon}
- color={"#000"}
- size={25}
- backgroundColor={"#e3e3e3"}
- />
- </View>
- </View>
- {props.selectedPortal ? (
- <View style={styles.panel}>
- <Text>{JSON.stringify(props.selectedPortal)}</Text>
- </View>
- ) : null}
- </>
-);
-
+ {props.selectedPortal ? (
+ <View style={styles.panel} tint={'default'} intensity={90}>
+ <Image style={styles.photo} source={{ uri: portal.photo }} />
+ <View style={styles.column}>
+ <Text style={[styles.title, { color: COLORS_FRACTION[portal.fraction] }]} ellipsizeMode={'tail'} numberOfLines={1}>{portal.name}</Text>
+ <Text style={styles.subtitle}>Уровeнь: {portal.level}, здоровье: {portal.power}</Text>
+ <Text style={styles.subtitle}>Владелец: <Text style={[styles.user, { color: COLORS_FRACTION[portal.fraction] }]}>{portal.owner || 'нет'}</Text></Text>
+ <Text style={styles.subtitle}>Резонаторы:</Text>
+ <Text style={styles.subtitle}>
+ {portal.resonators && portal
+ .resonators
+ .filter(r => !!r)
+ .map((r, idx) => (<Text key={idx} style={[styles.subtitle, { color: COLORS_LVL[r[1]] }]}>[{r[1]}]</Text>))}
+ </Text>
+ </View>
+ {/* <FontAwesome.Button
+ style={styles.panelButton}
+ name={'star-o'}
+ onPress={() => {
+ props.onOpenPortal(props.selectedPortal.guid, props.selectedPortal.coords)
+ }}
+ iconStyle={styles.icon}
+ color={"#000"}
+ size={32}
+ backgroundColor={"transparent"}
+ /> */}
+ <FontAwesome.Button
+ style={styles.panelButton}
+ name={'angle-right'}
+ onPress={() => {
+ props.onOpenPortal(props.selectedPortal.guid, props.selectedPortal.coords)
+ }}
+ iconStyle={styles.icon}
+ color={"#000"}
+ size={32}
+ backgroundColor={"transparent"}
+ />
+ </View>
+ ) : null}
+ </>
+ );
+ }
+}
const styles = StyleSheet.create({
overlayLeft: {
position: 'absolute',
@@ -98,7 +119,12 @@ const styles = StyleSheet.create({
alignItems: 'center',
height: 48,
width: 48,
-
+ },
+ panelButton: {
+ justifyContent: 'center',
+ alignItems: 'center',
+ height: 100,
+ width: 64,
},
buttonWrapper: {
margin: 8,
@@ -114,15 +140,20 @@ const styles = StyleSheet.create({
},
panel: {
position: 'absolute',
- bottom: getBottomSpace(),
- left: 8,
- right: 8,
- borderRadius: 8,
- padding: 8,
+ bottom: 0,
+ left: 0,
+ right: 0,
backgroundColor: '#fff',
+ flexDirection: 'row',
+ alignItems: 'center',
+ overflow: 'hidden',
+ borderTopWidth: StyleSheet.hairlineWidth,
+ borderTopColor: '#000',
+ padding: 0,
+ height: 100,
//ios
- shadowOpacity: 0.3,
- shadowRadius: 3,
+ shadowOpacity: 0.6,
+ shadowRadius: 6,
shadowOffset: {
height: 0,
width: 0
@@ -130,11 +161,29 @@ const styles = StyleSheet.create({
//android
elevation: 1
},
+ column: {
+ flexGrow: 1,
+ padding: 8,
+ width: (width - 124)
+ },
icon: {
marginRight: 0,
},
loader: {
margin: 8,
paddingHorizontal: 8,
+ },
+ title: {
+ fontWeight: 'bold',
+ },
+ subtitle: {
+ fontWeight: 'normal',
+ },
+ user: {
+ fontWeight: 'bold',
+ },
+ photo: {
+ width: 55,
+ height: 100,
}
}); \ No newline at end of file
diff --git a/src/Components/PortalPanel.tsx b/src/Components/PortalPanel.tsx
index e372259..30564ca 100644
--- a/src/Components/PortalPanel.tsx
+++ b/src/Components/PortalPanel.tsx
@@ -43,7 +43,6 @@ class PortalPanel extends PureComponent<Props> {
<Text style={styles.subtitle}>Уровeнь: {portal.level}, здоровье: {portal.power}</Text>
<Text style={styles.subtitle}>Владелец: <Text style={[styles.user, { color: COLORS_FRACTION[portal.fraction] }]}>{portal.owner || 'нет'}</Text></Text>
<Text style={styles.subtitle}>Дата: {portal.timestamp && (new Date(portal.timestamp)).toLocaleString()}</Text>
- <Text style={styles.subtitle}>Адрес: {portal.address || 'загрузка...'}</Text>
</View>
</View>
<Text style={styles.title}>Резонаторы</Text>
diff --git a/src/Components/Settings.tsx b/src/Components/Settings.tsx
index ca481a9..ffc176c 100644
--- a/src/Components/Settings.tsx
+++ b/src/Components/Settings.tsx
@@ -23,28 +23,30 @@ class Settings extends PureComponent<Props> {
const { filterLevel } = this.props.settings
return (
<SafeAreaView style={styles.overlay}>
- <Text>Мин. Ур.: {filterLevel[0]}</Text>
- <Slider
- style={{ width: 150, height: 40 }}
- minimumValue={0}
- maximumValue={filterLevel[1]}
- value={filterLevel[0]}
- step={1}
- minimumTrackTintColor="#028ce3"
- maximumTrackTintColor="#000000"
- onSlidingComplete={this.props.setLevelFrom}
- />
- <Text>Макс. Ур.: {filterLevel[1]}</Text>
- <Slider
- style={{ width: 150, height: 40 }}
- minimumValue={filterLevel[0]}
- maximumValue={8}
- value={filterLevel[1]}
- step={1}
- minimumTrackTintColor="#028ce3"
- maximumTrackTintColor="#000000"
- onSlidingComplete={this.props.setLevelTo}
- />
+ <View style={styles.container}>
+ <Text>Мин. Ур.: {filterLevel[0]}</Text>
+ <Slider
+ style={{ height: 40 }}
+ minimumValue={0}
+ maximumValue={filterLevel[1]}
+ value={filterLevel[0]}
+ step={1}
+ minimumTrackTintColor="#028ce3"
+ maximumTrackTintColor="#000000"
+ onSlidingComplete={this.props.setLevelFrom}
+ />
+ <Text>Макс. Ур.: {filterLevel[1]}</Text>
+ <Slider
+ style={{ height: 40 }}
+ minimumValue={filterLevel[0]}
+ maximumValue={8}
+ value={filterLevel[1]}
+ step={1}
+ minimumTrackTintColor="#028ce3"
+ maximumTrackTintColor="#000000"
+ onSlidingComplete={this.props.setLevelTo}
+ />
+ </View>
</SafeAreaView>
);
}
@@ -57,6 +59,9 @@ const styles = StyleSheet.create({
flex: 1,
padding: 8,
},
+ container: {
+ margin: 8,
+ },
title: {
fontWeight: 'bold',
fontSize: 22,
diff --git a/src/Store/store.ts b/src/Store/store.ts
index 581f14b..2fb5a1f 100644
--- a/src/Store/store.ts
+++ b/src/Store/store.ts
@@ -1,8 +1,10 @@
import { createStore, combineReducers, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import { createReducer } from 'redux-su';
-import { composeWithDevTools } from 'redux-devtools-extension';
+import { AsyncStorage } from 'react-native';
+import { persistStore, persistReducer } from 'redux-persist';
import { Portal, Link, Field } from '../Api/types';
+import { Region } from '../Api/interfaces';
const reducers = {
'auth': createReducer({
@@ -32,8 +34,22 @@ const reducers = {
({ ...store, links: { ...store.links, ...action.links } }),
'fieldsSet': (store: any, action: { fields: { [guid: string]: Field } }) =>
({ ...store, fields: { ...store.fields, ...action.fields } }),
- 'setLoad': (store: any, action: { queue: string[][] }) =>
+ 'setLoad': (store: any, action: { queue: string[] }) =>
({ ...store, loadQueue: [...action.queue] }),
+ 'portalsGC': (store: any, action: { portals: { [tile: string]: string[] } }) => {
+ let portalsCache = store.portalsCache
+ let portals = store.portals
+ Object.keys(action.portals).forEach(tileId => {
+ const oldPortals = portalsCache[tileId]
+ if (oldPortals != undefined) {
+ oldPortals.forEach((guid: string) => {
+ delete portals[guid]
+ })
+ }
+ portalsCache[tileId] = action.portals[tileId]
+ })
+ return ({ ...store, portals: { ...portals }, portalsCache })
+ },
'linksGC': (store: any, action: { links: { [tile: string]: string[] } }) => {
let linksCache = store.linksCache
let links = store.links
@@ -62,28 +78,31 @@ const reducers = {
})
return ({ ...store, fields: { ...fields }, fieldsCache })
},
- }, { portals: {}, fields: {}, links: {}, loadQueue: [], linksCache: {}, fieldsCache: {} }),
+ }, { portals: {}, fields: {}, links: {}, loadQueue: [], linksCache: {}, fieldsCache: {}, portalsCache: {} }),
'settings': createReducer({
'setLevelFrom': (store: any, action: { level: number }) => ({
...store, filterLevel: [action.level, store.filterLevel[1]]
}),
'setLevelTo': (store: any, action: { level: number }) => ({
...store, filterLevel: [store.filterLevel[0], action.level]
+ }),
+ 'setRegion': (store: any, action: { region: Region }) => ({
+ ...store, region: action.region
})
- }, { filterLevel: [0, 8] })
+ }, { filterLevel: [0, 8], region: null })
}
-function extend(obj: any, src: any) {
- for (var key in src) {
- if (src.hasOwnProperty(key) && !!src[key]) {
- obj[key] = src[key];
- }
- }
- return obj;
-}
+const rootReducer = combineReducers(reducers)
-const store = createStore(
- combineReducers(reducers),
- composeWithDevTools(applyMiddleware(thunk))
-)
-export default store \ No newline at end of file
+const persistConfig = {
+ key: 'root',
+ storage: AsyncStorage,
+ }
+
+ const persistedReducer = persistReducer(persistConfig, rootReducer)
+
+ export default () => {
+ let store = createStore(persistedReducer, applyMiddleware(thunk))
+ let persistor = persistStore(store)
+ return { store, persistor }
+ } \ No newline at end of file
diff --git a/src/helper.js b/src/helper.js
index 2242d91..3a4cca0 100644
--- a/src/helper.js
+++ b/src/helper.js
@@ -45,23 +45,30 @@ function formatInt(num) {
return ("00" + num).slice(-2)
}
-export function calcCrow(lat1, lon1, lat2, lon2)
- {
- var R = 6371; // km
- var dLat = toRad(lat2-lat1);
- var dLon = toRad(lon2-lon1);
- var lat1 = toRad(lat1);
- var lat2 = toRad(lat2);
+export function calcCrow(lat1, lon1, lat2, lon2) {
+ var R = 6371; // km
+ var dLat = toRad(lat2 - lat1);
+ var dLon = toRad(lon2 - lon1);
+ var lat1 = toRad(lat1);
+ var lat2 = toRad(lat2);
- var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
- Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
- var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
- var d = R * c;
- return d;
- }
+ var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
+ Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2);
+ var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
+ var d = R * c;
+ return d;
+}
+
+// Converts numeric degrees to radians
+function toRad(Value) {
+ return Value * Math.PI / 180;
+}
- // Converts numeric degrees to radians
- function toRad(Value)
- {
- return Value * Math.PI / 180;
- } \ No newline at end of file
+export default function debounce(func, wait) {
+ let timeout
+ return function (...args) {
+ const context = this
+ clearTimeout(timeout)
+ timeout = setTimeout(() => func.apply(context, args), wait)
+ }
+}
diff --git a/yarn.lock b/yarn.lock
index 2b3030f..8c6f925 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4936,6 +4936,11 @@ redux-devtools-extension@^2.13.8:
resolved "https://registry.yarnpkg.com/redux-devtools-extension/-/redux-devtools-extension-2.13.8.tgz#37b982688626e5e4993ff87220c9bbb7cd2d96e1"
integrity sha512-8qlpooP2QqPtZHQZRhx3x3OP5skEV1py/zUdMY28WNAocbafxdG2tRD1MWE7sp8obGMNYuLWanhhQ7EQvT1FBg==
+redux-persist@^5.10.0:
+ version "5.10.0"
+ resolved "https://registry.yarnpkg.com/redux-persist/-/redux-persist-5.10.0.tgz#5d8d802c5571e55924efc1c3a9b23575283be62b"
+ integrity sha512-sSJAzNq7zka3qVHKce1hbvqf0Vf5DuTVm7dr4GtsqQVOexnrvbV47RWFiPxQ8fscnyiuWyD2O92DOxPl0tGCRg==
+
redux-su@^0.3.4:
version "0.3.4"
resolved "https://registry.yarnpkg.com/redux-su/-/redux-su-0.3.4.tgz#27111cd5c502cd58988d3c171c13bc10142ce9c3"