[google_maps_flutter_web] Fix InfoWindows and getLatLng. (#3163)
* Update package:google_maps to ^3.4.5.
* Fix GoogleMapController.getLatLng(): https://github.com/flutter/flutter/issues/67606
* Make InfoWindow contents clickable so onTap works as advertised: https://github.com/flutter/flutter/issues/67289
* Fix InfoWindow snippets when converting initial markers: https://github.com/flutter/flutter/issues/67854
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 1d40d67..e4918ab 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,10 @@
+## 0.1.0+5
+
+* Update `package:google_maps` to `^3.4.5`.
+* Fix `GoogleMapController.getLatLng()`. [Issue](https://github.com/flutter/flutter/issues/67606).
+* Make `InfoWindow` contents clickable so `onTap` works as advertised. [Issue](https://github.com/flutter/flutter/issues/67289).
+* Fix `InfoWindow` snippets when converting initial markers. [Issue](https://github.com/flutter/flutter/issues/67854).
+
## 0.1.0+4
* Update `package:sanitize_html` to `^1.4.1` to prevent [a crash](https://github.com/flutter/flutter/issues/67854) when InfoWindow title/snippet have links.
diff --git a/packages/google_maps_flutter/google_maps_flutter_web/lib/src/convert.dart b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/convert.dart
index 3e1b1f1..e8847fd 100644
--- a/packages/google_maps_flutter/google_maps_flutter_web/lib/src/convert.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/convert.dart
@@ -270,14 +270,15 @@
if (rawMarker['position'] != null) {
position = LatLng.fromJson(rawMarker['position']);
}
- if (rawMarker['infoWindow'] != null || rawMarker['snippet'] != null) {
- String title = rawMarker['infoWindow'] != null
- ? rawMarker['infoWindow']['title']
- : null;
- infoWindow = InfoWindow(
- title: title ?? '',
- snippet: rawMarker['snippet'] ?? '',
- );
+ if (rawMarker['infoWindow'] != null) {
+ final String title = rawMarker['infoWindow']['title'];
+ final String snippet = rawMarker['infoWindow']['snippet'];
+ if (title != null || snippet != null) {
+ infoWindow = InfoWindow(
+ title: title ?? '',
+ snippet: snippet ?? '',
+ );
+ }
}
return Marker(
markerId: MarkerId(rawMarker['markerId']),
@@ -378,13 +379,28 @@
return null;
}
- final content = '<h3 class="infowindow-title">' +
- sanitizeHtml(marker.infoWindow.title ?? "") +
- '</h3>' +
- sanitizeHtml(marker.infoWindow.snippet ?? "");
+ // Add an outer wrapper to the contents of the infowindow, we need it to listen
+ // to click events...
+ final HtmlElement container = DivElement()
+ ..id = 'gmaps-marker-${marker.markerId.value}-infowindow';
+ if (marker.infoWindow.title?.isNotEmpty ?? false) {
+ final HtmlElement title = HeadingElement.h3()
+ ..className = 'infowindow-title'
+ ..innerText = marker.infoWindow.title;
+ container.children.add(title);
+ }
+ if (marker.infoWindow.snippet?.isNotEmpty ?? false) {
+ final HtmlElement snippet = DivElement()
+ ..className = 'infowindow-snippet'
+ ..setInnerHtml(
+ sanitizeHtml(marker.infoWindow.snippet),
+ treeSanitizer: NodeTreeSanitizer.trusted,
+ );
+ container.children.add(snippet);
+ }
return gmaps.InfoWindowOptions()
- ..content = content
+ ..content = container
..zIndex = marker.zIndex;
// TODO: Compute the pixelOffset of the infoWindow, from the size of the Marker,
// and the marker.infoWindow.anchor property.
diff --git a/packages/google_maps_flutter/google_maps_flutter_web/lib/src/google_maps_controller.dart b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/google_maps_controller.dart
index 707af82..8195473 100644
--- a/packages/google_maps_flutter/google_maps_flutter_web/lib/src/google_maps_controller.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/google_maps_controller.dart
@@ -256,9 +256,8 @@
/// Returns the [LatLng] for a `screenCoordinate` (in pixels) of the viewport.
Future<LatLng> getLatLng(ScreenCoordinate screenCoordinate) async {
- final latLng = _googleMap.projection.fromPointToLatLng(
- gmaps.Point(screenCoordinate.x, screenCoordinate.y),
- );
+ final gmaps.LatLng latLng =
+ _pixelToLatLng(_googleMap, screenCoordinate.x, screenCoordinate.y);
return _gmLatLngToLatLng(latLng);
}
diff --git a/packages/google_maps_flutter/google_maps_flutter_web/lib/src/marker.dart b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/marker.dart
index a067e35..30db477 100644
--- a/packages/google_maps_flutter/google_maps_flutter_web/lib/src/marker.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/marker.dart
@@ -46,6 +46,10 @@
/// Returns the [gmaps.Marker] associated to this controller.
gmaps.Marker get marker => _marker;
+ /// Returns the [gmaps.InfoWindow] associated to the marker.
+ @visibleForTesting
+ gmaps.InfoWindow get infoWindow => _infoWindow;
+
/// Updates the options of the wrapped [gmaps.Marker] object.
void update(
gmaps.MarkerOptions options, {
diff --git a/packages/google_maps_flutter/google_maps_flutter_web/lib/src/markers.dart b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/markers.dart
index ebb478d..a0428ad 100644
--- a/packages/google_maps_flutter/google_maps_flutter_web/lib/src/markers.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/markers.dart
@@ -38,10 +38,14 @@
gmaps.InfoWindow gmInfoWindow;
if (infoWindowOptions != null) {
- gmInfoWindow = gmaps.InfoWindow(infoWindowOptions)
- ..addListener('click', () {
+ gmInfoWindow = gmaps.InfoWindow(infoWindowOptions);
+ // Google Maps' JS SDK does not have a click event on the InfoWindow, so
+ // we make one...
+ if (infoWindowOptions.content is HtmlElement) {
+ infoWindowOptions.content.onClick.listen((_) {
_onInfoWindowTap(marker.markerId);
});
+ }
}
final currentMarker = _markerIdToController[marker.markerId]?.marker;
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 6d0c917..a44d5c1 100644
--- a/packages/google_maps_flutter/google_maps_flutter_web/pubspec.yaml
+++ b/packages/google_maps_flutter/google_maps_flutter_web/pubspec.yaml
@@ -1,7 +1,7 @@
name: google_maps_flutter_web
description: Web platform implementation of google_maps_flutter
homepage: https://github.com/flutter/plugins/tree/master/packages/google_maps_flutter
-version: 0.1.0+4
+version: 0.1.0+5
flutter:
plugin:
@@ -17,7 +17,7 @@
sdk: flutter
meta: ^1.1.7
google_maps_flutter_platform_interface: ^1.0.4
- google_maps: ^3.0.0
+ google_maps: ^3.4.5
stream_transform: ^1.2.0
sanitize_html: ^1.4.1
diff --git a/packages/google_maps_flutter/google_maps_flutter_web/test/test_driver/google_maps_controller_integration.dart b/packages/google_maps_flutter/google_maps_flutter_web/test/test_driver/google_maps_controller_integration.dart
index 625ecb3..dfd01c6 100644
--- a/packages/google_maps_flutter/google_maps_flutter_web/test/test_driver/google_maps_controller_integration.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_web/test/test_driver/google_maps_controller_integration.dart
@@ -146,7 +146,13 @@
{'circleId': 'circle-1'}
],
'markersToAdd': [
- {'markerId': 'marker-1'}
+ {
+ 'markerId': 'marker-1',
+ 'infoWindow': {
+ 'title': 'title for test',
+ 'snippet': 'snippet for test',
+ },
+ },
],
'polygonsToAdd': [
{
@@ -191,10 +197,34 @@
expect(capturedCircles.first.circleId.value, 'circle-1');
expect(capturedMarkers.first.markerId.value, 'marker-1');
+ expect(capturedMarkers.first.infoWindow.snippet, 'snippet for test');
+ expect(capturedMarkers.first.infoWindow.title, 'title for test');
expect(capturedPolygons.first.polygonId.value, 'polygon-1');
expect(capturedPolylines.first.polylineId.value, 'polyline-1');
});
+ testWidgets('empty infoWindow does not create InfoWindow instance.',
+ (WidgetTester tester) async {
+ controller = _createController(options: {
+ 'markersToAdd': [
+ {
+ 'markerId': 'marker-1',
+ 'infoWindow': {},
+ },
+ ],
+ });
+ controller.debugSetOverrides(
+ markers: markers,
+ );
+
+ controller.init();
+
+ final capturedMarkers =
+ verify(markers.addMarkers(captureAny)).captured[0] as Set<Marker>;
+
+ expect(capturedMarkers.first.infoWindow, isNull);
+ });
+
group('Initialization options', () {
gmaps.MapOptions capturedOptions;
setUp(() {
@@ -390,6 +420,8 @@
group('map.projection methods', () {
// These are too much for dart mockito, can't mock:
// map.projection.method() (in Javascript ;) )
+
+ // Caused https://github.com/flutter/flutter/issues/67606
});
});
diff --git a/packages/google_maps_flutter/google_maps_flutter_web/test/test_driver/markers_integration.dart b/packages/google_maps_flutter/google_maps_flutter_web/test/test_driver/markers_integration.dart
index 75e1af7..a813ff8 100644
--- a/packages/google_maps_flutter/google_maps_flutter_web/test/test_driver/markers_integration.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_web/test/test_driver/markers_integration.dart
@@ -3,6 +3,7 @@
// found in the LICENSE file.
import 'dart:async';
+import 'dart:html';
import 'package:integration_test/integration_test.dart';
import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart';
@@ -127,8 +128,39 @@
controller.addMarkers(markers);
expect(controller.markers.length, 1);
- expect(controller.markers[MarkerId('1')].marker.title,
- equals('title for test'));
+ final content =
+ controller.markers[MarkerId('1')].infoWindow.content as HtmlElement;
+ expect(content.innerHtml, contains('title for test'));
+ expect(
+ content.innerHtml,
+ contains(
+ '<a href="https://www.google.com">Go to Google >>></a>'));
+ });
+
+ // https://github.com/flutter/flutter/issues/67289
+ testWidgets('InfoWindow content is clickable', (WidgetTester tester) async {
+ final markers = {
+ Marker(
+ markerId: MarkerId('1'),
+ infoWindow: InfoWindow(
+ title: 'title for test',
+ snippet: 'some snippet',
+ ),
+ ),
+ };
+
+ controller.addMarkers(markers);
+
+ expect(controller.markers.length, 1);
+ final content =
+ controller.markers[MarkerId('1')].infoWindow.content as HtmlElement;
+
+ content.click();
+
+ final event = await stream.stream.first;
+
+ expect(event, isA<InfoWindowTapEvent>());
+ expect((event as InfoWindowTapEvent).value, equals(MarkerId('1')));
});
});
}