/**
* RENAME TO SOMETHING MORE APPROPRIATE InitiationWrapper, SetupMapView
* Initiates BG plugin,
* even-listeners -> don't need them here for now !
* Possible initiation of backgroun-fetch
* Gets current position
* Possible to get current state (moving, still) and to track with odometer
*/
import React, { useState, useEffect,} from "react";
import {View} from 'react-native'
import Geolocation from 'react-native-geolocation-service';
import hasLocationPermission from "./LocationPermission";
import PositionedMapView from "../positioned-map-view/PositionedMapView";
import { addCLToStorage, addUserLocationToStorage, getUserLocationFromStorage, setUserLocaton } from "../../helpers/async_storage/AsyncStorage";
import BackgroundGeolocation from 'react-native-background-geolocation'; // Docs for the plugin https://transistorsoft.github.io/react-native-background-geolocation/
import BackgroundFetch from 'react-native-background-fetch';
import MapView from '../../../app/setup/map-view/MapView';
import {useDispatch} from 'react-redux'
import { setUserLocationCoordinates,setUserLocationHeading } from "../../reducers/UserLocationSlice";
import MapboxGL from '@rnmapbox/maps'; // DOCS https://github.com/rnmapbox/maps/tree/main/docs
const BackgroundGeolocationWrapper = ({children}) => {
const dispatch=useDispatch()
//useEffect which will refresh this part of app so interests that are added/removed from favourites will refresh
// To check if a user is logged in or not
useEffect(() => {
// const unsubscribe = auth().onAuthStateChanged(user => {
// if (user) {
// setIsUserLogged(true);
// } else {
// setIsUserLogged(false);
// }
// })
// return unsubscribe;
//Download(cache) map of Sarajevo so it can be used offline
//uncomment conosle logs in 2 functions below to see staus/error of maps being downloaded
const progressListener = (offlineRegion, status) => {//console.log(offlineRegion, status)
};
const errorListener = (offlineRegion, err) => {
//console.log(offlineRegion, err)
};
//This part below starts the actual download of map
try{
MapboxGL.offlineManager.createPack({
name: 'offlinePack',//name of the part of map being downloaded, can be anything
styleURL: MapboxGL.StyleURL.Street,//style of map which is being downloaded
minZoom: 14,//minimum zoom of downloaded map
maxZoom: 22,//maximum zoom of downloaded map, 22 max, if increased from 16 to 22 it wont increase number of tiles being downloaded
// bounds explanation: point1, point2=>[point1.longtitude,point1.latitude],[point2.longtitude,point2.latitude]
bounds: [[18.2292, 43.7934], [18.5374, 43.8878]]//area for which map will be downloaded, rectangle defined with these two points
}, progressListener, errorListener)
}
catch(e)
{
}
}, [])
// const [isMoving, setIsMoving] = React.useState(false);
// const [location, setLocation] = React.useState(null);
// const [odometer, setOdometer] = React.useState(0);
// const [motionActivityEvent, setMotionActivityEvent] = React.useState(null);
const [currentLocation, setCurrentLocation] = useState([0, 0]);
const [isDebug, setIsDebug] = useState(true)
const getBackgroundGeolocationState = async () => {
let state = await BackgroundGeolocation.getState();
if (state) {
setIsDebug(state.debug);
}
};
useEffect(() => {
//hydrate redux data
getUserLocationFromStorage().then(data=>{if(data)dispatch(setUserLocationCoordinates(data))})
getBackgroundGeolocationState();
// Subscribe to events. -> show in console
// BackgroundGeolocation.onLocation((location) => {
// // console.log('[onLocation]', location);
// })
// BackgroundGeolocation.onMotionChange((event) => {
// // console.log('[onMotionChange]', event);
// });
// BackgroundGeolocation.onActivityChange((event) => {
// // console.log('[onMotionChange]', event);
// })
// BackgroundGeolocation.onProviderChange((event) => {
// // console.log('[onProviderChange]', event);
// })
// Register BackgroundGeolocation event-listeners with setted states -> for odometer and stuff
// const locationSubscriber = BackgroundGeolocation.onLocation(setLocation, (error) => {
// console.warn('[onLocation] ERROR: ', error);
// });
// const motionChangeSubscriber = BackgroundGeolocation.onMotionChange((location) => {
// setIsMoving(location.isMoving);
// });
// const activityChangeSubscriber = BackgroundGeolocation.onActivityChange(setMotionActivityEvent);
// 2. ready the plugin.
initBackgroundGeolocation();
// Configure BackgroundFetch -> TO TEST !
// initBackgroundFetch();
// getCurrentPosition();
// Get current position for positioning map
//getCurrentPosition();
//getLocation();
// return () => {
// // When view is destroyed (or refreshed with dev live-reload), -> to test
// // Remove BackgroundGeolocation event-listeners.
// // locationSubscriber.remove();
// // motionChangeSubscriber.remove();
// // activityChangeSubscriber.remove();
// }
}, []);
useEffect(() => {
BackgroundGeolocation.setConfig({
debug: isDebug,
}).then(state => {
console.log('[setConfig] success: ', state.debug);
});
}, [isDebug]);
const debugToggle = () => {
setIsDebug(prevState => !prevState);
};
/* ### ⚠️ Warning:
Do not execute *any* API method which will require accessing location-services
until the callback to [[ready]] executes (eg: [[getCurrentPosition]], [[watchPosition]], [[start]]).
*/
const initBackgroundGeolocation = async () => {
// Ready the SDK and fetch the current state.
const state = await BackgroundGeolocation.ready({
// Geolocation Config
desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_HIGH,
distanceFilter: 10,
// Activity Recognition
stopTimeout: 5,
// Debug
debug: isDebug, // <-- enable this hear sounds for background-geolocation life-cycle.
logLevel: BackgroundGeolocation.LOG_LEVEL_VERBOSE,
// Application config
stopOnTerminate: false, // <-- Allow the background-service to continue tracking when user closes the app.
startOnBoot: true, // <-- Auto start tracking when device is powered-up.
enableHeadless: true,
// Permissions
locationAuthorizationRequest: 'Always',
backgroundPermissionRationale: {
title:
"Allow MapToBe to access this device's location even when closed or not in use.",
message:
'This app collects location data to enable recording your trips to work and calculate distance-travelled.',
positiveAction: 'Change to "{backgroundPermissionOptionLabel}"',
negativeAction: 'Cancel',
},
});
// setOdometer(state.odometer);
// setEnabled(state.enabled);
// setIsMoving(state.isMoving||false);
BackgroundGeolocation.start().then(state => {
console.log('[start] success - ', state);
getCurrentPosition();
});
// if (state.trackingMode == 1) {
// BackgroundGeolocation.start();
// } else {
// console.log("dva")
// BackgroundGeolocation.startGeofences();
// }
};
const initBackgroundFetch = async () => {
BackgroundFetch.configure(
{
minimumFetchInterval: 15,
enableHeadless: true,
stopOnTerminate: false,
},
async taskId => {
console.log('[BackgroundFetch]', taskId);
BackgroundFetch.finish(taskId);
},
taskId => {
console.log('[BackgroundFetch] TIMEOUT:', taskId);
BackgroundFetch.finish(taskId);
},
);
};
// NEW: BG get current position
// This functionality should be added on the UI also so user can locate himself
const getCurrentPosition = async () => {
// this is just for precaution
//const state = await BackgroundGeolocation.getState();
if (true) {
console.log('getting psoitions')
BackgroundGeolocation.getCurrentPosition({
persist: true,
samples: 3,
timeout: 30,
maximumAge: 5000, // Accept the last-known-location if not older than 5000 ms.
desiredAccuracy: 10, // Try to fetch a location with an accuracy of `10` meters.
extras: {
getCurrentPosition: true,
},
})
.then(location => {
console.log(
'[getCurrentPosition] success: ',
location.coords.latitude,
location.coords.longitude,
);
setCurrentLocation([
location.coords.latitude,
location.coords.longitude,
]);
addUserLocationToStorage([location.coords.longitude,location.coords.latitude ])
dispatch(setUserLocationCoordinates([location.coords.longitude,location.coords.latitude, ]))
dispatch(setUserLocationHeading(location.coords.heading))
})
.catch(error => {
console.warn('[getCurrentPosition] error: ', error);
});
}
};
/**
** Invokes hasLocationPermission from LocationPermission.js
** Invokes getCurrentPosition from Geolocation module that returns current position
** Sets currentLocation state with current position
** TODO: move this method in LocationPermission.js, invoke this method in headless task
*/
const getLocation = async () => {
const hasPermission = await hasLocationPermission();
if (!hasPermission) {
return;
}
Geolocation.getCurrentPosition(
position => {
setCurrentLocation([
position.coords.longitude,
position.coords.latitude,
]);
addUserLocationToStorage([
position.coords.latitude,
position.coords.longitude])
dispatch(setUserLocationCoordinates([
position.coords.latitude,
position.coords.longitude,
]));
dispatch(setUserLocationHeading(position.coords.heading));
// addCLToStorage([position.coords.longitude, position.coords.latitude]);
console.log('current position', currentLocation);
},
error => {
console.log(error);
},
{
/* accuracy: {
android: 'high',
ios: 'best',
},*/
enableHighAccuracy: true,
//timeout: 5000,
maximumAge: 3600000,
distanceFilter: 0,
forceRequestLocation: true,
showLocationDialog: true,
},
);
};
return (
<View style={{backgroundColor:'red',width:'100%',height:'100%'}}>
{children}
</View>);
};
export default BackgroundGeolocationWrapper;