Skip to content

[google_maps_flutter_web] Add Advanced markers support (web) #9773

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

aednlaxer
Copy link
Contributor

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

  • I read the [Contributor Guide] and followed the process outlined there for submitting PRs.
  • I read the [Tree Hygiene] page, which explains my responsibilities.
  • I read and followed the [relevant style guides] and ran [the auto-formatter].
  • I signed the [CLA].
  • The title of the PR starts with the name of the package surrounded by square brackets, e.g. [shared_preferences]
  • I [linked to at least one issue that this PR fixes] in the description above.
  • I updated pubspec.yaml with 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].
  • I updated CHANGELOG.md to 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].
  • I updated/added any relevant documentation (doc comments with ///).
  • I added new tests to check the change I am making, or I have commented below to indicate which [test exemption] this PR falls under[^1].
  • All existing and new tests are passing.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

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.

Comment on lines +84 to +85
clusterManagersController: clusterManagersController!
as ClusterManagersController<gmaps.AdvancedMarkerElement>,

Choose a reason for hiding this comment

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

critical

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>,

Copy link
Contributor

Choose a reason for hiding this comment

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

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.

Comment on lines +666 to 678
MarkerId getMarkerId(Object? marker) {
final JSObject object = marker! as JSObject;
final gmaps.MVCObject mapObject = marker as gmaps.MVCObject;
if (object.isA<gmaps.Marker>()) {
return MarkerId((mapObject.get('markerId')! as JSString).toDart);
} else if (object.isA<gmaps.AdvancedMarkerElement>()) {
return MarkerId((mapObject.get('id')! as JSString).toDart);
} else {
throw ArgumentError(
'Must be either a gmaps.Marker or a gmaps.AdvancedMarkerElement',
);
}
}

Choose a reason for hiding this comment

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

critical

The implementation of getMarkerId has a couple of issues for AdvancedMarkerElement:

  1. gmaps.AdvancedMarkerElement is an HTMLElement and does not extend gmaps.MVCObject. The cast marker as gmaps.MVCObject will fail at runtime when the marker is an AdvancedMarkerElement.
  2. The id of an AdvancedMarkerElement is a standard DOM attribute, not a property set via MVCObject.set. It should be accessed directly from the element.

Here's a corrected implementation.

MarkerId getMarkerId(Object? marker) {
  final JSObject object = marker! as JSObject;
  if (object.isA<gmaps.Marker>()) {
    final gmaps.MVCObject mapObject = marker as gmaps.MVCObject;
    return MarkerId((mapObject.get('markerId')! as JSString).toDart);
  } else if (object.isA<gmaps.AdvancedMarkerElement>()) {
    final gmaps.AdvancedMarkerElement element =
        marker as gmaps.AdvancedMarkerElement;
    return MarkerId(element.id);
  } else {
    throw ArgumentError(
      'Must be either a gmaps.Marker or a gmaps.AdvancedMarkerElement',
    );
  }
}

@@ -20,6 +20,7 @@ import 'package:google_maps/google_maps_visualization.dart' as visualization;
import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart';
import 'package:sanitize_html/sanitize_html.dart';
import 'package:stream_transform/stream_transform.dart';
import 'package:web/web.dart' as web;
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this being imported twice, once with a namespace?

Comment on lines +84 to +85
clusterManagersController: clusterManagersController!
as ClusterManagersController<gmaps.AdvancedMarkerElement>,
Copy link
Contributor

Choose a reason for hiding this comment

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

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.

/// The `MarkerController` class wraps a [gmaps.AdvancedMarkerElement]
/// or [gmaps.Marker], how it handles events, and its associated (optional)
/// [gmaps.InfoWindow] widget.
abstract class MarkerController<T, O> {
Copy link
Contributor

Choose a reason for hiding this comment

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

I missed this before; isn't this a breaking change for this package? It looks like this (via the part directive) is public API, and the public constructor can no longer be directly called.

That's not a significant issue if we don't expect people to generally be creating one directly, but it does mean we need to version this PR as a major version change.

///
/// [T] must extend [JSObject]. It's not specified in code because our mocking
/// framework does not support mocking JSObjects.
abstract class MarkersController<T, O> extends GeometryController {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here; this looks breaking.

sanitize_html: ^2.0.0
stream_transform: ^2.0.0
web: ">=0.5.1 <2.0.0"
web: ">=1.0.0 <2.0.0"
Copy link
Contributor

Choose a reason for hiding this comment

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

This can just be ^1.0.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants