Skip to content

Commit e411ae0

Browse files
committed
Add basic geolocation request
1 parent 02b964b commit e411ae0

File tree

5 files changed

+114
-5
lines changed

5 files changed

+114
-5
lines changed

apps/web-api-demo/geolocation.html

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<title>web-api demo</title>
6+
<base href="/" />
7+
8+
<meta name="viewport" content="width=device-width, initial-scale=1" />
9+
<link rel="icon" type="image/x-icon" href="favicon.ico" />
10+
</head>
11+
<body>
12+
<section>
13+
<h2>Geolocation</h2>
14+
15+
<p>latitude: <span id="latitude" /></p>
16+
<p>longitude: <span id="longitude" /></p>
17+
18+
<button id="get-location">Get Location</button>
19+
</section>
20+
<script type="module" src="/src/geolocation.ts"></script>
21+
</body>
22+
</html>

apps/web-api-demo/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ <h1>@withease/web-api</h1>
1616
<li><a href="/page-visibility.html">page-visibility</a></li>
1717
<li><a href="/screen-orientation.html">screen-orientation</a></li>
1818
<li><a href="/preferred-languages.html">preferred-languages</a></li>
19+
<li><a href="/geolocation.html">geolocation</a></li>
1920
</ul>
2021
</body>
2122
</html>

apps/web-api-demo/src/geolocation.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { trackGeolocation } from '@withease/web-api';
2+
3+
const latitudeElement = document.querySelector('#latitude')!;
4+
const longitudeElement = document.querySelector('#longitude')!;
5+
const getLocationButton = document.querySelector('#get-location')!;
6+
7+
const { $latitude, $longitude, request } = trackGeolocation({});
8+
9+
$latitude.watch((latitude) => {
10+
console.log('latitude', latitude);
11+
latitudeElement.textContent = JSON.stringify(latitude);
12+
});
13+
$longitude.watch((longitude) => {
14+
console.log('longitude', longitude);
15+
longitudeElement.textContent = JSON.stringify(longitude);
16+
});
17+
18+
getLocationButton.addEventListener('click', () => request());
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { expect, test } from '@playwright/test';
2+
3+
const GEOLOCATION_PAGE = '/geolocation.html';
4+
5+
test.use({
6+
geolocation: { longitude: 41.890221, latitude: 12.492348 },
7+
permissions: ['geolocation'],
8+
});
9+
10+
test('should show geolocation', async ({ page, context }) => {
11+
await page.goto(GEOLOCATION_PAGE);
12+
13+
const latitudeContainer = await page.$('#latitude');
14+
const longitudeContainer = await page.$('#longitude');
15+
const getLocationButton = await page.$('#get-location');
16+
17+
// By default it should be null
18+
expect(await latitudeContainer!.textContent()).toBe('null');
19+
expect(await longitudeContainer!.textContent()).toBe('null');
20+
21+
// After requesting the location, it should be updated
22+
await getLocationButton!.click();
23+
expect(await latitudeContainer!.textContent()).toBe('12.492348');
24+
expect(await longitudeContainer!.textContent()).toBe('41.890221');
25+
26+
// Change geolocation, values should NOT be updated
27+
await context.setGeolocation({ longitude: 22.492348, latitude: 32.890221 });
28+
expect(await latitudeContainer!.textContent()).toBe('12.492348');
29+
expect(await longitudeContainer!.textContent()).toBe('41.890221');
30+
// Request the location again, values should be updated
31+
await getLocationButton!.click();
32+
expect(await latitudeContainer!.textContent()).toBe('32.890221');
33+
expect(await longitudeContainer!.textContent()).toBe('22.492348');
34+
});

packages/web-api/src/geolocation.ts

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,17 @@ export function trackGeolocation(
8080
providers?: Array<CustomProvider | globalThis.Geolocation>;
8181
}
8282
): Geolocation {
83-
// In case of no providers, we will use the default one only
84-
const providres = params.providers ?? [BrowserProvider];
83+
const providres = (
84+
params.providers ?? /* In case of no providers, we will use the default one only */ [
85+
BrowserProvider,
86+
]
87+
).map(
88+
/* BrowserProvider symbol means usage of navigator.geolocation */
89+
(provider) =>
90+
(provider === BrowserProvider ? navigator.geolocation : provider) as
91+
| CustomProvider
92+
| globalThis.Geolocation
93+
);
8594

8695
// -- units
8796

@@ -128,9 +137,26 @@ export function trackGeolocation(
128137
void,
129138
CustomGeolocationPosition | globalThis.GeolocationPosition,
130139
CustomGeolocationError | globalThis.GeolocationPositionError
131-
>(() => {
132-
// TODO: real code
133-
throw { code: 'POSITION_UNAVAILABLE', message: 'Not implemented' };
140+
>(async () => {
141+
let geolocation: GeolocationPosition | null = null;
142+
143+
for (const provider of providres) {
144+
if (isDefaultProvider(provider)) {
145+
geolocation = await new Promise<GeolocationPosition>(
146+
(resolve, rejest) =>
147+
provider.getCurrentPosition(resolve, rejest, params)
148+
);
149+
}
150+
}
151+
152+
if (!geolocation) {
153+
throw {
154+
code: 'POSITION_UNAVAILABLE',
155+
message: 'No avaiable geolocation provider',
156+
};
157+
}
158+
159+
return geolocation;
134160
});
135161

136162
sample({ clock: request, target: getCurrentPositionFx });
@@ -183,3 +209,11 @@ export function trackGeolocation(
183209
}
184210

185211
trackGeolocation.browserProvider = BrowserProvider;
212+
213+
function isDefaultProvider(provider: any): provider is globalThis.Geolocation {
214+
return (
215+
'getCurrentPosition' in provider &&
216+
'watchPosition' in provider &&
217+
'clearWatch' in provider
218+
);
219+
}

0 commit comments

Comments
 (0)