diff --git a/js/enhancers/foodItemEnhancers.js b/js/enhancers/foodItemEnhancers.js index eec438d..4194621 100644 --- a/js/enhancers/foodItemEnhancers.js +++ b/js/enhancers/foodItemEnhancers.js @@ -30,10 +30,10 @@ const intoSet = reducer => items => { }; export const withFoodItems = mapPropsStream(props$ => - props$.combineLatest(FoodItems$, (props, foodItems) => { + props$.combineLatest(FoodItems$, (props, foodItemsMap) => { return { ...props, - foodItemsMap: foodItems && foodItems, + foodItemsMap, }; }) ); diff --git a/js/helpers/CoordinatesHelpers.js b/js/helpers/CoordinatesHelpers.js new file mode 100644 index 0000000..9841f73 --- /dev/null +++ b/js/helpers/CoordinatesHelpers.js @@ -0,0 +1,32 @@ +import { memoize } from 'ramda'; + +export const getZoomBox = memoize((foodItemsMap, coords) => + foodItemsMap.reduce( + (prev, foodItem) => { + const minLat = + !prev.minLat || prev.minLat > foodItem.latitude ? foodItem.latitude : prev.minLat; + + const maxLat = + !prev.maxLat || prev.maxLat < foodItem.latitude ? foodItem.latitude : prev.maxLat; + + const minLng = + !prev.minLng || prev.minLng > foodItem.longitude ? foodItem.longitude : prev.minLng; + + const maxLng = + !prev.maxLng || prev.maxLng < foodItem.longitude ? foodItem.longitude : prev.maxLng; + + return { + minLat, + maxLat, + minLng, + maxLng, + }; + }, + { + minLat: coords.latitude, + maxLat: coords.latitude, + minLng: coords.longitude, + maxLng: coords.longitude, + } + ) +); diff --git a/js/pages/FoodMap.js b/js/pages/FoodMap.js index 8eb3255..c1af230 100644 --- a/js/pages/FoodMap.js +++ b/js/pages/FoodMap.js @@ -4,14 +4,14 @@ import { View } from 'react-native'; import typeof FoodItemRecord from '../records/FoodItemRecord'; import { withFoodItems } from '../enhancers/foodItemEnhancers'; import { withLocation } from '../enhancers/locationEnhancers'; -import { compose, renderComponent, withState } from 'recompose'; +import { compose, renderComponent, withState, withProps } from 'recompose'; import { Map } from 'immutable'; import MapView from 'react-native-maps'; -import { path } from 'ramda'; import { routeWithTitle } from '../helpers/RouteHelpers'; import FoodItemTile from '../components/FoodItemTile'; import ActionsButton from '../components/ActionsButton'; import FilterModal from '../modals/FilterModal'; +import { getZoomBox } from '../helpers/CoordinatesHelpers'; type Region = { latitude: number, @@ -23,6 +23,7 @@ type Region = { type Props = { foodItemsMap: Map, location: Location, + initialRegion: Region, region: Region, onRegionChange: Region => void, pushRoute: () => {}, @@ -31,17 +32,18 @@ type Props = { }; const FoodMap = ({ - foodItemsMap = Map(), + foodItemsMap, region, onRegionChange, pushRoute, toggleFilterModal, isFilterModalOpen, + initialRegion, }: Props) => { - return ( + return !foodItemsMap ? null : ( @@ -76,16 +78,23 @@ const FoodMap = ({ ); }; +const withInitialRegionProp = withProps(({ foodItemsMap = Map(), location }) => { + const zoomBox = getZoomBox(foodItemsMap, location.coords); + + return { + initialRegion: { + latitude: (zoomBox.minLat + zoomBox.maxLat) / 2, + longitude: (zoomBox.minLng + zoomBox.maxLng) / 2, + latitudeDelta: zoomBox.maxLat - zoomBox.minLat + 0.02, + longitudeDelta: zoomBox.maxLng - zoomBox.minLng + 0.02, + }, + }; +}); + export default compose( renderComponent, withFoodItems, withLocation, - withState('region', 'onRegionChange', ({ location }) => { - return { - latitude: path(['coords', 'latitude'], location), - longitude: path(['coords', 'longitude'], location), - latitudeDelta: 0.07, - longitudeDelta: 0.07, - }; - }) + withState('region', 'onRegionChange', null), + withInitialRegionProp )(FoodMap); diff --git a/js/streams/LocationStream.js b/js/streams/LocationStream.js index bd3ec1e..783c13b 100644 --- a/js/streams/LocationStream.js +++ b/js/streams/LocationStream.js @@ -1,12 +1,12 @@ // @flow import { ReplaySubject } from 'rxjs'; -const multicaster: ReplaySubject = new ReplaySubject(); +const subject: ReplaySubject = new ReplaySubject(); export function emitter(val: ?Position) { - multicaster.next(val); + subject.next(val); } emitter(null); -export default multicaster; +export default subject;