Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 2.19.0

* Adds support for tapping points of interest on the map.

## 2.18.13

* Adopts new Pigeon async Swift support.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,27 @@ class StubBinaryMessenger: NSObject, FlutterBinaryMessenger {
}
}

/// Records POI tap callbacks for unit tests.
class MockMapEventHandler: TestMapEventHandler {
var lastTappedPointOfInterestPlaceIdentifier: String?
private var pointOfInterestTapContinuation: CheckedContinuation<Void, Never>?

func waitForPointOfInterestTap() async {
if lastTappedPointOfInterestPlaceIdentifier != nil {
return
}
await withCheckedContinuation { continuation in
pointOfInterestTapContinuation = continuation
}
}

override func didTapPointOfInterest(withPlaceIdentifier placeIdArg: String) async throws {
lastTappedPointOfInterestPlaceIdentifier = placeIdArg
pointOfInterestTapContinuation?.resume()
pointOfInterestTapContinuation = nil
}
}

class StubPluginRegistrar: NSObject, FlutterPluginRegistrar {
var viewController: UIViewController? { nil }
func publish(_ value: NSObject) {}
Expand Down Expand Up @@ -167,6 +188,36 @@ class StubPluginRegistrar: NSObject, FlutterPluginRegistrar {
#expect(mockTransactionWrapper.animationDuration == Double(durationMilliseconds) / 1000)
}

@Test func didTapPOIForwardsPlaceIdentifierToCallbackApi() async {
let frame = CGRect(x: 0, y: 0, width: 100, height: 100)
let mapViewOptions = GMSMapViewOptions()
mapViewOptions.frame = frame
mapViewOptions.camera = GMSCameraPosition(latitude: 0, longitude: 0, zoom: 0)

let mapView = PartiallyMockedMapView(options: mapViewOptions)

let mapEventHandler = MockMapEventHandler()
let controller = GoogleMapController(
mapView: mapView,
viewIdentifier: 0,
creationParameters: emptyCreationParameters(),
assetProvider: TestAssetProvider(),
binaryMessenger: StubBinaryMessenger(),
callbackHandler: mapEventHandler
)

async let poiTapReceived: Void = mapEventHandler.waitForPointOfInterestTap()
controller.mapView(
mapView,
didTapPOIWithPlaceID: "place-123",
name: "Test Place",
location: CLLocationCoordinate2DMake(0, 0)
)
await poiTapReceived

#expect(mapEventHandler.lastTappedPointOfInterestPlaceIdentifier == "place-123")
}

@Test func inspectorAPICameraPosition() throws {
let frame = CGRect(x: 0, y: 0, width: 100, height: 100)
let mapViewOptions = GMSMapViewOptions()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ class TestMapEventHandler: MapEventDelegate {

func didTapCircle(withIdentifier circleIdArg: String) async throws {}

func didTapPointOfInterest(withPlaceIdentifier placeIdArg: String) async throws {}

func didTapCluster(_ clusterArg: PlatformCluster) async throws {}

func didTapPolygon(withIdentifier polygonIdArg: String) async throws {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ dependencies:
# The example app is bundled with the plugin so we use a path dependency on
# the parent directory to use the current plugin's version.
path: ../
google_maps_flutter_platform_interface: ^2.14.1
google_maps_flutter_platform_interface: ^2.17.0

dev_dependencies:
flutter_test:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,11 @@ class FakeGoogleMapsFlutterPlatform extends GoogleMapsFlutterPlatform {
return mapEventStreamController.stream.whereType<CircleTapEvent>();
}

@override
Stream<PointOfInterestTapEvent> onPointOfInterestTap({required int mapId}) {
return mapEventStreamController.stream.whereType<PointOfInterestTapEvent>();
}

@override
Stream<MapTapEvent> onTap({required int mapId}) {
return mapEventStreamController.stream.whereType<MapTapEvent>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public class GoogleMapController: NSObject, GMSMapViewDelegate, FlutterPlatformV
/// The Google Maps SDK map view managed by this controller.
let mapView: GMSMapView
/// The Pigeon callback API implementation, used to send events to the Dart side.
let dartCallbackHandler: MapsCallbackApi
let dartCallbackHandler: MapEventDelegate
/// The main Pigeon API implementation, separate to avoid lifetime extension.
let callHandler: MapCallHandler
/// The inspector API implementation, separate to avoid lifetime extension.
Expand Down Expand Up @@ -101,21 +101,47 @@ public class GoogleMapController: NSObject, GMSMapViewDelegate, FlutterPlatformV
options.mapID = GMSMapID(identifier: mapId)
}

let binaryMessenger = registrar.messenger()
self.init(
mapView: GMSMapView(options: options),
viewIdentifier: viewId,
creationParameters: creationParameters,
assetProvider: DefaultAssetProvider(registrar: registrar),
binaryMessenger: registrar.messenger()
binaryMessenger: binaryMessenger,
callbackHandler: MapsCallbackApi(
binaryMessenger: binaryMessenger,
messageChannelSuffix: String(format: "%lld", viewId)
)
)
}

init(
convenience init(
mapView: GMSMapView,
viewIdentifier viewId: Int64,
creationParameters: PlatformMapViewCreationParams,
assetProvider: AssetProvider,
binaryMessenger: FlutterBinaryMessenger
) {
self.init(
mapView: mapView,
viewIdentifier: viewId,
creationParameters: creationParameters,
assetProvider: assetProvider,
binaryMessenger: binaryMessenger,
callbackHandler: MapsCallbackApi(
binaryMessenger: binaryMessenger,
messageChannelSuffix: String(format: "%lld", viewId)
)
)
}

init(
mapView: GMSMapView,
viewIdentifier viewId: Int64,
creationParameters: PlatformMapViewCreationParams,
assetProvider: AssetProvider,
binaryMessenger: FlutterBinaryMessenger,
callbackHandler: MapEventDelegate
) {
self.mapView = mapView
mapView.accessibilityElementsHidden = false
Expand All @@ -134,10 +160,7 @@ public class GoogleMapController: NSObject, GMSMapViewDelegate, FlutterPlatformV
// End duplicate code.

let pigeonSuffix = String(format: "%lld", viewId)
dartCallbackHandler = MapsCallbackApi(
binaryMessenger: binaryMessenger,
messageChannelSuffix: pigeonSuffix
)
dartCallbackHandler = callbackHandler

let markerType = creationParameters.mapConfiguration.markerType

Expand Down Expand Up @@ -167,7 +190,8 @@ public class GoogleMapController: NSObject, GMSMapViewDelegate, FlutterPlatformV
heatmapsController = HeatmapsController(mapView: mapView)
tileOverlaysController = TileOverlaysController(
mapView: mapView,
tileProvider: dartCallbackHandler
tileProvider: (callbackHandler as? MapsCallbackApi)
?? MapsCallbackApi(binaryMessenger: binaryMessenger, messageChannelSuffix: pigeonSuffix)
)
groundOverlaysController = GroundOverlaysController(
mapView: mapView,
Expand Down Expand Up @@ -396,6 +420,15 @@ public class GoogleMapController: NSObject, GMSMapViewDelegate, FlutterPlatformV
}
}

public func mapView(
_ mapView: GMSMapView, didTapPOIWithPlaceID placeID: String, name: String,
location: CLLocationCoordinate2D
) {
Task {
try await dartCallbackHandler.didTapPointOfInterest(withPlaceIdentifier: placeID)
}
}

func interpretMapConfiguration(_ config: PlatformMapConfiguration) {
// Any changes here must also be made to the `init` method above. See the comment there for
// details.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3455,6 +3455,8 @@ protocol MapsCallbackApiProtocol {
@MainActor func didTapInfoWindowOfMarker(withIdentifier markerIdArg: String) async throws
/// Called when a circle is tapped.
@MainActor func didTapCircle(withIdentifier circleIdArg: String) async throws
/// Called when a point of interest is tapped.
@MainActor func didTapPointOfInterest(withPlaceIdentifier placeIdArg: String) async throws
/// Called when a marker cluster is tapped.
@MainActor func didTapCluster(_ clusterArg: PlatformCluster) async throws
/// Called when a polygon is tapped.
Expand Down Expand Up @@ -3738,6 +3740,29 @@ class MapsCallbackApi: MapsCallbackApiProtocol {
}
}
}
/// Called when a point of interest is tapped.
@MainActor func didTapPointOfInterest(withPlaceIdentifier placeIdArg: String) async throws {
return try await withCheckedThrowingContinuation { continuation in
let channelName: String =
"dev.flutter.pigeon.google_maps_flutter_ios.MapsCallbackApi.onPointOfInterestTap\(messageChannelSuffix)"
let channel = FlutterBasicMessageChannel(
name: channelName, binaryMessenger: binaryMessenger, codec: codec)
channel.sendMessage([placeIdArg] as [Any?]) { response in
guard let listResponse = response as? [Any?] else {
continuation.resume(throwing: createConnectionError(withChannelName: channelName))
return
}
if listResponse.count > 1 {
let code: String = listResponse[0] as! String
let message: String? = nilOrValue(listResponse[1])
let details: String? = nilOrValue(listResponse[2])
continuation.resume(throwing: PigeonError(code: code, message: message, details: details))
} else {
continuation.resume()
}
}
}
}
/// Called when a marker cluster is tapped.
@MainActor func didTapCluster(_ clusterArg: PlatformCluster) async throws {
return try await withCheckedThrowingContinuation { continuation in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,11 @@ class GoogleMapsFlutterIOS extends GoogleMapsFlutterPlatform {
return _events(mapId).whereType<CircleTapEvent>();
}

@override
Stream<PointOfInterestTapEvent> onPointOfInterestTap({required int mapId}) {
return _events(mapId).whereType<PointOfInterestTapEvent>();
}

@override
Stream<GroundOverlayTapEvent> onGroundOverlayTap({required int mapId}) {
return _events(mapId).whereType<GroundOverlayTapEvent>();
Expand Down Expand Up @@ -957,6 +962,11 @@ class HostMapMessageHandler implements MapsCallbackApi {
streamController.add(CircleTapEvent(mapId, CircleId(circleId)));
}

@override
void onPointOfInterestTap(String placeId) {
streamController.add(PointOfInterestTapEvent(mapId, PointOfInterestId(placeId)));
}

@override
void onClusterTap(PlatformCluster cluster) {
streamController.add(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3456,6 +3456,9 @@ abstract class MapsCallbackApi {
/// Called when a circle is tapped.
void onCircleTap(String circleId);

/// Called when a point of interest is tapped.
void onPointOfInterestTap(String placeId);

/// Called when a marker cluster is tapped.
void onClusterTap(PlatformCluster cluster);

Expand Down Expand Up @@ -3751,6 +3754,31 @@ abstract class MapsCallbackApi {
});
}
}
{
final pigeonVar_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.google_maps_flutter_ios.MapsCallbackApi.onPointOfInterestTap$messageChannelSuffix',
pigeonChannelCodec,
binaryMessenger: binaryMessenger,
);
if (api == null) {
pigeonVar_channel.setMessageHandler(null);
} else {
pigeonVar_channel.setMessageHandler((Object? message) async {
final List<Object?> args = message! as List<Object?>;
final String arg_placeId = args[0]! as String;
try {
api.onPointOfInterestTap(arg_placeId);
return wrapResponse(empty: true);
} on PlatformException catch (e) {
return wrapResponse(error: e);
} catch (e) {
return wrapResponse(
error: PlatformException(code: 'error', message: e.toString()),
);
}
});
}
}
{
final pigeonVar_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.google_maps_flutter_ios.MapsCallbackApi.onClusterTap$messageChannelSuffix',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -803,6 +803,10 @@ abstract class MapsCallbackApi {
@SwiftFunction('didTapCircle(withIdentifier:)')
void onCircleTap(String circleId);

/// Called when a point of interest is tapped.
@SwiftFunction('didTapPointOfInterest(withPlaceIdentifier:)')
void onPointOfInterestTap(String placeId);

/// Called when a marker cluster is tapped.
@SwiftFunction('didTapCluster(_:)')
void onClusterTap(PlatformCluster cluster);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: google_maps_flutter_ios_sdk10
description: iOS implementation of the google_maps_flutter plugin using Google Maps SDK 10.
repository: https://github.com/flutter/packages/tree/main/packages/google_maps_flutter/google_maps_flutter_ios_sdk10
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+maps%22
version: 2.18.13
version: 2.19.0

environment:
sdk: ^3.10.0
Expand All @@ -19,7 +19,7 @@ flutter:
dependencies:
flutter:
sdk: flutter
google_maps_flutter_platform_interface: ^2.14.2
google_maps_flutter_platform_interface: ^2.17.0
meta: ^1.10.0
stream_transform: ^2.0.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -903,6 +903,20 @@ void main() {
expect((await stream.next).value.value, equals(objectId));
});

test('points of interest send tap events to correct stream', () async {
const mapId = 1;
const placeId = 'place-id';

final maps = GoogleMapsFlutterIOS();
final HostMapMessageHandler callbackHandler = maps.ensureHandlerInitialized(mapId);

final stream = StreamQueue<PointOfInterestTapEvent>(maps.onPointOfInterestTap(mapId: mapId));

callbackHandler.onPointOfInterestTap(placeId);

expect((await stream.next).value.value, equals(placeId));
});

test('clusters send tap events to correct stream', () async {
const mapId = 1;
const managerId = 'manager-id';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 2.19.0

* Adds support for tapping points of interest on the map.

## 2.18.14

* Adopts new Pigeon async Swift support.
Expand Down
Loading
Loading