mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Move Geolocation JS code to FB internal
Summary: This removes the JS parts of Geolocation from React Native open source. Reviewed By: yungsters Differential Revision: D14693179 fbshipit-source-id: 1da5b7ec0e3e9d21d2019b7ee43e5f85661795b4
This commit is contained in:
committed by
Facebook Github Bot
parent
1b51cd488a
commit
9834c580af
@@ -1,182 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const NativeEventEmitter = require('NativeEventEmitter');
|
||||
const RCTLocationObserver = require('NativeModules').LocationObserver;
|
||||
|
||||
const invariant = require('invariant');
|
||||
const logError = require('logError');
|
||||
const warning = require('fbjs/lib/warning');
|
||||
|
||||
const LocationEventEmitter = new NativeEventEmitter(RCTLocationObserver);
|
||||
|
||||
const Platform = require('Platform');
|
||||
const PermissionsAndroid = require('PermissionsAndroid');
|
||||
|
||||
let subscriptions = [];
|
||||
let updatesEnabled = false;
|
||||
|
||||
type GeoConfiguration = {
|
||||
skipPermissionRequests: boolean,
|
||||
};
|
||||
|
||||
export type GeoOptions = {
|
||||
timeout?: number,
|
||||
maximumAge?: number,
|
||||
enableHighAccuracy?: boolean,
|
||||
distanceFilter?: number,
|
||||
useSignificantChanges?: boolean,
|
||||
};
|
||||
|
||||
/**
|
||||
* The Geolocation API extends the web spec:
|
||||
* https://developer.mozilla.org/en-US/docs/Web/API/Geolocation
|
||||
*
|
||||
* See https://facebook.github.io/react-native/docs/geolocation.html
|
||||
*/
|
||||
const Geolocation = {
|
||||
/*
|
||||
* Sets configuration options that will be used in all location requests.
|
||||
*
|
||||
* See https://facebook.github.io/react-native/docs/geolocation.html#setrnconfiguration
|
||||
*
|
||||
*/
|
||||
setRNConfiguration: function(config: GeoConfiguration) {
|
||||
if (RCTLocationObserver.setConfiguration) {
|
||||
RCTLocationObserver.setConfiguration(config);
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* Requests Location permissions based on the key configured on pList.
|
||||
*
|
||||
* See https://facebook.github.io/react-native/docs/geolocation.html#requestauthorization
|
||||
*/
|
||||
requestAuthorization: function() {
|
||||
RCTLocationObserver.requestAuthorization();
|
||||
},
|
||||
|
||||
/*
|
||||
* Invokes the success callback once with the latest location info.
|
||||
*
|
||||
* See https://facebook.github.io/react-native/docs/geolocation.html#getcurrentposition
|
||||
*/
|
||||
getCurrentPosition: async function(
|
||||
geo_success: Function,
|
||||
geo_error?: Function,
|
||||
geo_options?: GeoOptions,
|
||||
) {
|
||||
invariant(
|
||||
typeof geo_success === 'function',
|
||||
'Must provide a valid geo_success callback.',
|
||||
);
|
||||
let hasPermission = true;
|
||||
// Supports Android's new permission model. For Android older devices,
|
||||
// it's always on.
|
||||
if (Platform.OS === 'android' && Platform.Version >= 23) {
|
||||
hasPermission = await PermissionsAndroid.check(
|
||||
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
|
||||
);
|
||||
if (!hasPermission) {
|
||||
const status = await PermissionsAndroid.request(
|
||||
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
|
||||
);
|
||||
hasPermission = status === PermissionsAndroid.RESULTS.GRANTED;
|
||||
}
|
||||
}
|
||||
if (hasPermission) {
|
||||
RCTLocationObserver.getCurrentPosition(
|
||||
geo_options || {},
|
||||
geo_success,
|
||||
geo_error || logError,
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* Invokes the success callback whenever the location changes.
|
||||
*
|
||||
* See https://facebook.github.io/react-native/docs/geolocation.html#watchposition
|
||||
*/
|
||||
watchPosition: function(
|
||||
success: Function,
|
||||
error?: Function,
|
||||
options?: GeoOptions,
|
||||
): number {
|
||||
if (!updatesEnabled) {
|
||||
RCTLocationObserver.startObserving(options || {});
|
||||
updatesEnabled = true;
|
||||
}
|
||||
const watchID = subscriptions.length;
|
||||
subscriptions.push([
|
||||
LocationEventEmitter.addListener('geolocationDidChange', success),
|
||||
error
|
||||
? LocationEventEmitter.addListener('geolocationError', error)
|
||||
: null,
|
||||
]);
|
||||
return watchID;
|
||||
},
|
||||
|
||||
/*
|
||||
* Unsubscribes the watcher with the given watchID.
|
||||
*
|
||||
* See https://facebook.github.io/react-native/docs/geolocation.html#clearwatch
|
||||
*/
|
||||
clearWatch: function(watchID: number) {
|
||||
const sub = subscriptions[watchID];
|
||||
if (!sub) {
|
||||
// Silently exit when the watchID is invalid or already cleared
|
||||
// This is consistent with timers
|
||||
return;
|
||||
}
|
||||
|
||||
sub[0].remove();
|
||||
// array element refinements not yet enabled in Flow
|
||||
const sub1 = sub[1];
|
||||
sub1 && sub1.remove();
|
||||
subscriptions[watchID] = undefined;
|
||||
let noWatchers = true;
|
||||
for (let ii = 0; ii < subscriptions.length; ii++) {
|
||||
if (subscriptions[ii]) {
|
||||
noWatchers = false; // still valid subscriptions
|
||||
}
|
||||
}
|
||||
if (noWatchers) {
|
||||
Geolocation.stopObserving();
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* Stops observing for device location changes and removes all registered listeners.
|
||||
*
|
||||
* See https://facebook.github.io/react-native/docs/geolocation.html#stopobserving
|
||||
*/
|
||||
stopObserving: function() {
|
||||
if (updatesEnabled) {
|
||||
RCTLocationObserver.stopObserving();
|
||||
updatesEnabled = false;
|
||||
for (let ii = 0; ii < subscriptions.length; ii++) {
|
||||
const sub = subscriptions[ii];
|
||||
if (sub) {
|
||||
warning(false, 'Called stopObserving with existing subscriptions.');
|
||||
sub[0].remove();
|
||||
// array element refinements not yet enabled in Flow
|
||||
const sub1 = sub[1];
|
||||
sub1 && sub1.remove();
|
||||
}
|
||||
}
|
||||
subscriptions = [];
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = Geolocation;
|
||||
@@ -1,102 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
* @emails oncall+react_native
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
describe('Geolocation', () => {
|
||||
let Geolocation;
|
||||
const NativeModules = require('NativeModules');
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
Geolocation = jest.requireActual('Geolocation');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should set the location observer configuration', () => {
|
||||
Geolocation.setRNConfiguration({skipPermissionRequests: true});
|
||||
expect(
|
||||
NativeModules.LocationObserver.setConfiguration.mock.calls.length,
|
||||
).toEqual(1);
|
||||
});
|
||||
|
||||
it('should request authorization for location requests', () => {
|
||||
Geolocation.requestAuthorization();
|
||||
expect(
|
||||
NativeModules.LocationObserver.requestAuthorization.mock.calls.length,
|
||||
).toEqual(1);
|
||||
});
|
||||
|
||||
it('should get the current position and pass it to the given callback', () => {
|
||||
const callback = () => {};
|
||||
Geolocation.getCurrentPosition(callback);
|
||||
expect(
|
||||
NativeModules.LocationObserver.getCurrentPosition.mock.calls.length,
|
||||
).toEqual(1);
|
||||
expect(
|
||||
NativeModules.LocationObserver.getCurrentPosition.mock.calls[0][1],
|
||||
).toBe(callback);
|
||||
});
|
||||
|
||||
it('should add a success listener to the geolocation', () => {
|
||||
const watchID = Geolocation.watchPosition(() => {});
|
||||
expect(watchID).toEqual(0);
|
||||
expect(NativeModules.LocationObserver.addListener.mock.calls[0][0]).toBe(
|
||||
'geolocationDidChange',
|
||||
);
|
||||
});
|
||||
|
||||
it('should add an error listener to the geolocation', () => {
|
||||
const watchID = Geolocation.watchPosition(() => {}, () => {});
|
||||
expect(watchID).toEqual(0);
|
||||
expect(NativeModules.LocationObserver.addListener.mock.calls[1][0]).toBe(
|
||||
'geolocationError',
|
||||
);
|
||||
});
|
||||
|
||||
it('should clear the listeners associated with a watchID', () => {
|
||||
const watchID = Geolocation.watchPosition(() => {}, () => {});
|
||||
Geolocation.clearWatch(watchID);
|
||||
expect(NativeModules.LocationObserver.stopObserving.mock.calls.length).toBe(
|
||||
1,
|
||||
);
|
||||
});
|
||||
|
||||
it('should correctly assess if all listeners have been cleared', () => {
|
||||
const watchID = Geolocation.watchPosition(() => {}, () => {});
|
||||
Geolocation.watchPosition(() => {}, () => {});
|
||||
Geolocation.clearWatch(watchID);
|
||||
expect(NativeModules.LocationObserver.stopObserving.mock.calls.length).toBe(
|
||||
0,
|
||||
);
|
||||
});
|
||||
|
||||
it('should not fail if the watchID one wants to clear does not exist', () => {
|
||||
Geolocation.watchPosition(() => {}, () => {});
|
||||
Geolocation.clearWatch(42);
|
||||
expect(NativeModules.LocationObserver.stopObserving.mock.calls.length).toBe(
|
||||
0,
|
||||
);
|
||||
});
|
||||
|
||||
it('should stop observing and warn about removing existing subscriptions', () => {
|
||||
const warningCallback = jest.fn();
|
||||
jest.mock('fbjs/lib/warning', () => warningCallback);
|
||||
Geolocation.watchPosition(() => {}, () => {});
|
||||
Geolocation.stopObserving();
|
||||
expect(NativeModules.LocationObserver.stopObserving.mock.calls.length).toBe(
|
||||
1,
|
||||
);
|
||||
expect(warningCallback.mock.calls.length).toBeGreaterThanOrEqual(1);
|
||||
});
|
||||
});
|
||||
@@ -1,78 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import Geolocation from 'Geolocation';
|
||||
const React = require('react');
|
||||
const ReactNative = require('react-native');
|
||||
const {StyleSheet, Text, View, Alert} = ReactNative;
|
||||
|
||||
class GeolocationExample extends React.Component<{}, $FlowFixMeState> {
|
||||
state = {
|
||||
initialPosition: 'unknown',
|
||||
lastPosition: 'unknown',
|
||||
};
|
||||
|
||||
watchID: ?number = null;
|
||||
|
||||
componentDidMount() {
|
||||
Geolocation.getCurrentPosition(
|
||||
position => {
|
||||
const initialPosition = JSON.stringify(position);
|
||||
this.setState({initialPosition});
|
||||
},
|
||||
error => Alert.alert('Error', JSON.stringify(error)),
|
||||
{enableHighAccuracy: true, timeout: 20000, maximumAge: 1000},
|
||||
);
|
||||
this.watchID = Geolocation.watchPosition(position => {
|
||||
const lastPosition = JSON.stringify(position);
|
||||
this.setState({lastPosition});
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.watchID != null && Geolocation.clearWatch(this.watchID);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View>
|
||||
<Text>
|
||||
<Text style={styles.title}>Initial position: </Text>
|
||||
{this.state.initialPosition}
|
||||
</Text>
|
||||
<Text>
|
||||
<Text style={styles.title}>Current position: </Text>
|
||||
{this.state.lastPosition}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
title: {
|
||||
fontWeight: '500',
|
||||
},
|
||||
});
|
||||
|
||||
exports.framework = 'React';
|
||||
exports.title = 'Geolocation';
|
||||
exports.description = 'Examples of using the Geolocation API.';
|
||||
|
||||
exports.examples = [
|
||||
{
|
||||
title: 'Geolocation',
|
||||
render: function(): React.Element<any> {
|
||||
return <GeolocationExample />;
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -156,10 +156,6 @@ const APIExamples: Array<RNTesterExample> = [
|
||||
key: 'Dimensions',
|
||||
module: require('./DimensionsExample'),
|
||||
},
|
||||
{
|
||||
key: 'GeolocationExample',
|
||||
module: require('./GeolocationExample'),
|
||||
},
|
||||
{
|
||||
key: 'ImageEditingExample',
|
||||
module: require('./ImageEditingExample'),
|
||||
|
||||
@@ -231,11 +231,6 @@ const APIExamples: Array<RNTesterExample> = [
|
||||
module: require('./DimensionsExample'),
|
||||
supportsTVOS: true,
|
||||
},
|
||||
{
|
||||
key: 'GeolocationExample',
|
||||
module: require('./GeolocationExample'),
|
||||
supportsTVOS: false,
|
||||
},
|
||||
{
|
||||
key: 'ImageEditingExample',
|
||||
module: require('./ImageEditingExample'),
|
||||
|
||||
Reference in New Issue
Block a user