summaryrefslogtreecommitdiff
path: root/src/Components/Map.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/Components/Map.tsx')
-rw-r--r--src/Components/Map.tsx180
1 files changed, 180 insertions, 0 deletions
diff --git a/src/Components/Map.tsx b/src/Components/Map.tsx
new file mode 100644
index 0000000..3e878f8
--- /dev/null
+++ b/src/Components/Map.tsx
@@ -0,0 +1,180 @@
+import React, { Component } from 'react';
+import { StyleSheet, View, Dimensions, ActivityIndicator } from 'react-native';
+import MapView, { Marker, Region, UrlTile } from 'react-native-maps';
+import { connect } from 'redux-su';
+import { NavigationActions } from 'react-navigation';
+
+import MapOverlay from './MapOverlay';
+import MapObjects from './MapObjects';
+import PortalPanel from './PortalPanel';
+import { getBottomSpace } from '../helper';
+import actions from '../Actions/actions';
+import { LatLng } from '../Api/interfaces';
+
+const { width, height } = Dimensions.get("screen")
+const draggableRange = {
+ top: height / 1.75,
+ bottom: 120 + getBottomSpace()
+}
+
+type Props = any
+type State = any
+class Map extends Component<Props, State> {
+ refresh: 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 },
+ }
+ }
+ componentWillMount() {
+ navigator.geolocation.getCurrentPosition(
+ position => {
+ this.setState({
+ followUser: true,
+ });
+ },
+ 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
+ },
+ });
+ },
+ error => alert(error.message),
+ { enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 }
+ )
+ }
+ onRegionChange = (region: Region) => {
+ const zoom = this.getZoomByRegion(width, region)
+ this.setState({ region, zoom })
+ setImmediate(() => this.load(false))
+ }
+ getZoomByRegion(width: number, region: Region): number {
+ return Math.ceil(Math.log2(360 * ((width / 256) / region.longitudeDelta))) + 1
+ }
+ load = async (refresh: boolean) => {
+ if (this.state.region != null && this.props.entities.loading == 0) {
+ 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 } })
+ }
+
+ onOpenPortal = (guid: string, coords: LatLng) => {
+ const navigateAction = NavigationActions.navigate({
+ routeName: 'Portal',
+ params: { guid, coords },
+ });
+ this.props.navigation.dispatch(navigateAction);
+ }
+
+ 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
+ ref={r => (r != null) ? this.map = r : null}
+ style={styles.container}
+ initialRegion={{ ...this.state.user, latitudeDelta: 0.002, longitudeDelta: 0.002 }}
+ onRegionChangeComplete={this.onRegionChange}
+ showsCompass={false}
+ showsScale
+ showsUserLocation
+ showsMyLocationButton
+ loadingEnabled
+ type={'hybrid'}
+ >
+ <MapObjects onPortalClick={this.onPortalClick} zoom={this.state.zoom} />
+ {this.state.selectedPortal && <Marker coordinate={this.state.selectedPortal.coords} />}
+ </MapView>
+ <MapOverlay
+ goToMe={goToMe}
+ refresh={refresh}
+ loading={this.props.entities.loading}
+ selectedPortal={this.state.selectedPortal}
+ onOpenPortal={this.onOpenPortal}
+ />
+ </>
+ );
+ }
+}
+
+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