diff options
author | Alexander NeonXP Kiryukhin <a.kiryukhin@mail.ru> | 2019-06-11 02:51:30 +0300 |
---|---|---|
committer | Alexander NeonXP Kiryukhin <a.kiryukhin@mail.ru> | 2019-06-11 02:51:30 +0300 |
commit | f12a3bccd8c726e59e92123a3d8ef1f5a73d7253 (patch) | |
tree | d4b6e126c0f216972562621608a4ba97800a94bf /src/Components | |
parent | b7810c3d6c0164def328c60244bfbd20d7935bc3 (diff) |
Fixes
Diffstat (limited to 'src/Components')
-rw-r--r-- | src/Components/Map.tsx | 17 | ||||
-rw-r--r-- | src/Components/MapObjects.tsx | 32 | ||||
-rw-r--r-- | src/Components/MapOverlay.tsx | 177 | ||||
-rw-r--r-- | src/Components/PortalPanel.tsx | 1 | ||||
-rw-r--r-- | src/Components/Settings.tsx | 49 |
5 files changed, 170 insertions, 106 deletions
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, |