Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
5f861c5
Add my location button
nploi Dec 12, 2022
d9a4fa6
Move to current location when click
nploi Dec 13, 2022
1450b75
Add blue dot
nploi Dec 14, 2022
03ed666
Update my location icon
nploi Dec 14, 2022
72b6553
Add blue dot
nploi Dec 14, 2022
ea3dd73
Add animation
nploi Dec 19, 2022
64668d0
Update my location element
nploi Dec 19, 2022
e2a5a24
Update my location element
nploi Dec 19, 2022
1ae5172
Update my location element
nploi Dec 19, 2022
9abc526
Add blue dot
nploi Dec 19, 2022
b986d65
Add blue dot icon
nploi Dec 20, 2022
c358fe8
Format code
nploi Dec 20, 2022
278b043
Update UI
nploi Dec 20, 2022
a72e0a1
Update types
nploi Dec 20, 2022
7ad54b5
Revert code
nploi Dec 20, 2022
e0c6c3d
Revert code
nploi Dec 20, 2022
ea4cdef
Add integration test
nploi Dec 24, 2022
1cdce7a
Revert code
nploi Dec 24, 2022
58c74ec
Fix test fail
nploi Dec 25, 2022
7bd8aa4
Fix test fail
nploi Dec 25, 2022
1b62e8c
Add more test & fix test fail
nploi Dec 25, 2022
4d6ba54
Revert code
nploi Dec 25, 2022
9d40e2e
Fix spelling
nploi Dec 25, 2022
f3a8fc9
Updated version & changelog
nploi Dec 25, 2022
77414ec
Updated version & changelog
nploi Dec 25, 2022
6668606
Updated version & changelog
nploi Dec 25, 2022
1b4b0bb
Move code to separate file, update logic, add mylocation-sprite-2x to…
nploi Dec 28, 2022
241f69d
Update logic watch position and check permission
nploi Dec 31, 2022
c0fff06
Rename method
nploi Dec 31, 2022
1747092
Revert code
nploi Dec 31, 2022
dd51548
Fix unit-test & fix logic
nploi Jan 1, 2023
c99c506
Update blue dot icon & add todo me
nploi Jan 1, 2023
6c0aecd
Fix lint
nploi Jan 1, 2023
cbc6bc2
Add unit-test for location permission
nploi Jan 1, 2023
766d690
Add author
nploi Jan 1, 2023
d85e6b8
Fix error syntax
nploi Jan 1, 2023
f99bce4
Revert code
nploi Jan 1, 2023
9755380
Fix lint
nploi Jan 1, 2023
65630ef
Merge branch 'main' of https://github.com/nploi/plugins into impl-my-…
nploi Jan 11, 2023
42e307a
Fix linter
nploi Jan 11, 2023
0090120
Merge branch 'main' of https://github.com/nploi/plugins into impl-my-…
nploi Jan 23, 2023
3db8113
Merge branch 'main' into impl-my-location
nploi Jan 25, 2023
9270247
Fix linter
nploi Jan 28, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add integration test
  • Loading branch information
nploi committed Dec 25, 2022
commit ea4cdef7beb14e706f5c10e3bc6643fa2622181d
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,25 @@ void main() {
expect(controller.trafficLayer, isNotNull);
});
});

group('My Location button', () {
testWidgets('by default is disabled', (WidgetTester tester) async {
controller = createController();
controller.init();
expect(controller.myLocationButton, isNull);
});

testWidgets('initializes with my location button',
(WidgetTester tester) async {
controller = createController(
mapConfiguration: const MapConfiguration(
myLocationEnabled: true,
));
controller.debugSetOverrides(createMap: (_, __) => map);
controller.init();
expect(controller.myLocationButton, isNotNull);
});
});
});

// These are the methods that are delegated to the gmaps.GMap object, that we can mock...
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ class MockGoogleMapController extends _i1.Mock
_i4.CirclesController? circles,
_i4.PolygonsController? polygons,
_i4.PolylinesController? polylines,
_i4.DebugGetCurrentLocation? getCurrentLocation,
}) =>
super.noSuchMethod(
Invocation.method(
Expand All @@ -112,6 +113,7 @@ class MockGoogleMapController extends _i1.Mock
#circles: circles,
#polygons: polygons,
#polylines: polylines,
#getCurrentLocation: getCurrentLocation,
},
),
returnValueForMissingStub: null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
<head>
<title>Browser Tests</title>
<!-- This API key comes from: go/flutter-maps-web-tests-api-key (GCP project: flutter-infra) -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAa9cRBkhuxGq3Xw3HPz8SPwaVOhRmm7kk&libraries=geometry"></script> </head>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAq8o5-8Y5pudbJMJtDFzb8aHiWJufa5fg&libraries=geometry"></script>
</head>
<body>
<script src="main.dart.js"></script>
</body>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ part of google_maps_flutter_web;
typedef DebugCreateMapFunction = gmaps.GMap Function(
HtmlElement div, gmaps.MapOptions options);

/// Type used when passing an override to the _getCurrentLocation function.
@visibleForTesting
typedef DebugGetCurrentLocation = Future<LatLng> Function();

/// Encapsulates a [gmaps.GMap], its events, and where in the DOM it's rendered.
class GoogleMapController {
/// Initializes the GMap, and the sub-controllers related to it. Wires events.
Expand Down Expand Up @@ -64,6 +68,7 @@ class GoogleMapController {
// The Flutter widget that contains the rendered Map.
HtmlElementView? _widget;
late HtmlElement _div;
late HtmlElement _myLocationButton;

/// The Flutter widget that will contain the rendered Map. Used for caching.
Widget? get widget {
Expand All @@ -75,6 +80,10 @@ class GoogleMapController {
return _widget;
}

/// A getter for the my location button
@visibleForTesting
HtmlElement? get myLocationButton => _myLocationButton;

// The currently-enabled traffic layer.
gmaps.TrafficLayer? _trafficLayer;

Expand Down Expand Up @@ -114,14 +123,19 @@ class GoogleMapController {
CirclesController? circles,
PolygonsController? polygons,
PolylinesController? polylines,
DebugGetCurrentLocation? getCurrentLocation,
}) {
_overrideCreateMap = createMap;
_markersController = markers ?? _markersController;
_circlesController = circles ?? _circlesController;
_polygonsController = polygons ?? _polygonsController;
_polylinesController = polylines ?? _polylinesController;
_overrideGetCurrentLocation = getCurrentLocation;
}

// Get current location
DebugGetCurrentLocation? _overrideGetCurrentLocation;

DebugCreateMapFunction? _overrideCreateMap;

gmaps.GMap _createMap(HtmlElement div, gmaps.MapOptions options) {
Expand Down Expand Up @@ -178,6 +192,7 @@ class GoogleMapController {
);

_setTrafficLayer(map, _lastMapConfiguration.trafficEnabled ?? false);

if (_lastMapConfiguration.myLocationEnabled! &&
_lastMapConfiguration.myLocationButtonEnabled!) {
_addMyLocationButton(map);
Expand Down Expand Up @@ -422,7 +437,7 @@ class GoogleMapController {
}

// Add My Location widget to right bottom
void _addMyLocationButton(gmaps.GMap map) {
HtmlElement _createMyLocationButton() {
final HtmlElement controlDiv = DivElement();
controlDiv.style.marginRight = '10px';

Expand Down Expand Up @@ -467,31 +482,50 @@ class GoogleMapController {
});
});

map.addListener('dragend', () {
document.getElementById('you_location_img')?.style.backgroundPosition =
'0px 0px';
});
return controlDiv;
}

map.controls![gmaps.ControlPosition.RIGHT_BOTTOM as int]?.push(controlDiv);
// Get current location
Future<LatLng> _getCurrentLocation() async {
final Geoposition location =
await window.navigator.geolocation.getCurrentPosition();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method will not update the user's location if they move around, unless something else on the map changes. I think this should use the watchPosition API, that returns a Stream<Geoposition> and then respond to the events from that stream. Some changes to this PR:

  • If the user wants to render the MyLocation dot: subscribe to the watchPosition Stream, and on each Geolocation event update the Marker.
    • The first event of the watchPosition Stream can be used to remove the "waiting" animation class from the button, for example, and to get ready the marker that needs to be rendered.
  • If the user wants to stop rendering their location, it's easy to remove whatever subscription to the Stream that we do, and whatever cleanup is needed.

Some documentation:

return LatLng(
location.coords!.latitude!.toDouble(),
location.coords!.longitude!.toDouble(),
);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two things here:

  1. What happens when the user denies the geolocation request from the browser? Does the await never return, or does this throw an error? There's a timeout property in the getCurrentPosition method that can be used to get this "unstuck" (say: wait for 30 seconds then fail).
  2. We're discarding a lot of information from coords, like its accuracy, heading and speed. Those can be used to:
    • Render a bigger "blue halo" around the current position marker when the accuracy is low.
    • Render the direction in which we're looking at with a small "cone" using the heading information.
    • Render the current position marker as an arrow when the current position is "moving" (speed > certain threshold), and the direction in which the arrow should point (again, with the heading information).

accuracy-and-heading

I think this should at least handle "1" gracefully. 2 can be left as a "todo" or a continuation to this PR.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm fixed "1", but i think i should do "2" in next pr :D

}

// Find and move to current location
Future<void> _moveToCurrentLocation() async {
final Geoposition location =
await window.navigator.geolocation.getCurrentPosition();
LatLng location;
if (_overrideGetCurrentLocation != null) {
location = await _overrideGetCurrentLocation!.call();
} else {
location = await _getCurrentLocation();
}

await moveCamera(
CameraUpdate.newLatLng(LatLng(
location.coords!.latitude!.toDouble(),
location.coords!.longitude!.toDouble(),
)),
CameraUpdate.newLatLng(location),
);

_addBlueDot(location);
}

// Add my location to map
void _addMyLocationButton(gmaps.GMap map) {
_myLocationButton = _createMyLocationButton();

map.addListener('dragend', () {
document.getElementById('you_location_img')?.style.backgroundPosition =
'0px 0px';
});

map.controls![gmaps.ControlPosition.RIGHT_BOTTOM as int]
?.push(_myLocationButton);
}

// Add blue dot for current location
Future<void> _addBlueDot(Geoposition location) async {
print('add blue dot');
Future<void> _addBlueDot(LatLng location) async {
assert(
_markersController != null, 'Cannot update markers after dispose().');
final BitmapDescriptor icon = await BitmapDescriptor.fromAssetImage(
Expand All @@ -502,10 +536,7 @@ class GoogleMapController {
_markersController?._addMarker(Marker(
markerId: const MarkerId('my_location_blue_dot'),
icon: icon,
position: LatLng(
location.coords!.latitude!.toDouble(),
location.coords!.longitude!.toDouble(),
),
position: location,
zIndex: 0.5,
));
}
Expand Down