summaryrefslogtreecommitdiff
path: root/src/Components
diff options
context:
space:
mode:
Diffstat (limited to 'src/Components')
-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
6 files changed, 259 insertions, 222 deletions
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