summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander NeonXP Kiryukhin <a.kiryukhin@mail.ru>2019-05-15 03:32:55 +0300
committerAlexander NeonXP Kiryukhin <a.kiryukhin@mail.ru>2019-05-15 03:32:55 +0300
commit491a92f71cf13bc8ef84db3b7fb24361013afb8e (patch)
treef4d45203428dcafa0b865e3604f5e9479d2c150b
parent0c9db775302d15483385f0621611583e3a2407cd (diff)
Many fixes
-rw-r--r--src/Actions/entity.ts79
-rw-r--r--src/Api/api.ts16
-rw-r--r--src/Api/interfaces.ts4
-rw-r--r--src/Components/Login.tsx20
-rw-r--r--src/Components/Map.tsx121
-rw-r--r--src/Components/MapObjects.tsx114
-rw-r--r--src/Components/MapOverlay.tsx130
-rw-r--r--src/Components/PortalPanel.tsx50
-rw-r--r--src/Components/Settings.tsx46
-rw-r--r--src/Main.js30
-rw-r--r--src/Store/store.ts14
-rw-r--r--src/colors.ts1
12 files changed, 325 insertions, 300 deletions
diff --git a/src/Actions/entity.ts b/src/Actions/entity.ts
index 632b505..f2161fc 100644
--- a/src/Actions/entity.ts
+++ b/src/Actions/entity.ts
@@ -9,55 +9,40 @@ import { decodePortal } from '../Api/entityDecoder';
const entity = {
'update': (region: Region, width: number, refresh: boolean) => async (dispatch, getStore) => {
const store = getStore()
- let tiles = getTilesToLoad(region, width)
- if (!refresh) {
- const loadedAlready = Object.keys(store.entities.portals)
- tiles = tiles.filter(t => loadedAlready.indexOf(t) == -1)
- }
- const display = store.entities.display
- dispatch(entity.loadTiles(tiles, display))
+ const queue = store.entities.loadQueue
+ const loadedAlready = refresh ?
+ [
+ ...Object.keys(store.entities.portals),
+ ...queue,
+ ] : []
+ const tiles = getTilesToLoad(region, width).filter(t => loadedAlready.indexOf(t) == -1)
+ dispatch(entity.setLoadQueue([...queue, ...tiles]))
+ setImmediate(() => dispatch(entity.loadRutine()))
},
- 'loadTiles': (tiles: string[], display: any) => async (dispatch, getStore) => {
+ 'loadRutine': () => async (dispatch, getStore) => {
const store = getStore()
+ const queue = store.entities.loadQueue
+ console.log('1', queue.length)
+ const chunk = queue.splice(0, 25)
+ console.log('2', chunk.length, queue.length)
const { v, csrf } = store.auth
const params = { v, csrf }
- dispatch(entity.entitiesLoad(tiles.length))
- setImmediate(() => loadTiles(tiles, params)
- .then((loadedData: LoadedResult) => dispatch(entity.receiveTiles(loadedData, display))))
- },
- 'receiveTiles': (loadedData: LoadedResult, display: any) => async (dispatch) => {
- dispatch(entity.portalsSet(loadedData.portals))
- dispatch(entity.linksSet(loadedData.links))
- dispatch(entity.fieldsSet(loadedData.fields))
- Object.keys(loadedData.portalsByTile).forEach(tile => {
- loadedData.portalsByTile[tile].forEach(p => {
- if (display.portals.indexOf(p) == -1) {
- display.portals.push(p)
+ loadTiles(chunk, params)
+ .then(({ result, failed }) => {
+ const queue = store.entities.loadQueue
+ dispatch(entity.portalsSet(result.portals))
+ dispatch(entity.linksSet(result.links))
+ dispatch(entity.fieldsSet(result.fields))
+ let newQueue = queue
+ if (failed.length > 0) {
+ newQueue = [...queue, ...failed]
}
- })
- })
- Object.keys(loadedData.linksByTile).forEach(tile => {
- loadedData.linksByTile[tile].forEach(p => {
- if (display.links.indexOf(p) == -1) {
- display.links.push(p)
- }
- })
- })
- Object.keys(loadedData.fieldsByTile).forEach(tile => {
- loadedData.fieldsByTile[tile].forEach(p => {
- if (display.fields.indexOf(p) == -1) {
- display.fields.push(p)
+ dispatch(entity.setLoadQueue([...newQueue]))
+ if (newQueue.length > 0) {
+ setImmediate(() => dispatch(entity.loadRutine()))
}
})
- })
- dispatch(entity.entitiesDisplay(display))
- if (loadedData.failedTiles.length > 0) {
- setImmediate(() => {
- dispatch(entity.loadTiles(loadedData.failedTiles, display))
- })
- } else {
- dispatch(entity.entitiesLoad(0))
- }
+
},
'getPortalDetails': (guid: string) => async (dispatch, getStore) => {
const store = getStore()
@@ -69,13 +54,9 @@ const entity = {
dispatch(entity.portalSet(guid, portal))
})
},
- 'entitiesDisplay': (display: any) => ({
- type: 'entitiesDisplay',
- display
- }),
- 'entitiesLoad': (loading: number) => ({
- type: 'entitiesLoad',
- loading
+ 'setLoadQueue': (queue: string[][]) => ({
+ type: 'setLoad',
+ queue
}),
'portalsSet': (portals: { [guid: string]: Portal }) => ({
type: 'portalsSet',
diff --git a/src/Api/api.ts b/src/Api/api.ts
index 2da4594..4c83252 100644
--- a/src/Api/api.ts
+++ b/src/Api/api.ts
@@ -59,8 +59,7 @@ export const getTilesToLoad = (region: Region, width: number): string[] => {
return tilesToLoad
}
-export const loadTiles = async (tilesToLoad: string[], params: RequestParams): Promise<LoadedResult> => {
- const chunk = tilesToLoad.splice(0, 25)
+export const loadTiles = async (tilesToLoad: string[], params: RequestParams): Promise<{ result: LoadedResult, failed: string[] }> => {
const loadedData: LoadedResult = {
fields: {},
links: {},
@@ -68,10 +67,9 @@ export const loadTiles = async (tilesToLoad: string[], params: RequestParams): P
portalsByTile: {},
fieldsByTile: {},
linksByTile: {},
- failedTiles: tilesToLoad,
- loaded: false,
}
- await getEntities(chunk, params)
+ const failed = []
+ await getEntities(tilesToLoad, params)
.then(loaded => {
const result = loaded.result
if (!result || !result['map']) {
@@ -79,7 +77,7 @@ export const loadTiles = async (tilesToLoad: string[], params: RequestParams): P
}
return Object.keys(result['map']).map(tile => {
if (result['map'][tile]['error'] || !result['map'][tile]['gameEntities']) {
- loadedData.failedTiles.push(tile)
+ failed.push(tile)
return true
}
if (!loadedData.portalsByTile[tile]) {
@@ -114,9 +112,11 @@ export const loadTiles = async (tilesToLoad: string[], params: RequestParams): P
})
})
}).catch(e => {
- loadedData.failedTiles = [...loadedData.failedTiles, ...chunk]
+ tilesToLoad.forEach(element => {
+ failed.push(element)
+ });
})
- return loadedData
+ return { result: loadedData, failed }
}
const getBoundingBox = (region: Region): BoundingBox => {
diff --git a/src/Api/interfaces.ts b/src/Api/interfaces.ts
index 779fcf1..0dcafc0 100644
--- a/src/Api/interfaces.ts
+++ b/src/Api/interfaces.ts
@@ -32,7 +32,6 @@ export interface GetPortalResponse {
}
export interface LoadedResult {
- loaded: boolean,
portalsByTile: {
[tile: string]: string[]
},
@@ -50,8 +49,7 @@ export interface LoadedResult {
},
fields: {
[guid: string]: Field
- },
- failedTiles: string[]
+ }
}
diff --git a/src/Components/Login.tsx b/src/Components/Login.tsx
index 6fe7957..fe20e09 100644
--- a/src/Components/Login.tsx
+++ b/src/Components/Login.tsx
@@ -8,20 +8,13 @@ import actions from '../Actions/actions';
const LOGIN_URL = "https://accounts.google.com/ServiceLogin?service=ah&passive=true&continue=https://appengine.google.com/_ah/conflogin%3Fcontinue%3Dhttps://intel.ingress.com/";
const HOME_URL = "https://intel.ingress.com/";
-var styles = StyleSheet.create({
- container: {
- flexGrow: 1,
- }
-});
-
type Props = {
- login(csrf: string, v: string): void
+ login(): void
actions: any
auth: any
}
type State = {
- v: string
onIngress: boolean
}
@@ -29,7 +22,7 @@ class Login extends Component<Props, State> {
webview!: WebView;
constructor(props: Props) {
super(props);
- this.state = { v: "", onIngress: false }
+ this.state = { onIngress: false }
}
onNavigationStateChange(navState: WebViewNavigation) {
@@ -47,7 +40,7 @@ class Login extends Component<Props, State> {
<>
<WebView
ref={r => r && (this.webview = r)}
- automaticallyAdjustContentInsets={false}
+ automaticallyAdjustContentInsets={true}
thirdPartyCookiesEnabled
useWebKit
style={styles.container}
@@ -68,4 +61,11 @@ class Login extends Component<Props, State> {
}
}
+var styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ }
+});
+
+
export default connect({ 'auth': 'auth' }, actions)(Login) \ No newline at end of file
diff --git a/src/Components/Map.tsx b/src/Components/Map.tsx
index 3e878f8..68698f4 100644
--- a/src/Components/Map.tsx
+++ b/src/Components/Map.tsx
@@ -20,67 +20,64 @@ const draggableRange = {
type Props = any
type State = any
class Map extends Component<Props, State> {
- refresh: number | undefined
+ static navigationOptions = ({ navigation }) => {
+ return {
+ title: 'Карта',
+ };
+ };
+ refreshTimer: number | undefined
map!: MapView;
constructor(props: Props) {
super(props)
this.state = {
user: undefined,
- followUser: true,
- zoom: 15,
region: null,
- loading: false,
- objects: { links: {}, fields: {}, portals: {}, loaded: false },
}
}
+ componentDidMount() {
+ this.refreshTimer = setInterval(() => {
+ this.refresh()
+ }, 30000)
+ }
+ componentWillUnmount() {
+ clearInterval(this.refreshTimer)
+ }
componentWillMount() {
+ const setPosition = (position) => {
+ this.setState({
+ user: {
+ latitude: position.coords.latitude,
+ longitude: position.coords.longitude
+ },
+ });
+ }
navigator.geolocation.getCurrentPosition(
- position => {
- this.setState({
- followUser: true,
- });
- },
+ setPosition,
error => alert(error.message),
{ enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 }
);
navigator.geolocation.watchPosition(
- position => {
- this.setState({
- user: {
- latitude: position.coords.latitude,
- longitude: position.coords.longitude
- },
- });
- },
+ setPosition,
error => alert(error.message),
{ enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 }
)
}
onRegionChange = (region: Region) => {
- const zoom = this.getZoomByRegion(width, region)
- this.setState({ region, zoom })
+ this.setState({ region })
setImmediate(() => this.load(false))
}
- getZoomByRegion(width: number, region: Region): number {
- return Math.ceil(Math.log2(360 * ((width / 256) / region.longitudeDelta))) + 1
+
+ refresh = () => {
+ setImmediate(() => this.load(true))
}
+
load = async (refresh: boolean) => {
- if (this.state.region != null && this.props.entities.loading == 0) {
+ if (this.state.region != null) {
this.props.actions.update(this.state.region, width, refresh)
}
return null
}
- refreshByTime = () => {
- setTimeout(() => {
- this.load(true).then(this.refreshByTime)
- }, 30000)
- }
-
- componentDidMount() {
- this.refreshByTime()
- }
-
onPortalClick = (guid: string, coords: LatLng) => {
this.setState({ selectedPortal: { guid, coords } })
}
@@ -93,23 +90,15 @@ class Map extends Component<Props, State> {
this.props.navigation.dispatch(navigateAction);
}
+ goToMe = () => {
+ this.map.animateToCoordinate(this.state.user)
+ }
+
render() {
if (!this.state.user) {
return <View style={styles.spinnerContainer}><ActivityIndicator size={'large'} /></View>
}
- const camera = {
- center: this.state.user,
- altitude: 1000,
- heading: 0,
- pitch: 30,
- zoom: 15,
- }
- const goToMe = () => {
- this.map.animateToCoordinate(this.state.user)
- }
- const refresh = () => {
- setImmediate(() => this.load(true))
- }
+
return (
<>
<MapView
@@ -124,13 +113,13 @@ class Map extends Component<Props, State> {
loadingEnabled
type={'hybrid'}
>
- <MapObjects onPortalClick={this.onPortalClick} zoom={this.state.zoom} />
+ <MapObjects onPortalClick={this.onPortalClick} />
{this.state.selectedPortal && <Marker coordinate={this.state.selectedPortal.coords} />}
</MapView>
<MapOverlay
- goToMe={goToMe}
- refresh={refresh}
- loading={this.props.entities.loading}
+ goToMe={this.goToMe}
+ refresh={this.refresh}
+ loading={this.props.entities.loadQueue.length}
selectedPortal={this.state.selectedPortal}
onOpenPortal={this.onOpenPortal}
/>
@@ -143,38 +132,6 @@ const styles = StyleSheet.create({
container: {
flex: 1,
},
- spinnerContainer: {
- flex: 1,
- justifyContent: 'center',
- alignItems: 'center',
- },
- panel: {
- flex: 1,
- backgroundColor: '#fff',
- position: 'relative',
- borderTopLeftRadius: 20,
- borderTopRightRadius: 20,
- //ios
- shadowOpacity: 0.3,
- shadowRadius: 3,
- shadowOffset: {
- height: 0,
- width: 0
- },
- //android
- elevation: 1
- },
- panelHeader: {
- height: 40,
- alignItems: 'center',
- justifyContent: 'center',
- },
- dash: {
- backgroundColor: 'rgba(200,200,200,0.9)',
- height: 6,
- width: 30,
- borderRadius: 3
- }
});
export default connect({ 'entities': 'entities' }, actions)(Map) \ No newline at end of file
diff --git a/src/Components/MapObjects.tsx b/src/Components/MapObjects.tsx
index 1d2fb12..af0afec 100644
--- a/src/Components/MapObjects.tsx
+++ b/src/Components/MapObjects.tsx
@@ -1,4 +1,4 @@
-import React, { ReactChild } from 'react';
+import React, { PureComponent } from 'react';
import { View, StyleSheet, Text } from 'react-native';
import { Polyline, Polygon, Marker, Region } from 'react-native-maps';
import Icon from 'react-native-vector-icons/FontAwesome';
@@ -17,74 +17,64 @@ type Props = {
links: { [guid: string]: Link }
fields: { [guid: string]: Field }
onPortalClick: Function
- zoom: number
}
-const MapObjects = (props: Props) => {
- const renderPortal = Object.keys(props.portals).map(guid => drawPortal(guid, props.portals[guid], props.zoom, props.onPortalClick))
- const renderField = Object.keys(props.fields).map(guid => drawField(guid, props.fields[guid]))
- const renderLink = Object.keys(props.links).map(guid => drawLink(guid, props.links[guid]))
+class MapObjects extends PureComponent<Props> {
+ render() {
+ const props = this.props
+ const renderPortal = Object.keys(props.portals).map(guid => this.drawPortal(guid, props.portals[guid], props.onPortalClick))
+ const renderField = Object.keys(props.fields).map(guid => this.drawField(guid, props.fields[guid]))
+ const renderLink = Object.keys(props.links).map(guid => this.drawLink(guid, props.links[guid]))
- if (props.zoom <= 14) {
- return [...renderField, ...renderLink]
- } else {
- return [...renderField, ...renderLink, ...renderPortal]
+ if (props.zoom <= 14) {
+ return [...renderField, ...renderLink]
+ } else {
+ return [...renderField, ...renderLink, ...renderPortal]
+ }
+ }
+ drawPortal = (guid: string, entity: Portal, onPortalClick: Function) => {
+ const size = 20
+ return (<Marker
+ key={guid}
+ coordinate={entity.coords}
+ onPress={() => onPortalClick(guid, entity.coords)}
+ >
+ {/* <Icon name={entity.fraction == "N" ? "circle-o" : "circle"} color={fillPortalColor[entity.fraction]} size={size} /> */}
+ <View style={{
+ borderWidth: 2,
+ height: size,
+ width: size,
+ borderRadius: size / 2,
+ borderColor: COLORS_LVL[entity.level],
+ backgroundColor: fillPortalColor[entity.fraction],
+ justifyContent: 'center',
+ alignItems: 'center',
+ }}>
+ <Text style={{ fontWeight: 'bold' }}>{entity.level}</Text>
+ </View>
+ </Marker>);
+ }
+ drawField = (guid: string, entity: Field) => {
+ return <Polygon
+ key={guid}
+ coordinates={entity.coords}
+ fillColor={fieldColor[entity.fraction]}
+ strokeColor={fieldColor[entity.fraction]}
+ strokeWidth={StyleSheet.hairlineWidth}
+ />
+ }
+ drawLink = (guid: string, entity: Link) => {
+ return <Polyline
+ key={guid}
+ coordinates={entity.coords}
+ strokeColor={fractColor[entity.fraction]}
+ strokeWidth={1}
+ />
}
-}
-const drawPortal = (guid: string, entity: Portal, zoom: number, onPortalClick: Function) => {
- const size = (zoom) * 1.5
- return (<Marker
- key={guid}
- coordinate={entity.coords}
- onPress={() => onPortalClick(guid, entity.coords)}
- >
- {/* <Icon name={entity.fraction == "N" ? "circle-o" : "circle"} color={fillPortalColor[entity.fraction]} size={size} /> */}
- <View style={{
- borderWidth: 2,
- height: size,
- width: size,
- borderRadius: size / 2,
- borderColor: COLORS_LVL[entity.level],
- backgroundColor: fillPortalColor[entity.fraction],
- justifyContent: 'center',
- alignItems: 'center',
- }}>
- <Text style={{ fontWeight: 'bold' }}>{entity.level}</Text>
- </View>
- </Marker>);
-}
-const drawField = (guid: string, entity: Field) => {
- return <Polygon
- key={guid}
- coordinates={entity.coords}
- fillColor={fieldColor[entity.fraction]}
- strokeColor={fieldColor[entity.fraction]}
- strokeWidth={StyleSheet.hairlineWidth}
- />
-}
-const drawLink = (guid: string, entity: Link) => {
- return <Polyline
- key={guid}
- coordinates={entity.coords}
- strokeColor={fractColor[entity.fraction]}
- strokeWidth={1}
- />
}
-
const styles = StyleSheet.create({
});
-export default connect((store) => {
- const display = store.entities.display
- const portals = {}
- const fields = {}
- const links = {}
- display.portals.forEach(guid => { portals[guid] = store.entities.portals[guid] })
- display.fields.forEach(guid => { fields[guid] = store.entities.fields[guid] })
- display.links.forEach(guid => { links[guid] = store.entities.links[guid] })
- return {
- portals, fields, links
- }
-}, {})(MapObjects) \ No newline at end of file
+export default connect((store) => ({ portals: store.entities.portals, fields: store.entities.fields, links: store.entities.links }), {})(MapObjects) \ No newline at end of file
diff --git a/src/Components/MapOverlay.tsx b/src/Components/MapOverlay.tsx
index 30160c9..faf484e 100644
--- a/src/Components/MapOverlay.tsx
+++ b/src/Components/MapOverlay.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { StyleSheet, View, Text, GestureResponderEvent, ActivityIndicator, Linking } from 'react-native';
import { FontAwesome } from '@expo/vector-icons';
-import { getStatusBarHeight } from '../helper';
+import { getStatusBarHeight, getBottomSpace } from '../helper';
import { LatLng } from '../Api/interfaces';
type Props = {
@@ -13,72 +13,88 @@ type Props = {
}
export default (props: Props) => (
- <View style={styles.overlay}>
- <View style={styles.button}>
- <FontAwesome.Button
- name={'crosshairs'}
- onPress={props.goToMe}
- iconStyle={styles.icon}
- color={"#000"}
- size={24}
- backgroundColor={"#e3e3e3"}
- />
- </View>
- <View style={styles.button}>
- <FontAwesome.Button
- name={'refresh'}
- onPress={props.refresh}
- iconStyle={styles.icon}
- color={"#000"}
- size={24}
- backgroundColor={"#e3e3e3"}
- />
- </View>
- {props.selectedPortal ? (
- <>
- <View style={styles.button}>
- <FontAwesome.Button
- name={'info'}
- onPress={() => {
- props.onOpenPortal(props.selectedPortal.guid, props.selectedPortal.coords)
- }}
- iconStyle={styles.icon}
- color={"#000"}
- size={24}
- backgroundColor={"#e3e3e3"}
- />
- </View>
- <View style={styles.button}>
- <FontAwesome.Button
- name={'location-arrow'}
- onPress={() => Linking.openURL(`geo:${props.selectedPortal.coords.latitude},${props.selectedPortal.coords.longitude}`)}
- iconStyle={styles.icon}
- color={"#000"}
- size={24}
- backgroundColor={"#e3e3e3"}
- />
+ <>
+ <View style={styles.overlayLeft}>
+ {props.loading > 0 ? (
+ <View style={styles.loader}>
+ <ActivityIndicator color={"#000"} />
</View>
- </>
- ) : null}
-
- <View style={styles.button}>
- <Text>{props.loading}</Text>
+ ) : null}
+ {props.selectedPortal ? (
+ <>
+ <View style={styles.buttonWrapper}>
+ <FontAwesome.Button
+ style={styles.button}
+ name={'info'}
+ onPress={() => {
+ props.onOpenPortal(props.selectedPortal.guid, props.selectedPortal.coords)
+ }}
+ iconStyle={styles.icon}
+ color={"#000"}
+ size={25}
+ backgroundColor={"#e3e3e3"}
+ />
+ </View>
+ <View style={styles.buttonWrapper}>
+ <FontAwesome.Button
+ style={styles.button}
+ name={'location-arrow'}
+ onPress={() => Linking.openURL(`geo:${props.selectedPortal.coords.latitude},${props.selectedPortal.coords.longitude}`)}
+ iconStyle={styles.icon}
+ color={"#000"}
+ size={25}
+ backgroundColor={"#e3e3e3"}
+ />
+ </View>
+ </>
+ ) : null}
</View>
- {props.loading > 0 ? (
- <View style={styles.loader}>
- <ActivityIndicator color={"#000"} />
+
+ <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>
- ) : null}
- </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>
+ </>
);
const styles = StyleSheet.create({
- overlay: {
+ overlayLeft: {
position: 'absolute',
- top: 8 + getStatusBarHeight(true),
+ bottom: getBottomSpace(),
+ left: 8,
+ },
+ overlayRight: {
+ position: 'absolute',
+ bottom: getBottomSpace(),
right: 8,
},
button: {
+ justifyContent: 'center',
+ alignItems: 'center',
+ height: 48,
+ width: 48,
+ },
+ buttonWrapper: {
margin: 8,
},
icon: {
diff --git a/src/Components/PortalPanel.tsx b/src/Components/PortalPanel.tsx
index 6cf19c2..d49d88a 100644
--- a/src/Components/PortalPanel.tsx
+++ b/src/Components/PortalPanel.tsx
@@ -1,12 +1,12 @@
import React, { Component, PureComponent } from 'react';
-import { StyleSheet, View, Text, GestureResponderEvent, ActivityIndicator } from 'react-native';
+import { StyleSheet, View, Text, GestureResponderEvent, ActivityIndicator, Image } from 'react-native';
// import { Button } from 'react-native-vector-icons/FontAwesome';
-import Reactotron from 'reactotron-react-native'
import { getStatusBarHeight } from '../helper';
import { connect } from 'react-redux';
import actions from '../Actions/actions';
import { Portal } from '../Api/types';
import { bindActionCreators } from 'redux';
+import { COLORS_FRACTION } from '../colors';
type Props = {
guid: string
@@ -16,18 +16,14 @@ type Props = {
class PortalPanel extends PureComponent<Props> {
static navigationOptions = ({ navigation }) => {
return {
- title: navigation.getParam('title', 'Загрузка...'),
+ title: 'Информация о портале',
};
- };
- componentWillMount() {
- this.props.navigation.setParams({title: this.props.portal.name})
- }
+ };
componentDidMount() {
this.props.getPortalDetails(this.props.guid)
}
componentWillReceiveProps(next: Props) {
if (next.guid != this.props.guid) {
- this.props.navigation.setParams({title: this.props.portal.name})
this.props.getPortalDetails(next.guid)
}
}
@@ -38,9 +34,28 @@ class PortalPanel extends PureComponent<Props> {
}
return (
<View style={styles.overlay}>
- <Text style={styles.title}>{portal.name}</Text>
- <Text style={styles.subtitle}>Уровeнь: {portal.level}, здоровье: {portal.power}</Text>
- <Text>{JSON.stringify(this.props)}</Text>
+ <View style={styles.panelRow}>
+ <Image style={styles.photo} source={{ uri: portal.photo }} />
+ <View style={styles.panelRight}>
+ <Text style={[styles.title, { color: COLORS_FRACTION[portal.fraction] }]}>{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}>Дата: {portal.timestamp && (new Date(portal.timestamp)).toLocaleString()}</Text>
+ </View>
+ </View>
+ <Text style={styles.title}>Резонаторы</Text>
+ <View>
+ {portal.resonators && portal.resonators.map((r, idx) =>
+ r ? (<Text style={styles.subtitle}>{idx + 1}: {r[1]} [{r[2]}] - {r[0]}</Text>) : (<Text style={styles.subtitle}>{idx + 1}: нет</Text>)
+ )}
+ {(!portal.resonators || portal.resonators.length == 0) && (<Text style={styles.subtitle}>нет</Text>)}
+ </View>
+ <Text style={styles.title}>Моды</Text>
+ <View>
+ {portal.mods && portal.mods.map((r, idx) =>
+ r ? (<Text style={styles.subtitle}>{idx + 1}: {r[1]} [{r[2]}] - {r[0]}</Text>) : (<Text style={styles.subtitle}>{idx + 1}: нет</Text>)
+ )}
+ </View>
</View>
);
}
@@ -59,6 +74,12 @@ const styles = StyleSheet.create({
flex: 1,
padding: 8,
},
+ panelRow: {
+ flexDirection: 'row',
+ },
+ panelRight: {
+ paddingLeft: 8
+ },
title: {
fontWeight: 'bold',
fontSize: 22,
@@ -66,5 +87,12 @@ const styles = StyleSheet.create({
subtitle: {
fontWeight: 'normal',
fontSize: 18,
+ },
+ user: {
+ fontWeight: 'bold',
+ },
+ photo: {
+ width: 100,
+ height: 195,
}
}); \ No newline at end of file
diff --git a/src/Components/Settings.tsx b/src/Components/Settings.tsx
new file mode 100644
index 0000000..daf3216
--- /dev/null
+++ b/src/Components/Settings.tsx
@@ -0,0 +1,46 @@
+import React, { Component, PureComponent } from 'react';
+import { StyleSheet, View, Text, GestureResponderEvent, ActivityIndicator } from 'react-native';
+// import { Button } from 'react-native-vector-icons/FontAwesome';
+import { getStatusBarHeight } from '../helper';
+import { connect } from 'react-redux';
+import actions from '../Actions/actions';
+import { Portal } from '../Api/types';
+import { bindActionCreators } from 'redux';
+
+type Props = {
+ guid: string
+ portal?: Portal
+}
+
+class Settings extends PureComponent<Props> {
+ static navigationOptions = ({ navigation }) => {
+ return {
+ title: 'Настройки',
+ };
+ };
+
+ render() {
+ return (
+ <View style={styles.overlay}>
+ <Text>{JSON.stringify(this.props)}</Text>
+ </View>
+ );
+ }
+}
+
+export default connect((store) => ({}), (dispatch) => bindActionCreators(actions, dispatch))(Settings)
+
+const styles = StyleSheet.create({
+ overlay: {
+ flex: 1,
+ padding: 8,
+ },
+ title: {
+ fontWeight: 'bold',
+ fontSize: 22,
+ },
+ subtitle: {
+ fontWeight: 'normal',
+ fontSize: 18,
+ }
+}); \ No newline at end of file
diff --git a/src/Main.js b/src/Main.js
index 5a67c64..4e5c128 100644
--- a/src/Main.js
+++ b/src/Main.js
@@ -1,12 +1,14 @@
import React, { Component } from 'react';
-import { Platform, StyleSheet, Text, View } from 'react-native';
+import { View } from 'react-native';
import { connect } from 'redux-su';
+import IconComponent from 'react-native-vector-icons/Ionicons';
import Login from './Components/Login';
import Map from './Components/Map';
import PortalPanel from './Components/PortalPanel';
-import { createStackNavigator, createAppContainer } from 'react-navigation';
+import { createStackNavigator, createBottomTabNavigator, createAppContainer } from 'react-navigation';
+import Settings from './Components/Settings';
-const AppNavigator = createStackNavigator({
+const MapNavigator = createStackNavigator({
Map: {
screen: Map,
navigationOptions: {
@@ -15,12 +17,26 @@ const AppNavigator = createStackNavigator({
},
Portal: {
screen: PortalPanel,
- navigationOptions: () => ({
- headerMode: 'float',
- headerBackTitle: null
- })
},
});
+
+const AppNavigator = createBottomTabNavigator({
+ Map: {
+ screen: MapNavigator,
+ navigationOptions: {
+ tabBarLabel: 'Карта',
+ tabBarIcon: ({tintColor}) => <IconComponent name={'ios-map'} size={25} color={tintColor} />
+ }
+ },
+ Settings: {
+ screen: Settings,
+ navigationOptions: {
+ tabBarLabel: 'Настройки',
+ tabBarIcon: ({tintColor}) => <IconComponent name={'ios-settings'} size={25} color={tintColor} />
+ }
+ }
+})
+
const AppContainer = createAppContainer(AppNavigator)
class App extends Component {
render() {
diff --git a/src/Store/store.ts b/src/Store/store.ts
index 0929882..c26f019 100644
--- a/src/Store/store.ts
+++ b/src/Store/store.ts
@@ -4,12 +4,6 @@ import { createReducer } from 'redux-su';
import { composeWithDevTools } from 'redux-devtools-extension';
import { Portal, Link, Field } from '../Api/types';
-type Display = {
- portals: string[],
- fields: string[],
- links: string[]
-}
-
const reducers = {
'auth': createReducer({
'authSet': (store: any, action: { v: string, csrf: string, user: any }) => ({ v: action.v, csrf: action.csrf, user: action.user, loading: false }),
@@ -39,12 +33,10 @@ const reducers = {
({ ...store, links: { ...store.links, ...action.links } }),
'fieldsSet': (store: any, action: { fields: { [guid: string]: Field } }) =>
({ ...store, fields: { ...store.fields, ...action.fields } }),
- 'entitiesLoad': (store: any, action: { loading: number }) =>
- ({ ...store, loading: action.loading }),
- 'entitiesDisplay': (store: any, action: { display: Display }) =>
- ({ ...store, display: action.display }),
+ 'setLoad': (store: any, action: { queue: string[][] }) =>
+ ({ ...store, loadQueue: [...action.queue] }),
- }, { portals: {}, fields: {}, links: {}, loading: 0, display: { portals: [], fields: [], links: [] } })
+ }, { portals: {}, fields: {}, links: {}, loadQueue: [] })
}
function extend(obj: any, src: any) {
diff --git a/src/colors.ts b/src/colors.ts
index 13b5e4f..8a3a508 100644
--- a/src/colors.ts
+++ b/src/colors.ts
@@ -1,3 +1,4 @@
export const COLORS = ['#FF6600', '#0088FF', '#03DC03']; // none, res, enl
+export const COLORS_FRACTION = { 'N': COLORS[0], 'R': COLORS[1], 'E': COLORS[2] }; // none, res, enl
export const COLORS_LVL = ['#000', '#FECE5A', '#FFA630', '#FF7315', '#E40000', '#FD2992', '#EB26CD', '#C124E0', '#9627F4'];
export const COLORS_MOD = { VERY_RARE: '#b08cff', RARE: '#73a8ff', COMMON: '#8cffbf' }; \ No newline at end of file