UNPKG

mappls-search-widgets-react-native

Version:

Mappls React Native Search Widget is a readymade widget used to search

565 lines (519 loc) 15.7 kB
import React from 'react'; import { View, Text, Image, Button, TouchableOpacity, NativeModules, LogBox, Platform, } from 'react-native'; import MapplsGL from 'mappls-map-react-native'; import BottomSheet from '../utils/bottomSheet'; import NetInfo from '@react-native-community/netinfo'; import Toast from 'react-native-simple-toast'; import Components from './components'; import styles from './styles'; import PropTypes from 'prop-types'; const {RNAndroidLocationEnabler} = NativeModules; const INTERNET_ERROR = [ "Oops! Something isn't right here !", "Who turned off the lights? Can't see the net !", ]; //LogBox.ignoreAllLogs(true); class MapplsPlacePicker extends React.Component { static propTypes = { center: PropTypes.arrayOf(PropTypes.number), zoom: PropTypes.number, pickerImage: PropTypes.object, showSearchIcon: PropTypes.bool, searchWidgetProps: PropTypes.shape({ location: PropTypes.array, historyCount: PropTypes.number, zoom: PropTypes.number, saveHistory: PropTypes.bool, pod: PropTypes.string, backgroundColor: PropTypes.string, tokenizeAddress: PropTypes.bool, toolbarColor: PropTypes.string, hint: PropTypes.string, filter: PropTypes.string, }), }; constructor(props) { super(props); this.state = { center: props.center, zoom: props.zoom, image: props.pickerImage != undefined ? props.pickerImage : require('../assets/pin.png'), widgetProps: props.searchWidgetProps !== undefined ? props.searchWidgetProps : {}, address: null, label: null, cameraMoving: false, twice: false, result: null, locationButtonEnabled: false, flag: false, currentLocation: null, placeWidgetActive: false, buttonColor: 'grey', mapCenter: null, interval: null, gpsEnable: false, isConnected: false, showSearchIcon: props.showSearchIcon ?? true }; this.onRegionDidChange = this.onRegionDidChange.bind(this); this.onRegionIsChanging = this.onRegionIsChanging.bind(this); } //api call and setting to state variables async revGeoCodeApi(latitude, longitude) { this.setState({ result: null, }); try { if (this.state.isConnected === true) { const result = await MapplsGL.RestApi.reverseGeocode({ latitude: latitude, longitude: longitude, }); if (result != null) { const response = result.results[0]; //console.log(result); if (response != null) { const add = response.formatted_address != '' ? response.formatted_address : 'Not available'; const labelname = response.poi != '' ? response.poi : 'Dropped Pin'; this.setState({ address: add, label: labelname, buttonColor: 'deepskyblue', result: { city: response.city, district: response.district, houseName: response.houseName, houseNumber: response.houseNumber, lat: response.lat, lng: response.lng, locality: response.locality, pincode: response.pincode, formatted_address: response.formatted_address, poi: response.poi, state: response.state, street: response.street, subDistrict: response.subDistrict, village: response.village, }, }); } } else { console.log('error api call: ' + JSON.stringify(result)); this.resultOnFail('no result'); } } else { this.resultOnFail('no internet'); } // const response = JSON.parse(obj); /* */ } catch (e) { console.log('error log: ' + e); this.resultOnFail(e.message); } } //when camera is moving onRegionIsChanging() { this.setState({ cameraMoving: true, buttonColor: 'grey', }); } //when camera ideal call api async onRegionDidChange(args) { // console.log(args.properties); this.checkInternet(); //console.log('region change done'); if (args.properties.zoomLevel !== 1) { //if getting data from placeWidget don't call api if (!this.state.placeWidgetActive) { const coor = await this._map.getCenter(); this.setState({ mapCenter: coor, }); let disabelCall = false; if ( !args.properties.animated && !args.properties.isUserInteraction && !this.state.gpsEnable && this.props.center === undefined ) { disabelCall = true; } if (!disabelCall) { if (this.clearId != null && this.props.center === undefined) { // console.log('if not null' + this.clearId); clearTimeout(this.clearId); // console.log('time canceled'); } if (this.props.center === undefined && this.clearId == null) { this.clearId = null; //console.log('time setting'); this.clearId = setTimeout(() => { this.callApiWithMapCenter(coor); }, 2000); } else { this.callApiWithMapCenter(coor); } } else { this.resultOnFail('Zoom in to pick a location.'); } } else { this.setState({ cameraMoving: false, placeWidgetActive: false, buttonColor: 'deepskyblue', }); } } } callApiWithMapCenter(coor) { this.setState({ cameraMoving: false, address: null, }); // console.log('method called'); if (coor.length === 2 && coor[1] > 0 && coor[0] > 0 && this.mount) { this.revGeoCodeApi(coor[1], coor[0]); } else { if (coor[0] < 0 || coor[1] < 0) { this.resultOnFail('drop pin'); } else { console.log('Unable to get center coordinates'); } } } //if something wrong happens call this resultOnFail(err) { this.setState({ cameraMoving: true, buttonColor: 'orange', result: { city: null, district: null, houseName: null, houseNumber: null, lat: this.state.mapCenter[1], lng: this.state.mapCenter[0], locality: null, pincode: null, formatted_address: null, poi: null, state: null, street: null, subDistrict: null, village: null, }, }); if ( err === 'Unable to resolve host "apis.mappls.com": No address associated with hostname' || err === 'no internet' ) { var randomNumber = Math.floor(Math.random() * INTERNET_ERROR.length); Toast.show(INTERNET_ERROR[randomNumber], Toast.SHORT); } else if (err === 'Zoom in to pick a location.') { Toast.show('Zoom in to pick a location.', Toast.SHORT); } else if (err === 'drop pin') { this.setState({ cameraMoving: false, address: `Latitude: ${this.state.mapCenter[1]},Longitude: ${this.state.mapCenter[1]}`, label: 'Dropped Pin', }); } else { Toast.show('Something went wrong.', Toast.SHORT); } } async enableLocationButtonClick() { this.setState({ locationButtonEnabled: true, }); if (Platform.OS === 'android') { if (this.checkLocationPermission()) { this.setState({ flag: true, }); } } else { this.setState({ flag: true, }); } const {coords} = await MapplsGL.locationManager.getLastKnownLocation(); if (coords.latitude && coords.longitude) { // console.log('Last location' + JSON.stringify(coords)); this.setState({ flag: false, }); this.camera.setCamera({ centerCoordinate: [coords.longitude, coords.latitude], zoomLevel: 16, animationDuration: 200, }); } } async componentDidMount() { // console.log(this.props.center); this.mount = true; if (this.props.center === undefined) { this.setState({ center: [77.2689, 28.5507], zoom: 2, }); this.checkLocationPermission(); } else { if (this.props.zoom === undefined) { this.setState({zoom: 16}); } } MapplsGL.locationManager.start(); } onUpdate(location) { // console.log(location); if (location) { const {latitude, longitude, accuracy} = location.coords; this.setState({currentLocation: [longitude, latitude]}); } if ( this.state.flag && this.state.currentLocation != null && this.state.currentLocation[0] > 0 && this.state.currentLocation[1] > 0 ) { this.setState({ center: this.state.currentLocation, zoom: 16, flag: false, }); } } componentWillUnmount() { this.mount = false; // console.log('unmount'); MapplsGL.locationManager.stop(); } checkInternet() { NetInfo.fetch().then(state => { // console.log(state.isConnected); this.setState({ isConnected: state.isConnected, }); }); } async checkLocationPermission() { if (Platform.OS === 'android') { const granted = await MapplsGL.requestAndroidLocationPermissions(); if (granted) { RNAndroidLocationEnabler.promptForEnableLocationIfNeeded({ interval: 10000, fastInterval: 5000, }) .then(data => { // console.log(data); this.setState({ flag: true, gpsEnable: true, }); return true; }) .catch(err => { console.log(err); this.setState({ center: [77.2689, 28.5507], zoom: 2, }); return false; }); } else { this.setState({ center: [77.2689, 28.5507], zoom: 2, }); return false; } } else { this.setState({ flag: true, gpsEnable: true, }); return true; } } async callSerachWidget() { try { const data = await Components.openPlaceWidget(this.state.widgetProps); if (data != null) { const response = data.eLocation; if (response.longitude && response.latitude) { this.camera.setCamera({ centerCoordinate: [ response.longitude, response.latitude, ], zoomLevel: 16, animationDuration: 200, }); } else { this.camera.setCamera({ centerMapplsPin: response.mapplsPin, zoomLevel: 16, animationDuration: 200, }); } this.setState({ cameraMoving: true, placeWidgetActive: true, label: response.placeName, address: response.placeAddress, result: { city: response.addressTokens?.city != undefined ? response.addressTokens.city : '', district: response.addressTokens?.district != undefined ? response.addressTokens.district : '', houseName: response.addressTokens?.houseName != undefined ? response.addressTokens?.houseName : '', houseNumber: response.addressTokens?.houseNumber != undefined ? response.addressTokens?.houseNumber : '', lat: response.latitude, lng: response.longitude, mapplsPin: response.mapplsPin, locality: response.addressTokens?.locality != undefined ? response.addressTokens?.locality : '', pincode: response.addressTokens?.pincode != undefined ? response.addressTokens?.pincode : '', formatted_address: response.placeAddress, poi: response.placeName, state: response.addressTokens?.state != undefined ? response.addressTokens?.state : '', street: response.addressTokens?.street != undefined ? response.addressTokens?.street : '', subDistrict: response.addressTokens?.subDistrict != undefined ? response.addressTokens?.subDistrict : '', village: response.addressTokens?.village != undefined ? response.addressTokens?.village : '', }, }); } } catch (e) { console.log('place widget errors :' + e); } } //done button clickListener doneButtonClick() { if (this.state.buttonColor != 'grey') { this.props.resultCallback(this.state.result); } else { Toast.show('Please wait...', Toast.SHORT); } } render() { //if only show when camera is not moving const sheet = !this.state.cameraMoving ? ( <BottomSheet address={this.state.address} label={this.state.label} /> ) : null; //enable location button const currentLocationButton = ( <TouchableOpacity style={styles.currentLocation} onPress={() => this.enableLocationButtonClick()}> <Image source={require('../assets/current-location.png')} style={{height: 50, width: 50}} /> </TouchableOpacity> ); //search button const searchFab = ( <TouchableOpacity style={styles.searchButton} onPress={() => this.callSerachWidget()}> <Image source={require('../assets/fab_search.png')} style={{height: 50, width: 50}} /> </TouchableOpacity> ); const locationComponent = this.props.center === undefined || this.state.locationButtonEnabled ? ( <MapplsGL.UserLocation visible={true} onUpdate={location => this.onUpdate(location)} /> ) : null; return ( <View style={styles.rootView}> <MapplsGL.MapView style={styles.rootView} ref={m => (this._map = m)} onRegionIsChanging={this.onRegionIsChanging} onRegionDidChange={this.onRegionDidChange}> <MapplsGL.Camera ref={c => (this.camera = c)} zoomLevel={this.state.zoom} animationMode={'flyTo'} minZoomLevel={2} centerCoordinate={this.state.center} /> {locationComponent} </MapplsGL.MapView> <Image source={this.state.image} style={styles.centerMaker} /> <View style={styles.bottomContainer}> {this.state.showSearchIcon && searchFab} <View style={styles.logoButtonRow}> {Components.mapLogo()} {currentLocationButton} </View> {sheet} <View style={styles.buttonContainer}> <Text style={styles.bottomText}> You may move the map to get exact location </Text> <View style={{width: '100%'}}> <Button title="Done" color={this.state.buttonColor} onPress={() => this.doneButtonClick()} /> </View> </View> </View> </View> ); } } export default MapplsPlacePicker;