Skip to content

Commit ca27617

Browse files
Implement Geolocation API types in spark_web
Added support for the Geolocation Web API with a platform-agnostic interface, a `package:web` browser implementation, and a server-side no-op implementation. - Created `packages/spark_web/lib/src/geolocation.dart` with `Geolocation` interface and data classes. - Created `packages/spark_web/lib/src/server/geolocation.dart` with no-op implementation. - Created `packages/spark_web/lib/src/browser/geolocation.dart` wrapping `package:web`.
1 parent 014bd92 commit ca27617

3 files changed

Lines changed: 405 additions & 0 deletions

File tree

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/// Browser implementation of the Geolocation API wrapping `package:web`.
2+
library;
3+
4+
import 'dart:js_interop';
5+
import 'package:web/web.dart' as web;
6+
7+
import '../geolocation.dart' as iface;
8+
9+
// ---------------------------------------------------------------------------
10+
// BrowserGeolocation
11+
// ---------------------------------------------------------------------------
12+
13+
class BrowserGeolocation implements iface.Geolocation {
14+
final web.Geolocation _native;
15+
16+
BrowserGeolocation(this._native);
17+
18+
@override
19+
void getCurrentPosition(
20+
iface.PositionCallback successCallback, [
21+
iface.PositionErrorCallback? errorCallback,
22+
iface.PositionOptions? options,
23+
]) {
24+
_native.getCurrentPosition(
25+
((web.GeolocationPosition pos) =>
26+
successCallback(BrowserGeolocationPosition(pos)))
27+
.toJS,
28+
errorCallback == null
29+
? null
30+
: ((web.GeolocationPositionError err) =>
31+
errorCallback(BrowserGeolocationPositionError(err)))
32+
.toJS,
33+
_createNativeOptions(options),
34+
);
35+
}
36+
37+
@override
38+
int watchPosition(
39+
iface.PositionCallback successCallback, [
40+
iface.PositionErrorCallback? errorCallback,
41+
iface.PositionOptions? options,
42+
]) {
43+
return _native.watchPosition(
44+
((web.GeolocationPosition pos) =>
45+
successCallback(BrowserGeolocationPosition(pos)))
46+
.toJS,
47+
errorCallback == null
48+
? null
49+
: ((web.GeolocationPositionError err) =>
50+
errorCallback(BrowserGeolocationPositionError(err)))
51+
.toJS,
52+
_createNativeOptions(options),
53+
);
54+
}
55+
56+
@override
57+
void clearWatch(int watchId) => _native.clearWatch(watchId);
58+
59+
static web.PositionOptions? _createNativeOptions(
60+
iface.PositionOptions? options,
61+
) {
62+
if (options == null) return null;
63+
64+
final webOptions = web.PositionOptions(
65+
enableHighAccuracy: options.enableHighAccuracy,
66+
maximumAge: options.maximumAge,
67+
);
68+
69+
if (options.timeout != null) {
70+
webOptions.timeout = options.timeout!;
71+
}
72+
73+
return webOptions;
74+
}
75+
}
76+
77+
// ---------------------------------------------------------------------------
78+
// BrowserGeolocationPosition
79+
// ---------------------------------------------------------------------------
80+
81+
class BrowserGeolocationPosition implements iface.GeolocationPosition {
82+
final web.GeolocationPosition _native;
83+
84+
BrowserGeolocationPosition(this._native);
85+
86+
@override
87+
iface.GeolocationCoordinates get coords =>
88+
BrowserGeolocationCoordinates(_native.coords);
89+
90+
@override
91+
int get timestamp => _native.timestamp;
92+
}
93+
94+
// ---------------------------------------------------------------------------
95+
// BrowserGeolocationCoordinates
96+
// ---------------------------------------------------------------------------
97+
98+
class BrowserGeolocationCoordinates implements iface.GeolocationCoordinates {
99+
final web.GeolocationCoordinates _native;
100+
101+
BrowserGeolocationCoordinates(this._native);
102+
103+
@override
104+
double get latitude => _native.latitude;
105+
106+
@override
107+
double get longitude => _native.longitude;
108+
109+
@override
110+
double? get altitude => _native.altitude;
111+
112+
@override
113+
double get accuracy => _native.accuracy;
114+
115+
@override
116+
double? get altitudeAccuracy => _native.altitudeAccuracy;
117+
118+
@override
119+
double? get heading => _native.heading;
120+
121+
@override
122+
double? get speed => _native.speed;
123+
}
124+
125+
// ---------------------------------------------------------------------------
126+
// BrowserGeolocationPositionError
127+
// ---------------------------------------------------------------------------
128+
129+
class BrowserGeolocationPositionError
130+
implements iface.GeolocationPositionError {
131+
final web.GeolocationPositionError _native;
132+
133+
BrowserGeolocationPositionError(this._native);
134+
135+
@override
136+
int get code => _native.code;
137+
138+
@override
139+
String get message => _native.message;
140+
}
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
/// Geolocation API types matching the MDN Web API.
2+
///
3+
/// See: https://developer.mozilla.org/en-US/docs/Web/API/Geolocation_API
4+
library;
5+
6+
// ---------------------------------------------------------------------------
7+
// Callbacks
8+
// ---------------------------------------------------------------------------
9+
10+
typedef PositionCallback = void Function(GeolocationPosition position);
11+
typedef PositionErrorCallback = void Function(GeolocationPositionError error);
12+
13+
// ---------------------------------------------------------------------------
14+
// GeolocationPosition
15+
// ---------------------------------------------------------------------------
16+
17+
/// Represents the position of the concerned device at a given time.
18+
///
19+
/// See: https://developer.mozilla.org/en-US/docs/Web/API/GeolocationPosition
20+
abstract class GeolocationPosition {
21+
/// The coordinates defining the current location.
22+
GeolocationCoordinates get coords;
23+
24+
/// The time at which the location was retrieved (milliseconds since epoch).
25+
int get timestamp;
26+
}
27+
28+
// ---------------------------------------------------------------------------
29+
// GeolocationCoordinates
30+
// ---------------------------------------------------------------------------
31+
32+
/// Represents the position and altitude of the device on Earth, as well as the
33+
/// accuracy with which these properties are calculated.
34+
///
35+
/// See: https://developer.mozilla.org/en-US/docs/Web/API/GeolocationCoordinates
36+
abstract class GeolocationCoordinates {
37+
/// The position's latitude in decimal degrees.
38+
double get latitude;
39+
40+
/// The position's longitude in decimal degrees.
41+
double get longitude;
42+
43+
/// The position's altitude in meters, relative to sea level.
44+
double? get altitude;
45+
46+
/// The accuracy of the latitude and longitude properties, expressed in meters.
47+
double get accuracy;
48+
49+
/// The accuracy of the altitude expressed in meters.
50+
double? get altitudeAccuracy;
51+
52+
/// The direction in which the device is traveling, in degrees (0-360).
53+
///
54+
/// This value is 0 if the device is stationary.
55+
double? get heading;
56+
57+
/// The magnitude of the horizontal component of the device's velocity in m/s.
58+
double? get speed;
59+
}
60+
61+
// ---------------------------------------------------------------------------
62+
// GeolocationPositionError
63+
// ---------------------------------------------------------------------------
64+
65+
/// Represents the reason of an error occurring when using the geolocating device.
66+
///
67+
/// See: https://developer.mozilla.org/en-US/docs/Web/API/GeolocationPositionError
68+
abstract class GeolocationPositionError {
69+
/// The error code.
70+
int get code;
71+
72+
/// A human-readable error message.
73+
String get message;
74+
75+
/// The acquisition of the geolocation information failed because
76+
/// the page didn't have the permission to do it.
77+
static const int PERMISSION_DENIED = 1;
78+
79+
/// The acquisition of the geolocation failed because at least one
80+
/// internal source of position returned an internal error.
81+
static const int POSITION_UNAVAILABLE = 2;
82+
83+
/// The time allowed to acquire the geolocation, defined by
84+
/// [PositionOptions.timeout], was reached before the information was obtained.
85+
static const int TIMEOUT = 3;
86+
}
87+
88+
// ---------------------------------------------------------------------------
89+
// PositionOptions
90+
// ---------------------------------------------------------------------------
91+
92+
/// Options for methods [Geolocation.getCurrentPosition] and [Geolocation.watchPosition].
93+
///
94+
/// See: https://developer.mozilla.org/en-US/docs/Web/API/PositionOptions
95+
class PositionOptions {
96+
/// A boolean value that indicates the application would like to receive the
97+
/// best possible results.
98+
///
99+
/// If true and if the device is able to provide a more accurate position,
100+
/// it will do so. Note that this can result in slower response times or
101+
/// increased power consumption (with a GPS chip on a mobile device for example).
102+
/// On the other hand, if false, the device can take the liberty to save
103+
/// resources by responding more quickly and/or using less power.
104+
/// Default: false.
105+
final bool enableHighAccuracy;
106+
107+
/// A positive long value representing the maximum length of time (in milliseconds)
108+
/// the device is allowed to take in order to return a position.
109+
///
110+
/// The default value is Infinity, meaning that getCurrentPosition() won't return
111+
/// until the position is available.
112+
final int? timeout;
113+
114+
/// A positive long value indicating the maximum age in milliseconds of a
115+
/// possible cached position that is acceptable to return.
116+
///
117+
/// If set to 0, it means that the device cannot use a cached position and
118+
/// must attempt to retrieve the real current position. If set to Infinity
119+
/// the device must return a cached position regardless of its age.
120+
/// Default: 0.
121+
final int maximumAge;
122+
123+
const PositionOptions({
124+
this.enableHighAccuracy = false,
125+
this.timeout,
126+
this.maximumAge = 0,
127+
});
128+
}
129+
130+
// ---------------------------------------------------------------------------
131+
// Geolocation
132+
// ---------------------------------------------------------------------------
133+
134+
/// The Geolocation interface represents an object able to programmatically
135+
/// obtain the position of the device.
136+
///
137+
/// See: https://developer.mozilla.org/en-US/docs/Web/API/Geolocation
138+
abstract class Geolocation {
139+
/// usage: getCurrentPosition(success, error, options)
140+
void getCurrentPosition(
141+
PositionCallback successCallback, [
142+
PositionErrorCallback? errorCallback,
143+
PositionOptions? options,
144+
]);
145+
146+
/// usage: watchPosition(success, error, options)
147+
int watchPosition(
148+
PositionCallback successCallback, [
149+
PositionErrorCallback? errorCallback,
150+
PositionOptions? options,
151+
]);
152+
153+
/// usage: clearWatch(id)
154+
void clearWatch(int watchId);
155+
}

0 commit comments

Comments
 (0)