Skip to content

Commit 292712f

Browse files
committed
feat: improve GeoLocationSensor
1 parent e1beb5e commit 292712f

File tree

6 files changed

+146
-28
lines changed

6 files changed

+146
-28
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ const MyComponent = mock();
5858
- [`<WindowSizeSensor>`](./docs/WindowSizeSensor.md), `withWindowSize()`, and `@withWindowSize`
5959
- [`<MotionSensor>`](./docs/MotionSensor.md), [`withMotion()`](./docs/MotionSensor.md#withmotion-hoc), and [`@withMotion`](./docs/MotionSensor.md#withmotion-decorator)
6060
- [`<MouseSensor>`](./docs/MouseSensor.md), [`withMouse()`](./docs/MouseSensor.md#withmouse-hoc), and [`@withMouse`](./docs/MouseSensor.md#withmouse-decorator)
61-
- `<GeoPositionSensor>`, `withGeoPosition()`, and `@withGeoPosition`
61+
- [`<GeoLocationSensor>`](./docs/GeoLocationSensor.md), [`withGeoLocation()`](./docs/GeoLocationSensor.md#withgeolocation-hoc), and [`@withGeoLocation`](./docs/GeoLocationSensor.md#withgeolocation-decorator)
6262
- Generators
6363
- [`<Audio>`](./docs/Audio.md), [`<Video>`](./docs/Video.md), and `<Media>`
6464
- [`<LocalStorage>`](./docs/LocalStorage.md), `<SessionStorage>`, `<IndexedDb>`

docs/GeoLocationSensor.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# `<GeoLocationSensor>`
2+
3+
Render-prop/FaCC that re-renders on device location change, uses [Geolocation](https://developer.mozilla.org/en-US/docs/Web/API/Geolocation) API.
4+
5+
6+
### Props
7+
8+
None.
9+
10+
11+
### Example
12+
13+
```jsx
14+
import {GeoLocationSensor} from 'libreact/lib/GeoLocationSensor';
15+
16+
<GeoLocationSensor>{(state) =>
17+
JSON.strinfigy(state, null 4)
18+
}</GeoLocationSensor>
19+
```
20+
21+
Result
22+
23+
```json
24+
{
25+
"accuracy": 86,
26+
"altitude": null,
27+
"altitudeAccuracy": null,
28+
"heading": null,
29+
"latitude": 54.4,
30+
"longitude": -0.3,
31+
"speed": null,
32+
"timestamp": 1517137742896
33+
}
34+
```
35+
36+
## `withGeoLocation()` HOC
37+
38+
HOC that merges `geolocation` prop into enhanced component's props.
39+
40+
```jsx
41+
import {withGeoLocation} from 'libreact/lib/GeoLocationSensor';
42+
```
43+
44+
45+
## `@withGeoLocation` decorator
46+
47+
React stateful component decorator that adds `geolocation` prop.
48+
49+
```js
50+
import {withGeoLocation} from 'libreact/lib/GeoLocationSensor';
51+
52+
@withGeoLocation
53+
class MyComp extends Component {
54+
55+
}
56+
```

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "libreact",
3-
"version": "0.4.3",
3+
"version": "0.4.4",
44
"description": "React standard library",
55
"main": "lib/index.js",
66
"keywords": [

src/GeoLocation/__story__/story.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import {createElement as h} from 'react';
2+
import {storiesOf} from '@storybook/react';
3+
import {action} from '@storybook/addon-actions';
4+
import {linkTo} from '@storybook/addon-links';
5+
import {GeoLocationSensor, withGeoLocation} from '..';
6+
import ShowDocs from '../../../.storybook/ShowDocs'
7+
8+
const Print = ({geolocation}) =>
9+
<pre style={{fontFamily: 'monospace'}}>
10+
{JSON.stringify(geolocation, null, 4)}
11+
</pre>;
12+
13+
const Hoc = withGeoLocation(Print);
14+
15+
storiesOf('Sensors/GeoLocationSensor', module)
16+
.add('Documentation', () => h(ShowDocs, {name: 'GeoLocationSensor'}))
17+
.add('FaCC', () =>
18+
<GeoLocationSensor>{(state) =>
19+
<pre style={{fontFamily: 'monospace'}}>{JSON.stringify(state, null, 4)}</pre>
20+
}</GeoLocationSensor>
21+
)
22+
.add('HOC', () => <Hoc />);

src/GeoLocation/index.ts

Lines changed: 49 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,70 @@
11
import {Component} from 'react';
2-
import {SyncSensor} from '../SyncSensor';
32
import {h, on, off, isClient} from '../util';
3+
import renderProp from '../util/renderProp';
44
import faccToHoc from '../util/faccToHoc';
55

66
export interface IGeoLocationSensorProps {
77
children?: (state: IGeoLocationSensorState) => React.ReactElement<any>;
8+
render?: (state: IGeoLocationSensorState) => React.ReactElement<any>;
89
}
910

1011
export interface IGeoLocationSensorState {
11-
12+
accuracy: number,
13+
altitude: number,
14+
altitudeAccuracy: number,
15+
heading: number,
16+
latitude: number,
17+
longitude: number,
18+
speed: number,
19+
timestamp: number
1220
}
1321

14-
const DEFAULT = {
22+
export class GeoLocationSensor extends Component<IGeoLocationSensorProps, IGeoLocationSensorState> {
23+
mounted = false;
24+
watchId: number = 0;
25+
26+
state: IGeoLocationSensorState = {
27+
accuracy: null,
28+
altitude: null,
29+
altitudeAccuracy: null,
30+
heading: null,
31+
latitude: null,
32+
longitude: null,
33+
speed: null,
34+
timestamp: Date.now()
35+
};
1536

16-
};
37+
componentDidMount () {
38+
this.mounted = true;
1739

18-
const addListener = (handler) => navigator.geolocation.watchPosition(handler);
19-
const removeListener = (handler) => navigator.geolocation.clearWatch(handler);
20-
const onEvent = (event) => {
21-
console.log('event', event);
40+
navigator.geolocation.getCurrentPosition(this.onEvent);
41+
this.watchId = navigator.geolocation.watchPosition(this.onEvent);
42+
}
2243

23-
};
44+
componentWillUnmount () {
45+
this.mounted = false;
2446

25-
const getInitialState = () => {
26-
return DEFAULT;
27-
};
47+
navigator.geolocation.clearWatch(this.watchId);
48+
}
2849

29-
export class GeoLocationSensor extends Component<IGeoLocationSensorProps, any> {
30-
initial = getInitialState();
50+
onEvent = (event) => {
51+
if (this.mounted) {
52+
this.setState({
53+
accuracy: event.coords.accuracy,
54+
altitude: event.coords.altitude,
55+
altitudeAccuracy: event.coords.altitudeAccuracy,
56+
heading: event.coords.heading,
57+
latitude: event.coords.latitude,
58+
longitude: event.coords.longitude,
59+
speed: event.coords.speed,
60+
timestamp: event.timestamp
61+
});
62+
}
63+
};
3164

3265
render () {
33-
return h(SyncSensor, {
34-
children: this.props.children,
35-
initial: this.initial,
36-
addListener,
37-
removeListener,
38-
onEvent
39-
});
66+
return renderProp(this.props, this.state);
4067
}
4168
}
4269

43-
export const withMotion= faccToHoc(GeoLocationSensor, 'geolocation');
70+
export const withGeoLocation = faccToHoc(GeoLocationSensor, 'geolocation');

src/MotionSensor/index.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,22 @@ export interface IMotionSensorProps {
88
}
99

1010
export interface IMotionSensorState {
11-
angle: number;
12-
type: string;
11+
acceleration: {
12+
x: number,
13+
y: number,
14+
z: number
15+
},
16+
accelerationIncludingGravity: {
17+
x: number,
18+
y: number,
19+
z: number
20+
},
21+
rotationRate: {
22+
alpha: number,
23+
beta: number,
24+
gamma: number
25+
},
26+
interval: number
1327
}
1428

1529
const DEFAULT = {
@@ -34,7 +48,6 @@ const DEFAULT = {
3448
const addListener = (handler) => on(window, 'devicemotion', handler);
3549
const removeListener = (handler) => off(window, 'devicemotion', handler);
3650
const onEvent = (event) => {
37-
console.log('event', event);
3851
const {
3952
acceleration,
4053
accelerationIncludingGravity,
@@ -80,4 +93,4 @@ export class MotionSensor extends Component<IMotionSensorProps, any> {
8093
}
8194
}
8295

83-
export const withMotion= faccToHoc(MotionSensor, 'motion');
96+
export const withMotion = faccToHoc(MotionSensor, 'motion');

0 commit comments

Comments
 (0)