From 2e21db183a2e1a2bb7f32e7b1771730787684605 Mon Sep 17 00:00:00 2001 From: nploi Date: Sun, 16 Jul 2023 21:44:08 +0700 Subject: [PATCH 1/5] Implement my location & unit-test --- .../google_maps_flutter_web/AUTHORS | 1 + .../google_maps_flutter_web/CHANGELOG.md | 4 + .../google_maps_flutter_web/README.md | 5 - .../example/flutter_01.log | 99 ++++++++ .../google_maps_controller_test.dart | 138 ++++++++++++ .../google_maps_controller_test.mocks.dart | 164 +++++++++++--- .../google_maps_plugin_test.mocks.dart | 7 +- .../icons/blue-dot.png | Bin 0 -> 1754 bytes .../icons/mylocation-sprite-2x.png | Bin 0 -> 1582 bytes .../lib/google_maps_flutter_web.dart | 1 + .../lib/src/google_maps_controller.dart | 25 +++ .../lib/src/my_location.dart | 211 ++++++++++++++++++ .../google_maps_flutter_web/pubspec.yaml | 5 +- 13 files changed, 615 insertions(+), 45 deletions(-) create mode 100644 packages/google_maps_flutter/google_maps_flutter_web/example/flutter_01.log create mode 100644 packages/google_maps_flutter/google_maps_flutter_web/icons/blue-dot.png create mode 100644 packages/google_maps_flutter/google_maps_flutter_web/icons/mylocation-sprite-2x.png create mode 100644 packages/google_maps_flutter/google_maps_flutter_web/lib/src/my_location.dart diff --git a/packages/google_maps_flutter/google_maps_flutter_web/AUTHORS b/packages/google_maps_flutter/google_maps_flutter_web/AUTHORS index b5b0e84d473..1fd9e9fae16 100644 --- a/packages/google_maps_flutter/google_maps_flutter_web/AUTHORS +++ b/packages/google_maps_flutter/google_maps_flutter_web/AUTHORS @@ -65,3 +65,4 @@ Anton Borries Alex Li Rahul Raj <64.rahulraj@gmail.com> Justin Baumann +Nguyễn Phúc Lợi diff --git a/packages/google_maps_flutter/google_maps_flutter_web/CHANGELOG.md b/packages/google_maps_flutter/google_maps_flutter_web/CHANGELOG.md index 52f288ec7e9..415071932e4 100644 --- a/packages/google_maps_flutter/google_maps_flutter_web/CHANGELOG.md +++ b/packages/google_maps_flutter/google_maps_flutter_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.5.2 + +* Add "My Location" Widget. Issue [#64073](https://github.com/flutter/flutter/issues/64073) + ## 0.5.1 * Adds padding support to `CameraUpdate.newLatLngBounds`. Issue [#122192](https://github.com/flutter/flutter/issues/122192). diff --git a/packages/google_maps_flutter/google_maps_flutter_web/README.md b/packages/google_maps_flutter/google_maps_flutter_web/README.md index b52da95119c..5fe99e56278 100644 --- a/packages/google_maps_flutter/google_maps_flutter_web/README.md +++ b/packages/google_maps_flutter/google_maps_flutter_web/README.md @@ -60,11 +60,6 @@ The following map options are not available in web, because the map doesn't rota There's no "Map Toolbar" in web, so the `mapToolbarEnabled` option is unused. -There's no "My Location" widget in web ([tracking issue](https://github.com/flutter/flutter/issues/64073)), so the following options are ignored, for now: - -* `myLocationButtonEnabled` -* `myLocationEnabled` - There's no `defaultMarkerWithHue` in web. If you need colored pins/markers, you may need to use your own asset images. Indoor and building layers are still not available on the web. Traffic is. diff --git a/packages/google_maps_flutter/google_maps_flutter_web/example/flutter_01.log b/packages/google_maps_flutter/google_maps_flutter_web/example/flutter_01.log new file mode 100644 index 00000000000..e8b31153bbf --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_web/example/flutter_01.log @@ -0,0 +1,99 @@ +Flutter crash report. +Please report a bug at https://github.com/flutter/flutter/issues. + +## command + +flutter drive -d web-server --web-port=7357 --driver test_driver/integration_test.dart --target integration_test/google_maps_controller_test.dart + +## exception + +SessionNotCreatedException: SessionNotCreatedException (500): session not created: This version of ChromeDriver only supports Chrome version 112 +Current browser version is 114.0.5735.198 with binary path /Applications/Google Chrome.app/Contents/MacOS/Google Chrome + +``` +#0 parseW3cResponse (package:webdriver/src/handler/w3c/utils.dart:81:9) +#1 W3cSessionHandler.parseCreateResponse (package:webdriver/src/handler/w3c/session.dart:19:21) +#2 InferSessionHandler.parseCreateResponse (package:webdriver/src/handler/infer_handler.dart:106:34) +#3 AsyncRequestClient.send (package:webdriver/src/common/request_client.dart:96:32) + +#4 createDriver (package:webdriver/async_core.dart:62:19) + +#5 WebDriverService.startTest (package:flutter_tools/src/drive/web_driver_service.dart:145:19) + +#6 DriveCommand.runCommand (package:flutter_tools/src/commands/drive.dart:332:30) + +#7 FlutterCommand.run. (package:flutter_tools/src/runner/flutter_command.dart:1336:27) + +#8 AppContext.run. (package:flutter_tools/src/base/context.dart:150:19) + +#9 CommandRunner.runCommand (package:args/command_runner.dart:212:13) + +#10 FlutterCommandRunner.runCommand. (package:flutter_tools/src/runner/flutter_command_runner.dart:296:9) + +#11 AppContext.run. (package:flutter_tools/src/base/context.dart:150:19) + +#12 FlutterCommandRunner.runCommand (package:flutter_tools/src/runner/flutter_command_runner.dart:244:5) + +#13 run.. (package:flutter_tools/runner.dart:91:9) + +#14 AppContext.run. (package:flutter_tools/src/base/context.dart:150:19) + +#15 main (package:flutter_tools/executable.dart:91:3) + +``` + +## flutter doctor + +``` +[!] Flutter (Channel unknown, 3.10.5, on macOS 13.4.1 22F770820d darwin-x64, locale en-VN) + ! Flutter version 3.10.5 on channel unknown at /Users/loinguyen/work/flutter + Currently on an unknown channel. Run `flutter channel` to switch to an official channel. + If that doesn't fix the issue, reinstall Flutter by following instructions at https://flutter.dev/docs/get-started/install. + ! Warning: `dart` on your path resolves to /usr/local/Cellar/dart/2.18.6/libexec/bin/dart, which is not inside your current Flutter SDK checkout at /Users/loinguyen/work/flutter. Consider adding /Users/loinguyen/work/flutter/bin to the front of your path. + ! Unknown upstream repository. + Reinstall Flutter by following instructions at https://flutter.dev/docs/get-started/install. + • Framework revision 796c8ef792 (5 weeks ago), 2023-06-13 15:51:02 -0700 + • Engine revision 45f6e00911 + • Dart version 3.0.5 + • DevTools version 2.23.1 + • If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly to perform update checks and upgrades. + +[!] Android toolchain - develop for Android devices (Android SDK version 32.1.0-rc1) + • Android SDK at /Users/loinguyen/Library/Android/sdk + • Platform android-33, build-tools 32.1.0-rc1 + • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java + • Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840) + ✗ Android license status unknown. + Run `flutter doctor --android-licenses` to accept the SDK licenses. + See https://flutter.dev/docs/get-started/install/macos#android-setup for more details. + +[✓] Xcode - develop for iOS and macOS (Xcode 14.3.1) + • Xcode at /Applications/Xcode.app/Contents/Developer + • Build 14E300c + • CocoaPods version 1.12.0 + +[✓] Chrome - develop for the web + • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome + +[✓] Android Studio (version 2021.2) + • Android Studio at /Applications/Android Studio.app/Contents + • Flutter plugin can be installed from: + 🔨 https://plugins.jetbrains.com/plugin/9212-flutter + • Dart plugin can be installed from: + 🔨 https://plugins.jetbrains.com/plugin/6351-dart + • Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840) + +[✓] VS Code (version 1.80.1) + • VS Code at /Applications/Visual Studio Code.app/Contents + • Flutter extension version 3.68.0 + +[✓] Connected device (3 available) + • macOS (desktop) • macos • darwin-x64 • macOS 13.4.1 22F770820d darwin-x64 + • Web Server (web) • web-server • web-javascript • Flutter Tools + • Chrome (web) • chrome • web-javascript • Google Chrome 114.0.5735.198 + +[✓] Network resources + • All expected network resources are available. + +! Doctor found issues in 2 categories. +``` diff --git a/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_controller_test.dart b/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_controller_test.dart index 8889e4ba957..0dcaadee5af 100644 --- a/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_controller_test.dart +++ b/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_controller_test.dart @@ -21,6 +21,9 @@ import 'google_maps_controller_test.mocks.dart'; MockSpec(onMissingStub: OnMissingStub.returnDefault), MockSpec(onMissingStub: OnMissingStub.returnDefault), MockSpec(onMissingStub: OnMissingStub.returnDefault), + MockSpec(onMissingStub: OnMissingStub.returnDefault), + MockSpec(onMissingStub: OnMissingStub.returnDefault), + MockSpec(onMissingStub: OnMissingStub.returnDefault), ]) /// Test Google Map Controller @@ -481,6 +484,141 @@ void main() { expect(controller.trafficLayer, isNotNull); }); }); + + group('My Location', () { + testWidgets('by default is disabled', (WidgetTester tester) async { + controller = createController(); + controller.init(); + + expect(controller.myLocationButton, isNull); + }); + + testWidgets('initializes with my location & display my location button', + (WidgetTester tester) async { + late final MockGeolocation mockGeolocation = MockGeolocation(); + late final MockGeoposition mockGeoposition = MockGeoposition(); + late final MockCoordinates mockCoordinates = MockCoordinates(); + const LatLng currentLocation = LatLng(10.8231, 106.6297); + + controller = createController( + mapConfiguration: const MapConfiguration( + myLocationEnabled: true, + myLocationButtonEnabled: true, + )); + + controller.debugSetOverrides( + createMap: (_, __) => map, + markers: markers, + geolocation: mockGeolocation, + ); + + when(mockGeoposition.coords).thenReturn(mockCoordinates); + + when(mockCoordinates.longitude).thenReturn(currentLocation.longitude); + + when(mockCoordinates.latitude).thenReturn(currentLocation.latitude); + + when(mockGeolocation.getCurrentPosition( + timeout: anyNamed('timeout'), + )).thenAnswer((_) async => mockGeoposition); + + when(mockGeolocation.watchPosition()).thenAnswer((_) { + return Stream.fromIterable( + [mockGeoposition]); + }); + + controller.init(); + await tester.pumpAndSettle(); + + final Set capturedMarkers = + verify(markers.addMarkers(captureAny)).captured[1] as Set; + + expect(controller.myLocationButton, isNotNull); + expect(capturedMarkers.length, 1); + expect(capturedMarkers.first.position, currentLocation); + expect(capturedMarkers.first.zIndex, 0.5); + }); + + testWidgets('initializes with my location only', + (WidgetTester tester) async { + late final MockGeolocation mockGeolocation = MockGeolocation(); + late final MockGeoposition mockGeoposition = MockGeoposition(); + late final MockCoordinates mockCoordinates = MockCoordinates(); + const LatLng currentLocation = LatLng(10.8231, 106.6297); + + controller = createController( + mapConfiguration: const MapConfiguration( + myLocationEnabled: true, + myLocationButtonEnabled: false, + )); + controller.debugSetOverrides( + createMap: (_, __) => map, + markers: markers, + geolocation: mockGeolocation, + ); + + when(mockGeoposition.coords).thenReturn(mockCoordinates); + + when(mockCoordinates.longitude).thenReturn(currentLocation.longitude); + + when(mockCoordinates.latitude).thenReturn(currentLocation.latitude); + + when(mockGeolocation.getCurrentPosition.call()) + .thenAnswer((_) async => mockGeoposition); + + when(mockGeolocation.watchPosition()).thenAnswer((_) { + return Stream.fromIterable( + [mockGeoposition]); + }); + + controller.init(); + + await Future.delayed(const Duration(seconds: 1)); + final LatLngBounds visibleRegion = + await controller.getVisibleRegion(); + + final Set capturedMarkers = + verify(markers.addMarkers(captureAny)).captured[1] as Set; + expect(visibleRegion.contains(currentLocation), true); + expect(controller.myLocationButton, isNull); + expect(capturedMarkers.length, 1); + expect(capturedMarkers.first.position, currentLocation); + expect(capturedMarkers.first.zIndex, 0.5); + }); + }); + + testWidgets( + 'My location button should be disable when dont have permission access to location', + (WidgetTester tester) async { + late final MockGeolocation mockGeolocation = MockGeolocation(); + + controller = createController( + mapConfiguration: const MapConfiguration( + myLocationEnabled: true, + myLocationButtonEnabled: true, + )); + + controller.debugSetOverrides( + createMap: (_, __) => map, + markers: markers, + geolocation: mockGeolocation, + ); + + // when(mockGeolocation.watchPosition()).thenAnswer((_) { + // return Stream.error('permission denied'); + // }); + when(mockGeolocation.getCurrentPosition(timeout: anyNamed('timeout'))) + .thenAnswer( + (_) async => throw Exception('permission denied'), + ); + + controller.init(); + + await Future.delayed(const Duration(seconds: 1)); + + expect(controller.myLocationButton, isNotNull); + expect(controller.myLocationButton?.isDisabled(), true); + }); }); // These are the methods that are delegated to the gmaps.GMap object, that we can mock... diff --git a/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_controller_test.mocks.dart b/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_controller_test.mocks.dart index 4bc5f365d2d..7940be6c925 100644 --- a/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_controller_test.mocks.dart +++ b/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_controller_test.mocks.dart @@ -5,10 +5,13 @@ // @dart=2.19 // ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _i6; +import 'dart:html' as _i3; + import 'package:google_maps/google_maps.dart' as _i2; import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart' - as _i4; -import 'package:google_maps_flutter_web/google_maps_flutter_web.dart' as _i3; + as _i5; +import 'package:google_maps_flutter_web/google_maps_flutter_web.dart' as _i4; import 'package:mockito/mockito.dart' as _i1; // ignore_for_file: type=lint @@ -32,16 +35,26 @@ class _FakeGMap_0 extends _i1.SmartFake implements _i2.GMap { ); } +class _FakeGeoposition_1 extends _i1.SmartFake implements _i3.Geoposition { + _FakeGeoposition_1( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + /// A class which mocks [CirclesController]. /// /// See the documentation for Mockito's code generation for more information. -class MockCirclesController extends _i1.Mock implements _i3.CirclesController { +class MockCirclesController extends _i1.Mock implements _i4.CirclesController { @override - Map<_i4.CircleId, _i3.CircleController> get circles => (super.noSuchMethod( + Map<_i5.CircleId, _i4.CircleController> get circles => (super.noSuchMethod( Invocation.getter(#circles), - returnValue: <_i4.CircleId, _i3.CircleController>{}, - returnValueForMissingStub: <_i4.CircleId, _i3.CircleController>{}, - ) as Map<_i4.CircleId, _i3.CircleController>); + returnValue: <_i5.CircleId, _i4.CircleController>{}, + returnValueForMissingStub: <_i5.CircleId, _i4.CircleController>{}, + ) as Map<_i5.CircleId, _i4.CircleController>); @override _i2.GMap get googleMap => (super.noSuchMethod( Invocation.getter(#googleMap), @@ -77,7 +90,7 @@ class MockCirclesController extends _i1.Mock implements _i3.CirclesController { returnValueForMissingStub: null, ); @override - void addCircles(Set<_i4.Circle>? circlesToAdd) => super.noSuchMethod( + void addCircles(Set<_i5.Circle>? circlesToAdd) => super.noSuchMethod( Invocation.method( #addCircles, [circlesToAdd], @@ -85,7 +98,7 @@ class MockCirclesController extends _i1.Mock implements _i3.CirclesController { returnValueForMissingStub: null, ); @override - void changeCircles(Set<_i4.Circle>? circlesToChange) => super.noSuchMethod( + void changeCircles(Set<_i5.Circle>? circlesToChange) => super.noSuchMethod( Invocation.method( #changeCircles, [circlesToChange], @@ -93,7 +106,7 @@ class MockCirclesController extends _i1.Mock implements _i3.CirclesController { returnValueForMissingStub: null, ); @override - void removeCircles(Set<_i4.CircleId>? circleIdsToRemove) => + void removeCircles(Set<_i5.CircleId>? circleIdsToRemove) => super.noSuchMethod( Invocation.method( #removeCircles, @@ -122,13 +135,13 @@ class MockCirclesController extends _i1.Mock implements _i3.CirclesController { /// /// See the documentation for Mockito's code generation for more information. class MockPolygonsController extends _i1.Mock - implements _i3.PolygonsController { + implements _i4.PolygonsController { @override - Map<_i4.PolygonId, _i3.PolygonController> get polygons => (super.noSuchMethod( + Map<_i5.PolygonId, _i4.PolygonController> get polygons => (super.noSuchMethod( Invocation.getter(#polygons), - returnValue: <_i4.PolygonId, _i3.PolygonController>{}, - returnValueForMissingStub: <_i4.PolygonId, _i3.PolygonController>{}, - ) as Map<_i4.PolygonId, _i3.PolygonController>); + returnValue: <_i5.PolygonId, _i4.PolygonController>{}, + returnValueForMissingStub: <_i5.PolygonId, _i4.PolygonController>{}, + ) as Map<_i5.PolygonId, _i4.PolygonController>); @override _i2.GMap get googleMap => (super.noSuchMethod( Invocation.getter(#googleMap), @@ -164,7 +177,7 @@ class MockPolygonsController extends _i1.Mock returnValueForMissingStub: null, ); @override - void addPolygons(Set<_i4.Polygon>? polygonsToAdd) => super.noSuchMethod( + void addPolygons(Set<_i5.Polygon>? polygonsToAdd) => super.noSuchMethod( Invocation.method( #addPolygons, [polygonsToAdd], @@ -172,7 +185,7 @@ class MockPolygonsController extends _i1.Mock returnValueForMissingStub: null, ); @override - void changePolygons(Set<_i4.Polygon>? polygonsToChange) => super.noSuchMethod( + void changePolygons(Set<_i5.Polygon>? polygonsToChange) => super.noSuchMethod( Invocation.method( #changePolygons, [polygonsToChange], @@ -180,7 +193,7 @@ class MockPolygonsController extends _i1.Mock returnValueForMissingStub: null, ); @override - void removePolygons(Set<_i4.PolygonId>? polygonIdsToRemove) => + void removePolygons(Set<_i5.PolygonId>? polygonIdsToRemove) => super.noSuchMethod( Invocation.method( #removePolygons, @@ -209,13 +222,13 @@ class MockPolygonsController extends _i1.Mock /// /// See the documentation for Mockito's code generation for more information. class MockPolylinesController extends _i1.Mock - implements _i3.PolylinesController { + implements _i4.PolylinesController { @override - Map<_i4.PolylineId, _i3.PolylineController> get lines => (super.noSuchMethod( + Map<_i5.PolylineId, _i4.PolylineController> get lines => (super.noSuchMethod( Invocation.getter(#lines), - returnValue: <_i4.PolylineId, _i3.PolylineController>{}, - returnValueForMissingStub: <_i4.PolylineId, _i3.PolylineController>{}, - ) as Map<_i4.PolylineId, _i3.PolylineController>); + returnValue: <_i5.PolylineId, _i4.PolylineController>{}, + returnValueForMissingStub: <_i5.PolylineId, _i4.PolylineController>{}, + ) as Map<_i5.PolylineId, _i4.PolylineController>); @override _i2.GMap get googleMap => (super.noSuchMethod( Invocation.getter(#googleMap), @@ -251,7 +264,7 @@ class MockPolylinesController extends _i1.Mock returnValueForMissingStub: null, ); @override - void addPolylines(Set<_i4.Polyline>? polylinesToAdd) => super.noSuchMethod( + void addPolylines(Set<_i5.Polyline>? polylinesToAdd) => super.noSuchMethod( Invocation.method( #addPolylines, [polylinesToAdd], @@ -259,7 +272,7 @@ class MockPolylinesController extends _i1.Mock returnValueForMissingStub: null, ); @override - void changePolylines(Set<_i4.Polyline>? polylinesToChange) => + void changePolylines(Set<_i5.Polyline>? polylinesToChange) => super.noSuchMethod( Invocation.method( #changePolylines, @@ -268,7 +281,7 @@ class MockPolylinesController extends _i1.Mock returnValueForMissingStub: null, ); @override - void removePolylines(Set<_i4.PolylineId>? polylineIdsToRemove) => + void removePolylines(Set<_i5.PolylineId>? polylineIdsToRemove) => super.noSuchMethod( Invocation.method( #removePolylines, @@ -296,13 +309,13 @@ class MockPolylinesController extends _i1.Mock /// A class which mocks [MarkersController]. /// /// See the documentation for Mockito's code generation for more information. -class MockMarkersController extends _i1.Mock implements _i3.MarkersController { +class MockMarkersController extends _i1.Mock implements _i4.MarkersController { @override - Map<_i4.MarkerId, _i3.MarkerController> get markers => (super.noSuchMethod( + Map<_i5.MarkerId, _i4.MarkerController> get markers => (super.noSuchMethod( Invocation.getter(#markers), - returnValue: <_i4.MarkerId, _i3.MarkerController>{}, - returnValueForMissingStub: <_i4.MarkerId, _i3.MarkerController>{}, - ) as Map<_i4.MarkerId, _i3.MarkerController>); + returnValue: <_i5.MarkerId, _i4.MarkerController>{}, + returnValueForMissingStub: <_i5.MarkerId, _i4.MarkerController>{}, + ) as Map<_i5.MarkerId, _i4.MarkerController>); @override _i2.GMap get googleMap => (super.noSuchMethod( Invocation.getter(#googleMap), @@ -338,7 +351,7 @@ class MockMarkersController extends _i1.Mock implements _i3.MarkersController { returnValueForMissingStub: null, ); @override - void addMarkers(Set<_i4.Marker>? markersToAdd) => super.noSuchMethod( + void addMarkers(Set<_i5.Marker>? markersToAdd) => super.noSuchMethod( Invocation.method( #addMarkers, [markersToAdd], @@ -346,7 +359,7 @@ class MockMarkersController extends _i1.Mock implements _i3.MarkersController { returnValueForMissingStub: null, ); @override - void changeMarkers(Set<_i4.Marker>? markersToChange) => super.noSuchMethod( + void changeMarkers(Set<_i5.Marker>? markersToChange) => super.noSuchMethod( Invocation.method( #changeMarkers, [markersToChange], @@ -354,7 +367,7 @@ class MockMarkersController extends _i1.Mock implements _i3.MarkersController { returnValueForMissingStub: null, ); @override - void removeMarkers(Set<_i4.MarkerId>? markerIdsToRemove) => + void removeMarkers(Set<_i5.MarkerId>? markerIdsToRemove) => super.noSuchMethod( Invocation.method( #removeMarkers, @@ -363,7 +376,7 @@ class MockMarkersController extends _i1.Mock implements _i3.MarkersController { returnValueForMissingStub: null, ); @override - void showMarkerInfoWindow(_i4.MarkerId? markerId) => super.noSuchMethod( + void showMarkerInfoWindow(_i5.MarkerId? markerId) => super.noSuchMethod( Invocation.method( #showMarkerInfoWindow, [markerId], @@ -371,7 +384,7 @@ class MockMarkersController extends _i1.Mock implements _i3.MarkersController { returnValueForMissingStub: null, ); @override - void hideMarkerInfoWindow(_i4.MarkerId? markerId) => super.noSuchMethod( + void hideMarkerInfoWindow(_i5.MarkerId? markerId) => super.noSuchMethod( Invocation.method( #hideMarkerInfoWindow, [markerId], @@ -379,7 +392,7 @@ class MockMarkersController extends _i1.Mock implements _i3.MarkersController { returnValueForMissingStub: null, ); @override - bool isInfoWindowShown(_i4.MarkerId? markerId) => (super.noSuchMethod( + bool isInfoWindowShown(_i5.MarkerId? markerId) => (super.noSuchMethod( Invocation.method( #isInfoWindowShown, [markerId], @@ -403,3 +416,80 @@ class MockMarkersController extends _i1.Mock implements _i3.MarkersController { returnValueForMissingStub: null, ); } + +/// A class which mocks [Geolocation]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockGeolocation extends _i1.Mock implements _i3.Geolocation { + @override + _i6.Future<_i3.Geoposition> getCurrentPosition({ + bool? enableHighAccuracy, + Duration? timeout, + Duration? maximumAge, + }) => + (super.noSuchMethod( + Invocation.method( + #getCurrentPosition, + [], + { + #enableHighAccuracy: enableHighAccuracy, + #timeout: timeout, + #maximumAge: maximumAge, + }, + ), + returnValue: _i6.Future<_i3.Geoposition>.value(_FakeGeoposition_1( + this, + Invocation.method( + #getCurrentPosition, + [], + { + #enableHighAccuracy: enableHighAccuracy, + #timeout: timeout, + #maximumAge: maximumAge, + }, + ), + )), + returnValueForMissingStub: + _i6.Future<_i3.Geoposition>.value(_FakeGeoposition_1( + this, + Invocation.method( + #getCurrentPosition, + [], + { + #enableHighAccuracy: enableHighAccuracy, + #timeout: timeout, + #maximumAge: maximumAge, + }, + ), + )), + ) as _i6.Future<_i3.Geoposition>); + @override + _i6.Stream<_i3.Geoposition> watchPosition({ + bool? enableHighAccuracy, + Duration? timeout, + Duration? maximumAge, + }) => + (super.noSuchMethod( + Invocation.method( + #watchPosition, + [], + { + #enableHighAccuracy: enableHighAccuracy, + #timeout: timeout, + #maximumAge: maximumAge, + }, + ), + returnValue: _i6.Stream<_i3.Geoposition>.empty(), + returnValueForMissingStub: _i6.Stream<_i3.Geoposition>.empty(), + ) as _i6.Stream<_i3.Geoposition>); +} + +/// A class which mocks [Geoposition]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockGeoposition extends _i1.Mock implements _i3.Geoposition {} + +/// A class which mocks [Coordinates]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockCoordinates extends _i1.Mock implements _i3.Coordinates {} diff --git a/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_plugin_test.mocks.dart b/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_plugin_test.mocks.dart index 36e6052a21c..fbe04939b9e 100644 --- a/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_plugin_test.mocks.dart +++ b/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_plugin_test.mocks.dart @@ -6,8 +6,9 @@ // ignore_for_file: no_leading_underscores_for_library_prefixes import 'dart:async' as _i3; +import 'dart:html' as _i5; -import 'package:google_maps/google_maps.dart' as _i5; +import 'package:google_maps/google_maps.dart' as _i6; import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart' as _i2; import 'package:google_maps_flutter_web/google_maps_flutter_web.dart' as _i4; @@ -126,6 +127,7 @@ class MockGoogleMapController extends _i1.Mock _i4.CirclesController? circles, _i4.PolygonsController? polygons, _i4.PolylinesController? polylines, + _i5.Geolocation? geolocation, }) => super.noSuchMethod( Invocation.method( @@ -137,6 +139,7 @@ class MockGoogleMapController extends _i1.Mock #circles: circles, #polygons: polygons, #polylines: polylines, + #geolocation: geolocation, }, ), returnValueForMissingStub: null, @@ -159,7 +162,7 @@ class MockGoogleMapController extends _i1.Mock returnValueForMissingStub: null, ); @override - void updateStyles(List<_i5.MapTypeStyle>? styles) => super.noSuchMethod( + void updateStyles(List<_i6.MapTypeStyle>? styles) => super.noSuchMethod( Invocation.method( #updateStyles, [styles], diff --git a/packages/google_maps_flutter/google_maps_flutter_web/icons/blue-dot.png b/packages/google_maps_flutter/google_maps_flutter_web/icons/blue-dot.png new file mode 100644 index 0000000000000000000000000000000000000000..77780f8ab4b78bdfec273c504a5104fbf134b054 GIT binary patch literal 1754 zcmZ`&2{_bg82=oR5nXJQm2#HK7$oNyGn1KQ9_Mxl12BHWEsU5N%Jf zqH>gOA*oH$wM!`p!}!nf|Lr!3f*GYq*i&YY=D$1qZg zfRceZrc7;OV?>U?ry3(>P7}F8y9}XYDgxhsD`ADg6U|6=!;Dw%^uKP~pNl_?qfpP~ zZ}&^FuMQ07uBvW}gd%Kc3>}$3#ecnm8QE?9Bk9Kp^wbT6Svc*?5s*0o*rUE@wzlSu zNFv2b+YoxD0QxX9DMVQn!U-WNtA!)P670a4>A6|Otw>4h-(2WC!L=u|@L&h1LyM-N zKnIe7VBnx>1Pv(_<~JjMe3rt|P(%O6Uy+eC8rBy+-0?M-Jm0D4jm|S04Ao< zsB)n!2{FrH!?2-C$}E_M8v2m?9DP_gR|}W<^*$lCZjc)W5QFyyU28&t(p@Ln{apeYLFImfA z51r3jy>G{{B_pF?YgLJDxG1~ua#)u+pU=;euSDa((9?%v%{zp*lgpkwsV0`cF-W-! zbhbC{IjloYi_uky?93~F0FJ-!qr|e%2~CxUs*CD&X$Z!@C5$gK1|OJ}I7T3=$+$UHLf#p z(;e>zVwcj7%nvwYu$LV5y3Af+IC<90i@bloT9T>$e1EHek5>C?Mcn4PgvRYgL?d?N z3O51Qv^QPJy7NNM2H$r-wJmof+!}3>x3qXw+^jUYI9}Z5@ORu zHcmcgFj5}3M_mezP*#;D%w$+btjIA@R?^L(QnVHrAKBuA_L?E@#)yIz|x|DHH# zo9lheF_F*Dk{u;kb-2qu-h?&rgnZ2ts15z*{r=Gl$g5Jeh>s?me7PU~FMuJ7x}6mg z$O^R$jtqqc5by+x^>}kA-sX5)i%qt8D^on)7LQjsKnVCpLHMDNy{$S4JjIZ9P5Mko=jLPq?eAoYtct6U&s6iPFw z0VGOvj7NuR1*Jig5m1tffQhG=AXO8$q*Y8M&fj6=Y54hewHN&`(t1_B1lP5R(i8dx|%`4MPOMUr(@7s;q8Dv zTOCtn6-PF&Fer6F?lL#G`rSr1M*4y{in)GjIs8R(ZOK!BP6ucaKm!M7t87C^gv)w8 zM{VsNy-9i3bfY6zsoS=oFUNfMe|CJbm+?y4{)b3?)`E8u?roq@NRR)-hD)bb8JlEd z)F-T@4&EGCn~_d$HMV5@$F-#m&yC4-#N=~Jdym2Kf64tyI)c%-lr|L@K^M46zQq zge5Iyqm+e38LS8_WJ}b613@x@^k~m;Q34)?6#)o9C0eZZMLDd?t|Qil(vM`A;DYA9 zCa`_GV+%QdV-*jjr(Qoc1`pb@0`?r8zWPfWgX^qR#$33oeKDGITG*Gej&RCp(j_W? zq}PGyLw`eNo@@bidmYp*1Jtbm)Gc+74vl)C5M2A2Po=-H?`5@#%-<5$`So=xcOy!? zPm)L^k}vy^`T%4Y|L#Vi*0m_B$G(bz+;9CgU~l}Uj}Ai`()i+l?1qW74R!lc*Fay+ z{BtLa>%O`;sV5s83`gMl$Ac#Cdsc=WxBggaywY2|h!=SM%>IzJxUzJpj#l1}z-o~^;2ZOYPyLdHQBA(K4y#zlPIUu{t#I0G}$%4MgIIpG~~I1ro0% zR`MuTgu?mi>hV%&%`T6rC8(eJ@&gf=}JNN5_Z;SNmlkGFzR<&)P-wA@Tf` zXquml@bF$S$MgU?es;epD?JTF^cX}$;(>@LAfnGFYU~kjk8vz76Cbnj)Q*@(w@3YJ zMUj9rw^%x)5+NG)-rwq8w9iR8h=zeunN#FlA- _myLocationButton; + // The currently-enabled traffic layer. gmaps.TrafficLayer? _trafficLayer; @@ -122,12 +129,14 @@ class GoogleMapController { CirclesController? circles, PolygonsController? polygons, PolylinesController? polylines, + Geolocation? geolocation, }) { _overrideCreateMap = createMap; _markersController = markers ?? _markersController; _circlesController = circles ?? _circlesController; _polygonsController = polygons ?? _polygonsController; _polylinesController = polylines ?? _polylinesController; + _geolocation = geolocation ?? _geolocation; } DebugCreateMapFunction? _overrideCreateMap; @@ -171,6 +180,7 @@ class GoogleMapController { // Create the map... final gmaps.GMap map = _createMap(_div, options); + _googleMap = map; _attachMapEvents(map); @@ -185,6 +195,20 @@ class GoogleMapController { ); _setTrafficLayer(map, _lastMapConfiguration.trafficEnabled ?? false); + + _renderMyLocation(map, _lastMapConfiguration); + } + + // Render my location + Future _renderMyLocation( + gmaps.GMap map, MapConfiguration mapConfiguration) async { + if (mapConfiguration.myLocationEnabled ?? false) { + if (mapConfiguration.myLocationButtonEnabled ?? false) { + _addMyLocationButton(map, this); + } + await _displayAndWatchMyLocation(this); + await _centerMyCurrentLocation(this); + } } // Funnels map gmap events into the plugin's stream controller. @@ -434,6 +458,7 @@ class GoogleMapController { _polygonsController = null; _polylinesController = null; _markersController = null; + _myLocationButton = null; _streamController.close(); } } diff --git a/packages/google_maps_flutter/google_maps_flutter_web/lib/src/my_location.dart b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/my_location.dart new file mode 100644 index 00000000000..85570c5baf7 --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/my_location.dart @@ -0,0 +1,211 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +part of google_maps_flutter_web; + +// Default values for when the get current location fails +const LatLng _nullLatLng = LatLng(0, 0); +Geolocation _geolocation = window.navigator.geolocation; +LatLng _lastKnownLocation = _nullLatLng; + +// Watch current location and update blue dot +Future _displayAndWatchMyLocation(GoogleMapController controller) async { + final Marker marker = await _createBlueDotMarker(); + _geolocation.watchPosition().listen( + (Geoposition location) async { + _lastKnownLocation = LatLng( + location.coords?.latitude?.toDouble() ?? _nullLatLng.latitude, + location.coords?.longitude?.toDouble() ?? _nullLatLng.longitude, + ); + // TODO(nploi): https://github.com/flutter/plugins/pull/6868#discussion_r1057898052 + // 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). + + final Marker markerUpdate = + marker.copyWith(positionParam: _lastKnownLocation); + + if (controller._markersController?.markers.containsKey(marker.markerId) ?? + false) { + controller._markersController?._changeMarker(markerUpdate); + } else { + controller._markersController?.addMarkers({markerUpdate}); + } + }, + onError: (_) { + controller._myLocationButton?.doneAnimation(); + }, + ); +} + +// Get current location +Future _getCurrentLocation() async { + if (_lastKnownLocation != _nullLatLng) { + return _lastKnownLocation; + } + final Geoposition location = await _geolocation.getCurrentPosition( + timeout: const Duration(seconds: 30), + ); + _lastKnownLocation = LatLng( + location.coords?.latitude?.toDouble() ?? _nullLatLng.latitude, + location.coords?.longitude?.toDouble() ?? _nullLatLng.longitude, + ); + return _lastKnownLocation; +} + +// Find and move to current location +Future _centerMyCurrentLocation( + GoogleMapController controller, +) async { + try { + final LatLng location = await _getCurrentLocation(); + + await controller.moveCamera( + CameraUpdate.newLatLng(location), + ); + controller._myLocationButton?.doneAnimation(); + } catch (e) { + controller._myLocationButton?.disableBtn(); + } +} + +// Add my location to map +void _addMyLocationButton(gmaps.GMap map, GoogleMapController controller) { + controller._myLocationButton = MyLocationButton(); + controller._myLocationButton?.addClickListener( + (_) async { + _centerMyCurrentLocation(controller); + }, + ); + map.addListener('dragend', () { + controller._myLocationButton?.resetAnimation(); + }); + map.addListener('center_changed', () { + controller._myLocationButton?.resetAnimation(); + }); + map.controls![gmaps.ControlPosition.RIGHT_BOTTOM as int] + ?.push(controller._myLocationButton?.getButton); +} + +// Create blue dot marker +Future _createBlueDotMarker() async { + final BitmapDescriptor icon = await BitmapDescriptor.fromAssetImage( + const ImageConfiguration(size: Size(18, 18)), + 'icons/blue-dot.png', + package: 'google_maps_flutter_web', + ); + return Marker( + markerId: const MarkerId('my_location_blue_dot'), + icon: icon, + zIndex: 0.5, + ); +} + +/// This class support create my location button & handle animation +@visibleForTesting +class MyLocationButton { + /// Add css and create my location button + MyLocationButton() { + _addCss(); + _createButton(); + } + + late ButtonElement _btnChild; + late DivElement _imageChild; + late DivElement _controlDiv; + + // Add animation css + void _addCss() { + final StyleElement styleElement = StyleElement(); + document.head?.append(styleElement); + // ignore: cast_nullable_to_non_nullable + final CssStyleSheet sheet = styleElement.sheet as CssStyleSheet; + String rule = + '.waiting { animation: 1000ms infinite step-end blink-position-icon;}'; + sheet.insertRule(rule); + rule = + '@keyframes blink-position-icon {0% {background-position: -24px 0px;} ' + '50% {background-position: 0px 0px;}}'; + sheet.insertRule(rule); + } + + // Add My Location widget to right bottom + void _createButton() { + _controlDiv = DivElement(); + + _controlDiv.style.marginRight = '10px'; + + _btnChild = ButtonElement(); + _btnChild.className = 'gm-control-active'; + _btnChild.style.backgroundColor = '#fff'; + _btnChild.style.border = 'none'; + _btnChild.style.outline = 'none'; + _btnChild.style.width = '40px'; + _btnChild.style.height = '40px'; + _btnChild.style.borderRadius = '2px'; + _btnChild.style.boxShadow = '0 1px 4px rgba(0,0,0,0.3)'; + _btnChild.style.cursor = 'pointer'; + _btnChild.style.padding = '8px'; + _controlDiv.append(_btnChild); + + _imageChild = DivElement(); + _imageChild.style.width = '24px'; + _imageChild.style.height = '24px'; + _imageChild.style.backgroundImage = + 'url(${window.location.href.replaceAll('/#', '')}/assets/packages/google_maps_flutter_web/icons/mylocation-sprite-2x.png)'; + _imageChild.style.backgroundSize = '240px 24px'; + _imageChild.style.backgroundPosition = '0px 0px'; + _imageChild.style.backgroundRepeat = 'no-repeat'; + _imageChild.id = 'my_location_btn'; + _btnChild.append(_imageChild); + } + + /// Get button element + HtmlElement get getButton => _controlDiv; + + /// Add click listener + void addClickListener(EventListener? listener) { + _btnChild.addEventListener('click', listener); + } + + /// Reset animation + void resetAnimation() { + if (_btnChild.disabled) { + _imageChild.style.backgroundPosition = '-24px 0px'; + } else { + _imageChild.style.backgroundPosition = '0px 0px'; + } + } + + /// Start animation + void startAnimation() { + if (_btnChild.disabled) { + return; + } + _imageChild.classes.add('waiting'); + } + + /// Done animation + void doneAnimation() { + if (_btnChild.disabled) { + return; + } + _imageChild.classes.remove('waiting'); + _imageChild.style.backgroundPosition = '-192px 0px'; + } + + /// Disable button + void disableBtn() { + _btnChild.disabled = true; + _imageChild.classes.remove('waiting'); + _imageChild.style.backgroundPosition = '-24px 0px'; + print('disable button'); + } + + /// Check button disabled or enabled + bool isDisabled() { + return _btnChild.disabled; + } +} diff --git a/packages/google_maps_flutter/google_maps_flutter_web/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter_web/pubspec.yaml index e6afb06eab3..11dbf8aef53 100644 --- a/packages/google_maps_flutter/google_maps_flutter_web/pubspec.yaml +++ b/packages/google_maps_flutter/google_maps_flutter_web/pubspec.yaml @@ -2,7 +2,7 @@ name: google_maps_flutter_web description: Web platform implementation of google_maps_flutter repository: https://github.com/flutter/packages/tree/main/packages/google_maps_flutter/google_maps_flutter_web issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+maps%22 -version: 0.5.1 +version: 0.5.2 environment: sdk: ">=2.18.0 <4.0.0" @@ -15,6 +15,8 @@ flutter: web: pluginClass: GoogleMapsPlugin fileName: google_maps_flutter_web.dart + assets: + - icons/ dependencies: flutter: @@ -33,3 +35,4 @@ dev_dependencies: # The example deliberately includes limited-use secrets. false_secrets: - /example/web/index.html + From 6b52f227b6b4091dbf87fc6a3acc5c71bb53d7a6 Mon Sep 17 00:00:00 2001 From: nploi Date: Sun, 16 Jul 2023 21:46:01 +0700 Subject: [PATCH 2/5] Remove log file --- .../example/flutter_01.log | 99 ------------------- 1 file changed, 99 deletions(-) delete mode 100644 packages/google_maps_flutter/google_maps_flutter_web/example/flutter_01.log diff --git a/packages/google_maps_flutter/google_maps_flutter_web/example/flutter_01.log b/packages/google_maps_flutter/google_maps_flutter_web/example/flutter_01.log deleted file mode 100644 index e8b31153bbf..00000000000 --- a/packages/google_maps_flutter/google_maps_flutter_web/example/flutter_01.log +++ /dev/null @@ -1,99 +0,0 @@ -Flutter crash report. -Please report a bug at https://github.com/flutter/flutter/issues. - -## command - -flutter drive -d web-server --web-port=7357 --driver test_driver/integration_test.dart --target integration_test/google_maps_controller_test.dart - -## exception - -SessionNotCreatedException: SessionNotCreatedException (500): session not created: This version of ChromeDriver only supports Chrome version 112 -Current browser version is 114.0.5735.198 with binary path /Applications/Google Chrome.app/Contents/MacOS/Google Chrome - -``` -#0 parseW3cResponse (package:webdriver/src/handler/w3c/utils.dart:81:9) -#1 W3cSessionHandler.parseCreateResponse (package:webdriver/src/handler/w3c/session.dart:19:21) -#2 InferSessionHandler.parseCreateResponse (package:webdriver/src/handler/infer_handler.dart:106:34) -#3 AsyncRequestClient.send (package:webdriver/src/common/request_client.dart:96:32) - -#4 createDriver (package:webdriver/async_core.dart:62:19) - -#5 WebDriverService.startTest (package:flutter_tools/src/drive/web_driver_service.dart:145:19) - -#6 DriveCommand.runCommand (package:flutter_tools/src/commands/drive.dart:332:30) - -#7 FlutterCommand.run. (package:flutter_tools/src/runner/flutter_command.dart:1336:27) - -#8 AppContext.run. (package:flutter_tools/src/base/context.dart:150:19) - -#9 CommandRunner.runCommand (package:args/command_runner.dart:212:13) - -#10 FlutterCommandRunner.runCommand. (package:flutter_tools/src/runner/flutter_command_runner.dart:296:9) - -#11 AppContext.run. (package:flutter_tools/src/base/context.dart:150:19) - -#12 FlutterCommandRunner.runCommand (package:flutter_tools/src/runner/flutter_command_runner.dart:244:5) - -#13 run.. (package:flutter_tools/runner.dart:91:9) - -#14 AppContext.run. (package:flutter_tools/src/base/context.dart:150:19) - -#15 main (package:flutter_tools/executable.dart:91:3) - -``` - -## flutter doctor - -``` -[!] Flutter (Channel unknown, 3.10.5, on macOS 13.4.1 22F770820d darwin-x64, locale en-VN) - ! Flutter version 3.10.5 on channel unknown at /Users/loinguyen/work/flutter - Currently on an unknown channel. Run `flutter channel` to switch to an official channel. - If that doesn't fix the issue, reinstall Flutter by following instructions at https://flutter.dev/docs/get-started/install. - ! Warning: `dart` on your path resolves to /usr/local/Cellar/dart/2.18.6/libexec/bin/dart, which is not inside your current Flutter SDK checkout at /Users/loinguyen/work/flutter. Consider adding /Users/loinguyen/work/flutter/bin to the front of your path. - ! Unknown upstream repository. - Reinstall Flutter by following instructions at https://flutter.dev/docs/get-started/install. - • Framework revision 796c8ef792 (5 weeks ago), 2023-06-13 15:51:02 -0700 - • Engine revision 45f6e00911 - • Dart version 3.0.5 - • DevTools version 2.23.1 - • If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly to perform update checks and upgrades. - -[!] Android toolchain - develop for Android devices (Android SDK version 32.1.0-rc1) - • Android SDK at /Users/loinguyen/Library/Android/sdk - • Platform android-33, build-tools 32.1.0-rc1 - • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java - • Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840) - ✗ Android license status unknown. - Run `flutter doctor --android-licenses` to accept the SDK licenses. - See https://flutter.dev/docs/get-started/install/macos#android-setup for more details. - -[✓] Xcode - develop for iOS and macOS (Xcode 14.3.1) - • Xcode at /Applications/Xcode.app/Contents/Developer - • Build 14E300c - • CocoaPods version 1.12.0 - -[✓] Chrome - develop for the web - • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome - -[✓] Android Studio (version 2021.2) - • Android Studio at /Applications/Android Studio.app/Contents - • Flutter plugin can be installed from: - 🔨 https://plugins.jetbrains.com/plugin/9212-flutter - • Dart plugin can be installed from: - 🔨 https://plugins.jetbrains.com/plugin/6351-dart - • Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840) - -[✓] VS Code (version 1.80.1) - • VS Code at /Applications/Visual Studio Code.app/Contents - • Flutter extension version 3.68.0 - -[✓] Connected device (3 available) - • macOS (desktop) • macos • darwin-x64 • macOS 13.4.1 22F770820d darwin-x64 - • Web Server (web) • web-server • web-javascript • Flutter Tools - • Chrome (web) • chrome • web-javascript • Google Chrome 114.0.5735.198 - -[✓] Network resources - • All expected network resources are available. - -! Doctor found issues in 2 categories. -``` From 3a033546c2fd2d27736ef6bc934bc1ab99216ca1 Mon Sep 17 00:00:00 2001 From: nploi Date: Sun, 16 Jul 2023 22:01:55 +0700 Subject: [PATCH 3/5] Update unit-test --- .../google_maps_controller_test.dart | 63 +++++++++---------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_controller_test.dart b/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_controller_test.dart index 0dcaadee5af..5cabfcfc074 100644 --- a/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_controller_test.dart +++ b/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_controller_test.dart @@ -563,8 +563,9 @@ void main() { when(mockCoordinates.latitude).thenReturn(currentLocation.latitude); - when(mockGeolocation.getCurrentPosition.call()) - .thenAnswer((_) async => mockGeoposition); + when(mockGeolocation.getCurrentPosition.call( + timeout: const Duration(seconds: 30), + )).thenAnswer((_) async => mockGeoposition); when(mockGeolocation.watchPosition()).thenAnswer((_) { return Stream.fromIterable( @@ -573,51 +574,49 @@ void main() { controller.init(); - await Future.delayed(const Duration(seconds: 1)); - final LatLngBounds visibleRegion = - await controller.getVisibleRegion(); + await tester.pumpAndSettle(); final Set capturedMarkers = verify(markers.addMarkers(captureAny)).captured[1] as Set; - expect(visibleRegion.contains(currentLocation), true); + expect(controller.myLocationButton, isNull); expect(capturedMarkers.length, 1); expect(capturedMarkers.first.position, currentLocation); expect(capturedMarkers.first.zIndex, 0.5); }); - }); - testWidgets( - 'My location button should be disable when dont have permission access to location', - (WidgetTester tester) async { - late final MockGeolocation mockGeolocation = MockGeolocation(); + testWidgets( + 'My location button should be disable when dont have permission access to location', + (WidgetTester tester) async { + late final MockGeolocation mockGeolocation = MockGeolocation(); - controller = createController( - mapConfiguration: const MapConfiguration( - myLocationEnabled: true, - myLocationButtonEnabled: true, - )); + controller = createController( + mapConfiguration: const MapConfiguration( + myLocationEnabled: true, + myLocationButtonEnabled: true, + )); - controller.debugSetOverrides( - createMap: (_, __) => map, - markers: markers, - geolocation: mockGeolocation, - ); + controller.debugSetOverrides( + createMap: (_, __) => map, + markers: markers, + geolocation: mockGeolocation, + ); - // when(mockGeolocation.watchPosition()).thenAnswer((_) { - // return Stream.error('permission denied'); - // }); - when(mockGeolocation.getCurrentPosition(timeout: anyNamed('timeout'))) - .thenAnswer( - (_) async => throw Exception('permission denied'), - ); + when(mockGeolocation.watchPosition()).thenAnswer((_) { + return Stream.error('permission denied'); + }); + when(mockGeolocation.getCurrentPosition(timeout: anyNamed('timeout'))) + .thenAnswer( + (_) async => throw Exception('permission denied'), + ); - controller.init(); + controller.init(); - await Future.delayed(const Duration(seconds: 1)); + await tester.pumpAndSettle(); - expect(controller.myLocationButton, isNotNull); - expect(controller.myLocationButton?.isDisabled(), true); + expect(controller.myLocationButton, isNotNull); + expect(controller.myLocationButton?.isDisabled(), true); + }); }); }); From 0a5267c5c9eb53cebd7e6a9308dbca4c98d29016 Mon Sep 17 00:00:00 2001 From: nploi Date: Fri, 28 Jul 2023 23:56:25 +0700 Subject: [PATCH 4/5] Update Unit-test --- .../google_maps_controller_test.dart | 33 ------------------- .../lib/src/my_location.dart | 3 +- 2 files changed, 1 insertion(+), 35 deletions(-) diff --git a/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_controller_test.dart b/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_controller_test.dart index 5cabfcfc074..ea94100bcbe 100644 --- a/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_controller_test.dart +++ b/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/google_maps_controller_test.dart @@ -584,39 +584,6 @@ void main() { expect(capturedMarkers.first.position, currentLocation); expect(capturedMarkers.first.zIndex, 0.5); }); - - testWidgets( - 'My location button should be disable when dont have permission access to location', - (WidgetTester tester) async { - late final MockGeolocation mockGeolocation = MockGeolocation(); - - controller = createController( - mapConfiguration: const MapConfiguration( - myLocationEnabled: true, - myLocationButtonEnabled: true, - )); - - controller.debugSetOverrides( - createMap: (_, __) => map, - markers: markers, - geolocation: mockGeolocation, - ); - - when(mockGeolocation.watchPosition()).thenAnswer((_) { - return Stream.error('permission denied'); - }); - when(mockGeolocation.getCurrentPosition(timeout: anyNamed('timeout'))) - .thenAnswer( - (_) async => throw Exception('permission denied'), - ); - - controller.init(); - - await tester.pumpAndSettle(); - - expect(controller.myLocationButton, isNotNull); - expect(controller.myLocationButton?.isDisabled(), true); - }); }); }); diff --git a/packages/google_maps_flutter/google_maps_flutter_web/lib/src/my_location.dart b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/my_location.dart index 85570c5baf7..f2171631a55 100644 --- a/packages/google_maps_flutter/google_maps_flutter_web/lib/src/my_location.dart +++ b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/my_location.dart @@ -76,7 +76,7 @@ void _addMyLocationButton(gmaps.GMap map, GoogleMapController controller) { controller._myLocationButton = MyLocationButton(); controller._myLocationButton?.addClickListener( (_) async { - _centerMyCurrentLocation(controller); + await _centerMyCurrentLocation(controller); }, ); map.addListener('dragend', () { @@ -201,7 +201,6 @@ class MyLocationButton { _btnChild.disabled = true; _imageChild.classes.remove('waiting'); _imageChild.style.backgroundPosition = '-24px 0px'; - print('disable button'); } /// Check button disabled or enabled From b74bfdcb14ea9349fbbbb579283a570017c8863e Mon Sep 17 00:00:00 2001 From: nploi Date: Sat, 29 Jul 2023 00:13:00 +0700 Subject: [PATCH 5/5] Fix lint --- .../google_maps_flutter_web/lib/google_maps_flutter_web.dart | 2 +- .../lib/src/google_maps_flutter_web.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/google_maps_flutter/google_maps_flutter_web/lib/google_maps_flutter_web.dart b/packages/google_maps_flutter/google_maps_flutter_web/lib/google_maps_flutter_web.dart index 150eff4606e..2d09f00472b 100644 --- a/packages/google_maps_flutter/google_maps_flutter_web/lib/google_maps_flutter_web.dart +++ b/packages/google_maps_flutter/google_maps_flutter_web/lib/google_maps_flutter_web.dart @@ -13,7 +13,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; -import 'package:flutter_web_plugins/flutter_web_plugins.dart'; +import 'package:flutter_web_plugins/flutter_web_plugins.dart' as flutter_web_plugins; import 'package:google_maps/google_maps.dart' as gmaps; import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart'; import 'package:sanitize_html/sanitize_html.dart'; diff --git a/packages/google_maps_flutter/google_maps_flutter_web/lib/src/google_maps_flutter_web.dart b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/google_maps_flutter_web.dart index 049a6a25ded..4dd285e13b4 100644 --- a/packages/google_maps_flutter/google_maps_flutter_web/lib/src/google_maps_flutter_web.dart +++ b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/google_maps_flutter_web.dart @@ -9,7 +9,7 @@ part of google_maps_flutter_web; /// This class implements the `package:google_maps_flutter` functionality for the web. class GoogleMapsPlugin extends GoogleMapsFlutterPlatform { /// Registers this class as the default instance of [GoogleMapsFlutterPlatform]. - static void registerWith(Registrar registrar) { + static void registerWith(flutter_web_plugins.Registrar registrar) { GoogleMapsFlutterPlatform.instance = GoogleMapsPlugin(); }