Filter reports returned by the API based on map center

Only keep reports which are around the map center in the data returned
by the server. Filtering is done client-side for privacy reasons.
This commit is contained in:
Lucas Verney 2018-10-15 09:11:41 +02:00
parent 19cbb3165f
commit 4ff645cc43
5 changed files with 43 additions and 42 deletions

View File

@ -89,6 +89,9 @@ export const REPORT_DOWNVOTES_THRESHOLD = 1;
export const EARTH_RADIUS = 6378137; // in meters export const EARTH_RADIUS = 6378137; // in meters
// Keep reports only in a given radius around map center.
export const KEEP_REPORTS_METERS_AROUND = 10000; // in meters
export const DEFAULT_ZOOM = 17; export const DEFAULT_ZOOM = 17;
export const MIN_ZOOM = 10; export const MIN_ZOOM = 10;
export const MAX_ZOOM = 18; export const MAX_ZOOM = 18;

View File

@ -1,5 +1,6 @@
import * as api from '@/api'; import * as api from '@/api';
import * as constants from '@/constants'; import * as constants from '@/constants';
import { distance } from '@/tools';
import i18n from '@/i18n'; import i18n from '@/i18n';
import { import {
@ -22,11 +23,23 @@ import {
STORE_REPORTS, STORE_REPORTS,
} from './mutations-types'; } from './mutations-types';
export function fetchReports({ commit }) { export function fetchReports({ commit, state }) {
commit(IS_LOADING); commit(IS_LOADING);
return api.getActiveReports() return api.getActiveReports()
.then((reports) => { .then((reports) => {
commit(STORE_REPORTS, { reports }); // Filter reports which are too far
const reportsToCommit = reports.filter(
(report) => {
if (report.attributes.downvotes >= constants.REPORT_DOWNVOTES_THRESHOLD) {
return false;
}
return distance(
[report.attributes.lat, report.attributes.lng],
state.map.center,
) < 10000;
},
);
commit(STORE_REPORTS, { reports: reportsToCommit });
commit(IS_DONE_LOADING); commit(IS_DONE_LOADING);
}) })
.catch((exc) => { .catch((exc) => {

View File

@ -1,5 +1,3 @@
import { REPORT_DOWNVOTES_THRESHOLD } from '@/constants';
export function getLastLocation(state) { export function getLastLocation(state) {
const { gpx } = state.location; const { gpx } = state.location;
if (gpx.length > 0) { if (gpx.length > 0) {
@ -7,12 +5,3 @@ export function getLastLocation(state) {
} }
return null; return null;
} }
export function notDismissedReports(state) {
return state.reports.filter((item) => {
if (item.attributes.downvotes >= REPORT_DOWNVOTES_THRESHOLD) {
return false;
}
return true;
});
}

View File

@ -171,16 +171,6 @@ export const mutations = {
}, },
[types.SET_CURRENT_POSITION](state, { currentLocation }) { [types.SET_CURRENT_POSITION](state, { currentLocation }) {
state.location.gpx.push(currentLocation); state.location.gpx.push(currentLocation);
if (
!state.lastReportFetchingLocation
|| !state.lastReportFetchingLocation[0]
|| !state.lastReportFetchingLocation[1]
) {
state.lastReportFetchingLocation = [
currentLocation.latitude,
currentLocation.longitude,
];
}
}, },
[types.SET_LAST_REPORT_FETCHING_LOCATION](state, { locationLatLng }) { [types.SET_LAST_REPORT_FETCHING_LOCATION](state, { locationLatLng }) {
state.lastReportFetchingLocation = locationLatLng; state.lastReportFetchingLocation = locationLatLng;

View File

@ -64,23 +64,6 @@ function handlePositionError(error) {
} }
function setPosition(position) { function setPosition(position) {
const lastFetchingLocation = store.state.lastReportFetchingLocation;
if (
lastFetchingLocation
&& lastFetchingLocation[0] !== null
&& lastFetchingLocation[1] !== null
) {
const distanceFromPreviousPoint = distance(
[lastFetchingLocation[0], lastFetchingLocation[1]],
[position.coords.latitude, position.coords.longitude],
);
if (distanceFromPreviousPoint > constants.UPDATE_REPORTS_DISTANCE_THRESHOLD) {
store.dispatch('setLastReportFetchingLocation', {
locationLatLng: [position.coords.latitude, position.coords.longitude],
});
store.dispatch('fetchReports');
}
}
store.dispatch( store.dispatch(
'setCurrentPosition', 'setCurrentPosition',
{ coords: position.coords, timestamp: position.timestamp }, { coords: position.coords, timestamp: position.timestamp },
@ -158,7 +141,7 @@ export default {
return this.$store.state.location.gpx.map(item => [item.latitude, item.longitude]); return this.$store.state.location.gpx.map(item => [item.latitude, item.longitude]);
}, },
reportsMarkers() { reportsMarkers() {
return this.$store.getters.notDismissedReports.map(report => ({ return this.$store.state.reports.map(report => ({
id: report.id, id: report.id,
type: report.attributes.type, type: report.attributes.type,
latLng: [report.attributes.lat, report.attributes.lng], latLng: [report.attributes.lat, report.attributes.lng],
@ -230,6 +213,30 @@ export default {
this.$store.dispatch('setLocationWatcherId', { id: watchID }); this.$store.dispatch('setLocationWatcherId', { id: watchID });
}, },
onMapCenterUpdate(center) { onMapCenterUpdate(center) {
// Update reports by default
let distanceFromPreviousPoint = constants.UPDATE_REPORTS_DISTANCE_THRESHOLD + 1;
// If last fetching location is known, only update reports if not too close
const lastFetchingLocation = this.$store.state.lastReportFetchingLocation;
if (
lastFetchingLocation
&& lastFetchingLocation[0] !== null
&& lastFetchingLocation[1] !== null
) {
distanceFromPreviousPoint = distance(
[lastFetchingLocation[0], lastFetchingLocation[1]],
[center[0], center[1]],
);
}
// If necessary, refetch reports
if (distanceFromPreviousPoint > constants.UPDATE_REPORTS_DISTANCE_THRESHOLD) {
store.dispatch('setLastReportFetchingLocation', {
locationLatLng: center,
});
store.dispatch('fetchReports').catch(() => {});
}
this.$store.dispatch('setCurrentMapCenter', { center }); this.$store.dispatch('setCurrentMapCenter', { center });
}, },
onMapZoomUpdate(zoom) { onMapZoomUpdate(zoom) {
@ -314,7 +321,6 @@ export default {
this.$store.dispatch('markHasVibratedOnce'); this.$store.dispatch('markHasVibratedOnce');
} }
} }
this.$store.dispatch('fetchReports').catch(() => {});
}, },
}; };
</script> </script>