import React from "react" import { Text, SectionList, View, TouchableOpacity, TouchableHighlight, PermissionsAndroid, Platform, } from "react-native" import MapView, { Marker, Callout } from "react-native-maps" import { Icon, Header, Geolocation } from "../ui" import { MessageModal, WaitModal } from "../Modal" import { api } from "../API" import { reactAutoBind } from "auto-bind2" import { ifIphoneX } from "react-native-iphone-x-helper" import { geoDistance, workItemTypeText, pad, regionContainingPoints, dotify, } from "../util" import { ensurePermissions } from "../App" import { versionInfo } from "../version" import { config } from "../config" import KeyboardSpacer from "react-native-keyboard-spacer" import hardhatPinImage from "./images/hardhat-pin.png" import clipboardPinImage from "./images/clipboard-pin.png" import questionPinImage from "./images/question-pin.png" import moment from "moment" export class Home extends React.Component { constructor(props) { super(props) reactAutoBind(this) this.state = { waitModal: null, messageModal: null, sections: [], showWorkItems: true, haveCameraPermission: false, haveLocationPermission: false, } this.currentPosition = null this.isMapReady = false this.goToRegionWhenReady = false this.region = null if (Platform.OS !== "ios") { ensurePermissions( [ PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION, PermissionsAndroid.PERMISSIONS.CAMERA, PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE, ], { title: versionInfo.title, message: "This app needs these permissions so that you can " + "find, access and photograph geo located items.", }, (results) => { if ( results[PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION] === PermissionsAndroid.RESULTS.GRANTED ) { this.setState({ haveLocationPermission: true }) } if ( results[PermissionsAndroid.PERMISSIONS.CAMERA] === PermissionsAndroid.RESULTS.GRANTED ) { this.setState({ haveCameraPermission: true }) } }, () => { this.setState({ messageModal: { icon: "hand", message: "You have denied the app access to phone features it needs to function. " + "Some parts of the app are disabled.", detail: "To enable these features in future " + "please go to Settings.", }, }) } ) } else { navigator.geolocation.requestAuthorization() this.state.haveLocationPermission = true this.state.haveCameraPermission = true } } componentDidMount() { this.loadWorkItems() } loadWorkItems() { this.setState({ waitModal: { message: "Loading Work Items..." } }) api .listTeams() .then((list) => { this.teams = list.items return api.listWorkItemActivities() }) .then((list) => { this.setState({ waitModal: null }) list.items.forEach((item) => { item.data.forEach((datum) => { const team = this.teams.find((team) => team._id === datum.team) datum.teamName = team ? team.name : "???" }) }) this.setState({ sections: list.items, }) this.region = regionContainingPoints( list.items.map((item) => item.coordinate), config.homeRegionInset ) || config.initialRegion if (this.isMapReady) { this.mapView.animateToRegion(this.region) } else { this.goToRegionWhenReady = true } }) .catch((err) => { this.setState({ waitModal: null, messageModal: { icon: "hand", message: "Unable to get a list of work items, activities and teams", detail: err.message, }, }) }) } handleMessageDismiss() { this.setState({ messageModal: null }) } handleOnMapReady() { if (this.goToRegionWhenReady) { this.mapView.animateToRegion(this.region) this.goToRegionWhenReady = false } this.isMapReady = true } handleMarkerPress(e, sectionIndex) { if (this.sectionList) { this.sectionList.scrollToLocation({ sectionIndex, itemIndex: 0, viewOffset: 45, }) } } handleWorkItemsListPress() { if (this.currentPosition) { const { coords } = this.currentPosition this.props.history.push( `/workItemList?latLng=${coords.latitude},${coords.longitude}` ) } } handleItemSelect(activity) { this.props.history.push(`/activity?id=${activity._id}`) } handleSectionSelect(workItem) { if (!this.isMapReady) { return } const { latitude, longitude } = workItem.coordinate this.region = { latitude, longitude, latitudeDelta: config.homeRegionDelta, longitudeDelta: config.homeRegionDelta, } this.mapView.animateToRegion(this.region) } handleLogoutPress() { this.props.history.replace("/logout") } handleGlassesPress() { const { sections: workItems } = this.state if (this.currentPosition) { const { latitude: latitude1, longitude: longitude1, } = this.currentPosition.coords let closestWorkItem = config.alwaysShowWorkItemInAR ? workItems[0] : null let shortestDistance = config.minDistanceToItem workItems.forEach((workItem) => { const { latitude: latitude2, longitude: longitude2, } = workItem.coordinate const distance = geoDistance(latitude1, longitude1, latitude2, longitude2, "K") * 1000 if (distance <= shortestDistance) { closestWorkItem = workItem shortestDistance = distance } }) this.props.history.push( `/arviewer${ closestWorkItem ? "?workItemId=" + closestWorkItem._id + "&workItemType=" + closestWorkItem.workItemType : "" }` ) } } handleMyLocationPress() { if (this.currentPosition && this.isMapReady) { const { coords } = this.currentPosition this.mapView.animateToCoordinate({ latitude: coords.latitude, longitude: coords.longitude, }) } } handleToggleWorkItemsList() { const newShowWorkItems = !this.state.showWorkItems this.setState({ showWorkItems: newShowWorkItems }) if (newShowWorkItems) { this.loadWorkItems() } } handleCalloutPress(workItem) { if (api.loggedInUser.administrator) { this.props.history.push( `/arviewer?workItemId=${workItem._id}&workItemType=${ workItem.workItemType }` ) } } handlePositionUpdate(position) { this.currentPosition = position } getCoordinateDistance(coordinate) { if (this.currentPosition) { const { coords } = this.currentPosition const { latitude, longitude } = coordinate return ( geoDistance( coords.latitude, coords.longitude, latitude, longitude, "K" ).toFixed(2) + " km" ) } else { return "?" } } render() { const { sections, showWorkItems, messageModal, waitModal, haveCameraPermission, haveLocationPermission, } = this.state return (
{ this.mapView = ref }} style={[ { width: "100%", }, showWorkItems && { height: "40%" }, !showWorkItems && { flexGrow: 1 }, ]} showsUserLocation showsBuildings={false} showsTraffic={false} showsIndoors={false} zoomControlEnabled={false} showsMyLocationButton={false} initialRegion={config.initialRegion} onMapReady={this.handleOnMapReady}> {sections.map((workItem, index) => ( this.handleMarkerPress(e, index)}> this.handleCalloutPress(workItem)}> {pad(workItem.ticketNumber, 4) + ": " + workItemTypeText[workItem.workItemType] + " (" + this.getCoordinateDistance(workItem.coordinate) + ")"} {dotify(workItem.address)} ))} (this.sectionList = ref)} style={{ width: "100%", flexGrow: 1 }} sections={sections} stickySectionHeadersEnabled={true} renderSectionHeader={({ section: workItem }) => ( this.handleSectionSelect(workItem)}> {workItemTypeText[workItem.workItemType].toUpperCase()}{" "} {pad(workItem.ticketNumber, 4)} )} keyExtractor={(item) => item._id} renderItem={({ item: activity, section }) => { return ( this.handleItemSelect(activity)}> {activity.status.toUpperCase()} {activity.resolution} {activity.teamName + " | " + dotify(moment(activity.createdAt).format(), -15)} ) }} /> {showWorkItems ? "Hide List" : "Show List"} {haveLocationPermission && ( )} {Platform.OS === "ios" && } ) } }