Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save bradennapier/396bc82e9a16f13bd58a71fc7adb8dc5 to your computer and use it in GitHub Desktop.
Save bradennapier/396bc82e9a16f13bd58a71fc7adb8dc5 to your computer and use it in GitHub Desktop.
import { Process } from 'redux-saga-process';
import { call, put } from 'redux-saga/effects';
import { createSelector } from 'reselect';
import { createTaskManager } from 'saga-task-manager';
import startUserPositionObserver from 'saga-geolocation-observer';
import handleUserPosition from './sagas/handleUserPosition';
const nilLocation = {
accuracy: undefined,
latitude: undefined,
longitude: undefined,
lastUpdated: undefined,
};
const buildType = (type, config) => `${config.types.prefix}_${config.types[type]}`;
const buildConfig = config => ({
reduces: 'user',
pid: 'userLocation',
stateKey: 'location',
exports: ['actions', 'selectors'],
autoStart: false,
log: false,
initialState: nilLocation,
positionOptions: {
enableHighAccuracy: true,
},
...config,
actions: {
start: 'geolocationStart',
stop: 'geolocationStop',
...config.actions,
},
types: {
prefix: 'USER',
location: 'LOCATION',
...config.types,
},
});
function handleError(event, error) {
console.error(`[saga-process-geolocation]: ${error.message}`);
}
function handleCancelled() {
console.warn('Geolocation Observer Cancelled');
// console.warn(event, uid)
}
export default _config => {
const config = buildConfig(_config);
const processSelectors = {};
const stateKeySelector = state => state[config.reduces] && state[config.reduces][config.stateKey];
processSelectors.userLocation = createSelector(stateKeySelector, userLocation => ({
accuracy: userLocation.accuracy,
latitude: userLocation.latitude,
longitude: userLocation.longitude,
lastUpdated: userLocation.lastUpdated,
}));
const processActionRoutes = {
[config.actions.stop]: 'handleStop',
[config.actions.start]: 'handleStart',
};
const processActionCreators = {
[config.actions.stop]: null,
[config.actions.start]: null,
};
const processInitialState = {
[config.stateKey]: config.initialState,
};
const processReducer = {
[buildType('location', config)]: (state, action) => ({
...state,
[config.stateKey]: {
accuracy: action.accuracy,
latitude: action.latitude,
longitude: action.longitude,
lastUpdated: action.lastUpdated,
},
}),
};
const processConfig = {
pid: config.pid,
reduces: config.reduces,
};
class GeoLocationProcess extends Process {
constructor(processID, proc) {
super(processID, proc);
this.state = {
coords: undefined,
};
this.task = createTaskManager(processID, {
name: buildType('location', config),
log: true,
});
}
* handleStop() {
yield call([this.task, this.task.cancel], 'observers');
}
* handleStart() {
const handlers = {
onEvent: [this, this.handleEvent],
onError: [this, handleError],
onCancel: [this, handleCancelled],
};
yield* this.task.create(
'observers',
'geolocation',
startUserPositionObserver,
'user-geolocation-observer',
config.positionOptions,
handlers,
);
}
* handleEvent(event, value) {
switch (event) {
case 'watchPosition': {
const position = yield call([this, handleUserPosition], value);
if (position) {
yield put({
type: buildType('location', config),
...position,
});
}
break;
}
default: {
console.warn('[saga-process-geolocation]: Default Reached in Event handleEvnet');
}
}
}
* processStarts() {
if (config.autoStart) {
yield call([this, this.handleStart]);
}
}
}
return {
process: GeoLocationProcess,
config: processConfig,
initialState: processInitialState,
actionCreators: processActionCreators,
actionRoutes: processActionRoutes,
selectors: processSelectors,
reducer: processReducer,
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment