[google_maps_flutter_web] Add Advanced markers support (web)#9773
Conversation
There was a problem hiding this comment.
Code Review
This PR adds support for Advanced Markers to the web implementation of google_maps_flutter. The changes are extensive and well-structured, refactoring the marker handling logic to support both legacy and advanced markers through generics and abstract classes. New tests have been added for the new functionality, and existing ones have been updated. The implementation looks solid, but I've found a couple of critical issues that would prevent the code from compiling or running correctly.
| clusterManagersController: clusterManagersController! | ||
| as ClusterManagersController<gmaps.AdvancedMarkerElement>, |
There was a problem hiding this comment.
There's a typo here. clusterManagersController is used, but it should be _clusterManagersController. This will cause a compilation error as clusterManagersController is not defined in this scope.
clusterManagersController: _clusterManagersController!
as ClusterManagersController<gmaps.AdvancedMarkerElement>,
There was a problem hiding this comment.
Obviously this does compile, but it does make it order-sensitive to when the private variable is set, which we don't want, so this should use _clusterManagersController.
packages/google_maps_flutter/google_maps_flutter_web/lib/src/convert.dart
Outdated
Show resolved
Hide resolved
packages/google_maps_flutter/google_maps_flutter_web/lib/google_maps_flutter_web.dart
Show resolved
Hide resolved
| clusterManagersController: clusterManagersController! | ||
| as ClusterManagersController<gmaps.AdvancedMarkerElement>, |
There was a problem hiding this comment.
Obviously this does compile, but it does make it order-sensitive to when the private variable is set, which we don't want, so this should use _clusterManagersController.
packages/google_maps_flutter/google_maps_flutter_web/lib/src/marker.dart
Show resolved
Hide resolved
packages/google_maps_flutter/google_maps_flutter_web/lib/src/markers.dart
Outdated
Show resolved
Hide resolved
| sanitize_html: ^2.0.0 | ||
| stream_transform: ^2.0.0 | ||
| web: ">=0.5.1 <2.0.0" | ||
| web: ">=1.0.0 <2.0.0" |
There was a problem hiding this comment.
This can just be ^1.0.0
|
From triage: @aednlaxer Are you still planning on updating this PR? |
|
FYI: After merging in |
Yes, please don't close it |
9da73a7 to
65b8c81
Compare
mdebbar
left a comment
There was a problem hiding this comment.
Overall, it looks good to me! I just have a few minor code improvements.
| options.glyphColor = _getCssColor(circleGlyph.color); | ||
| case final TextGlyph textGlyph: | ||
| final web.Element element = web.document.createElement('p'); | ||
| element.innerHTML = textGlyph.text.toJS; |
There was a problem hiding this comment.
It's safer to use element.text:
| element.innerHTML = textGlyph.text.toJS; | |
| element.text = textGlyph.text; |
| element.setAttribute( | ||
| 'style', | ||
| 'color: ${_getCssColor(textGlyph.textColor!)}', | ||
| ); |
There was a problem hiding this comment.
| element.setAttribute( | |
| 'style', | |
| 'color: ${_getCssColor(textGlyph.textColor!)}', | |
| ); | |
| element.style.color = _getCssColor(textGlyph.textColor!); |
There was a problem hiding this comment.
Element type doesn't have style property:
https://github.com/dart-lang/web/blob/5a7d0be70a258252b95bac6b900f26d6dae4d433/web/lib/src/dom/dom.dart#L3132
| icon.setAttribute( | ||
| 'style', | ||
| <String>[ | ||
| if (size != null) ...<String>[ | ||
| 'width: ${size.width.toStringAsFixed(1)}px;', | ||
| 'height: ${size.height.toStringAsFixed(1)}px;', | ||
| ], | ||
| if (opacity != null) 'opacity: $opacity;', | ||
| if (isVisible != null) 'visibility: ${isVisible ? 'visible' : 'hidden'};', | ||
| ].join(' '), |
There was a problem hiding this comment.
| icon.setAttribute( | |
| 'style', | |
| <String>[ | |
| if (size != null) ...<String>[ | |
| 'width: ${size.width.toStringAsFixed(1)}px;', | |
| 'height: ${size.height.toStringAsFixed(1)}px;', | |
| ], | |
| if (opacity != null) 'opacity: $opacity;', | |
| if (isVisible != null) 'visibility: ${isVisible ? 'visible' : 'hidden'};', | |
| ].join(' '), | |
| final iconStyle = icon.style; | |
| if (size != null) { | |
| iconStyle | |
| ..width = '${size.width.toStringAsFixed(1)}px' | |
| ..height = '${size.height.toStringAsFixed(1)}px'; | |
| } | |
| if (opacity != null) { | |
| iconStyle.opacity = opacity; | |
| } | |
| if (isVisible != null) { | |
| iconStyle.visibility = isVisible ? 'visible' : 'hidden'; | |
| } |
There was a problem hiding this comment.
Icon type of the web package doesn't have style property either.
There was a problem hiding this comment.
Making icon of type HTMLImageElement should make it work.
| }); | ||
|
|
||
| @override | ||
| void initializeMarkerListener({ |
There was a problem hiding this comment.
We typically use the "add listener" terminology in the flutter code base: https://api.flutter.dev/flutter/search.html?q=addlistener
What do you think about renaming this to addMarkerListeners?
There was a problem hiding this comment.
I think it's better to keep the naming consistent. I have changed the function name to addMarkerListener.
| if (_infoWindow != null && newInfoWindowContent != null) { | ||
| _infoWindow.content = newInfoWindowContent; | ||
| if (onTap != null) { | ||
| marker.onClick.listen((gmaps.MapMouseEvent event) { |
There was a problem hiding this comment.
Do we need to unsubscribe from these listeners when the marker is removed?
If yes, it can easily be done:
_subscriptions = [
if (onTap != null) marker.onClick.listen((_) => onTap.call()),
if (onDragStart != null) marker.onDragstart.listen((event) {
marker.position = event.latLng;
onDragStart.call(event.latLng ?? _nullGmapsLatLng);
}),
...
];and later in void remove():
_subscriptions?.forEach((sub) => sub.cancel);
_subscriptions = null;| required VoidCallback? onTap, | ||
| }) { | ||
| if (onTap != null) { | ||
| marker.onClick.listen((gmaps.MapMouseEvent event) { |
There was a problem hiding this comment.
Same question about unsubscribing from listeners.
c1047c3 to
f72d139
Compare
mdebbar
left a comment
There was a problem hiding this comment.
Added some suggestions to make element.style and icon.style available.
| final web.Element icon = web.document.createElement('img') | ||
| ..setAttribute('src', url); |
There was a problem hiding this comment.
Let's use a more specific type so we can use icon.style:
| final web.Element icon = web.document.createElement('img') | |
| ..setAttribute('src', url); | |
| final web.HTMLImageElement icon = web.HTMLImageElement()..src = url; |
There was a problem hiding this comment.
Thanks for the suggestion. All changes done.
| final web.Element icon = web.document.createElement('img')..setAttribute( | ||
| 'src', | ||
| ui_web.assetManager.getAssetUrl(iconConfig[1]! as String), | ||
| ); |
| final web.Element icon = web.document.createElement('img') | ||
| ..setAttribute('src', web.URL.createObjectURL(blob as JSObject)); |
| icon.setAttribute( | ||
| 'style', | ||
| <String>[ | ||
| if (size != null) ...<String>[ | ||
| 'width: ${size.width.toStringAsFixed(1)}px;', | ||
| 'height: ${size.height.toStringAsFixed(1)}px;', | ||
| ], | ||
| if (opacity != null) 'opacity: $opacity;', | ||
| if (isVisible != null) 'visibility: ${isVisible ? 'visible' : 'hidden'};', | ||
| ].join(' '), |
There was a problem hiding this comment.
Making icon of type HTMLImageElement should make it work.
| final web.Element element = web.document.createElement('p'); | ||
| element.text = textGlyph.text; | ||
| if (textGlyph.textColor != null) { | ||
| element.setAttribute( | ||
| 'style', | ||
| 'color: ${_getCssColor(textGlyph.textColor!)}', | ||
| ); |
There was a problem hiding this comment.
Using a HTMLParagraphElement type will allow you to use element.style:
| final web.Element element = web.document.createElement('p'); | |
| element.text = textGlyph.text; | |
| if (textGlyph.textColor != null) { | |
| element.setAttribute( | |
| 'style', | |
| 'color: ${_getCssColor(textGlyph.textColor!)}', | |
| ); | |
| final web.HTMLParagraphElement element = web.HTMLParagraphElement(); | |
| element.text = textGlyph.text; | |
| if (textGlyph.textColor != null) { | |
| element.style.color = _getCssColor(textGlyph.textColor!); |
4cbf9d7 to
71404f1
Compare
71404f1 to
f30050c
Compare
| @override | ||
| Future<bool> isAdvancedMarkersAvailable({required int mapId}) async { | ||
| final GoogleMapController map = _map(mapId); | ||
| return map.isAdvancedMarkersAvailable(); |
There was a problem hiding this comment.
Nit: why not just return _map(mapId).isAdvancedMarkersAvailable() like the other methods? The intermediate variable doesn't seem to be adding anything here.
383a245 to
340adb9
Compare
|
@mdebbar @stuartmorgan-g Since the |
|
Sorry about that, I missed the previous comment. Landing now! |
flutter/packages@091acc5...1e50195 2026-02-10 20989940+aednlaxer@users.noreply.github.com [google_maps_flutter_web] Add Advanced markers support (web) (flutter/packages#9773) 2026-02-10 louisehsu@google.com [google_sign_in_ios][UIScene] Migrate to UIScene (flutter/packages#10960) 2026-02-10 stuartmorgan@google.com [google_maps_flutter] Fix custom marker icons on iOS (flutter/packages#10993) 2026-02-10 engine-flutter-autoroll@skia.org Roll Flutter from e8f9dc5 to 9bda20a (34 revisions) (flutter/packages#10992) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages-flutter-autoroll Please CC flutter-ecosystem@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
…r#182216) flutter/packages@091acc5...1e50195 2026-02-10 20989940+aednlaxer@users.noreply.github.com [google_maps_flutter_web] Add Advanced markers support (web) (flutter/packages#9773) 2026-02-10 louisehsu@google.com [google_sign_in_ios][UIScene] Migrate to UIScene (flutter/packages#10960) 2026-02-10 stuartmorgan@google.com [google_maps_flutter] Fix custom marker icons on iOS (flutter/packages#10993) 2026-02-10 engine-flutter-autoroll@skia.org Roll Flutter from e8f9dc5 to 9bda20a (34 revisions) (flutter/packages#10992) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages-flutter-autoroll Please CC flutter-ecosystem@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
This PR adds Advanced markers support to the web implementation of
google_maps_flutter.Approved combined PR: #7882
Approved and merged platform interface PR: #9737
Issue: #155526
Pre-Review Checklist
[shared_preferences]pubspec.yamlwith an appropriate new version according to the [pub versioning philosophy], or I have commented below to indicate which [version change exemption] this PR falls under[^1].CHANGELOG.mdto add a description of the change, [following repository CHANGELOG style], or I have commented below to indicate which [CHANGELOG exemption] this PR falls under[^1].///).