From 720b76258a267c3672cdc484ba04e5eb61bd69f7 Mon Sep 17 00:00:00 2001 From: David Iglesias Teixeira Date: Thu, 4 Aug 2022 18:38:43 -0700 Subject: [PATCH 1/5] [google_maps_flutter_platform_interface] Adds size to BitmapDescriptor.fromBytes --- .../CHANGELOG.md | 6 +++ .../lib/src/types/bitmap.dart | 18 ++++++- .../pubspec.yaml | 2 +- .../test/types/bitmap_test.dart | 52 +++++++++++++++++++ 4 files changed, 75 insertions(+), 3 deletions(-) diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/CHANGELOG.md b/packages/google_maps_flutter/google_maps_flutter_platform_interface/CHANGELOG.md index e8da5f3aba99..5aae75133045 100644 --- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/CHANGELOG.md +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/CHANGELOG.md @@ -1,3 +1,9 @@ +## 2.2.2 + +* Adds a `size` parameter to `BitmapDescriptor.fromBytes`, so **web** applications + can specify the actual *physical size* of the bitmap. The parameter is not needed + (and ignored) in other platforms. Issue [#73789](https://github.com/flutter/flutter/issues/73789). + ## 2.2.1 * Adds a new interface for inspecting the platform map state in tests. diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/bitmap.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/bitmap.dart index 0ccc3e624abe..7dda43a7abf4 100644 --- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/bitmap.dart +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/bitmap.dart @@ -157,8 +157,22 @@ class BitmapDescriptor { /// Creates a BitmapDescriptor using an array of bytes that must be encoded /// as PNG. - static BitmapDescriptor fromBytes(Uint8List byteData) { - return BitmapDescriptor._([_fromBytes, byteData]); + /// On the web, the [size] parameter represents the *physical size* of the + /// bitmap, regardless of the actual resolution of the encoded PNG. + /// This helps the browser to render High-DPI images at the correct size. + /// `size` is not required (and ignored, if passed) in other platforms. + static BitmapDescriptor fromBytes(Uint8List byteData, {Size? size}) { + assert(byteData.isNotEmpty, + 'Cannot create BitmapDescriptor with empty byteData'); + return BitmapDescriptor._([ + _fromBytes, + byteData, + if (kIsWeb && size != null) + [ + size.width, + size.height, + ] + ]); } final Object _json; diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter_platform_interface/pubspec.yaml index f1463c71230a..9f4b7c03fdb2 100644 --- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/pubspec.yaml +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/pubspec.yaml @@ -4,7 +4,7 @@ repository: https://github.com/flutter/plugins/tree/main/packages/google_maps_fl issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+maps%22 # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 2.2.1 +version: 2.2.2 environment: sdk: '>=2.12.0 <3.0.0' diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/bitmap_test.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/bitmap_test.dart index 7fbaf4998355..a6f890ca07a4 100644 --- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/bitmap_test.dart +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/bitmap_test.dart @@ -3,7 +3,9 @@ // found in the LICENSE file. import 'dart:typed_data'; +import 'dart:ui'; +import 'package:flutter/foundation.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart'; @@ -26,6 +28,56 @@ void main() { expect(identical(descriptorFromJson.toJson(), json), isTrue); // Same JSON }); + group('fromBytes constructor', () { + test('with empty byte array, throws assertion error', () { + expect(() { + BitmapDescriptor.fromBytes(Uint8List.fromList([])); + }, throwsAssertionError); + }); + + test('with bytes', () { + final BitmapDescriptor descriptor = BitmapDescriptor.fromBytes( + Uint8List.fromList([1, 2, 3]), + ); + expect(descriptor, isA()); + expect( + descriptor.toJson(), + equals([ + 'fromBytes', + [1, 2, 3], + ])); + }); + + test('with size, not on the web, size is ignored', () { + final BitmapDescriptor descriptor = BitmapDescriptor.fromBytes( + Uint8List.fromList([1, 2, 3]), + size: const Size(40, 20), + ); + + expect( + descriptor.toJson(), + equals([ + 'fromBytes', + [1, 2, 3], + ])); + }, skip: kIsWeb); + + test('with size, on the web, size is preserved', () { + final BitmapDescriptor descriptor = BitmapDescriptor.fromBytes( + Uint8List.fromList([1, 2, 3]), + size: const Size(40, 20), + ); + + expect( + descriptor.toJson(), + equals([ + 'fromBytes', + [1, 2, 3], + [40, 20], + ])); + }, skip: !kIsWeb); + }); + group('fromJson validation', () { group('type validation', () { test('correct type', () { From 2d7bdbdce2782f2348338268c8343e3e469ea8fe Mon Sep 17 00:00:00 2001 From: David Iglesias Teixeira Date: Thu, 4 Aug 2022 21:20:53 -0700 Subject: [PATCH 2/5] Ignore unnecessary_import in test --- .../test/types/bitmap_test.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/bitmap_test.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/bitmap_test.dart index a6f890ca07a4..2499e87bb649 100644 --- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/bitmap_test.dart +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/bitmap_test.dart @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// ignore:unnecessary_import import 'dart:typed_data'; import 'dart:ui'; From 0faca95a6120aed22108cefedbe6b7fcb8f9096d Mon Sep 17 00:00:00 2001 From: David Iglesias Teixeira Date: Thu, 4 Aug 2022 20:47:40 -0700 Subject: [PATCH 3/5] [google_maps_flutter_web] Use size from BitmapDescriptor.fromBytes. --- .../google_maps_flutter_web/CHANGELOG.md | 5 ++ .../google_maps_controller_test.mocks.dart | 67 +++++++++------ .../google_maps_plugin_test.mocks.dart | 86 +++++++++++++------ .../integration_test/markers_test.dart | 40 +++++++-- .../example/pubspec.yaml | 4 + .../lib/src/convert.dart | 57 ++++++++---- .../google_maps_flutter_web/pubspec.yaml | 6 +- 7 files changed, 187 insertions(+), 78 deletions(-) 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 d86642934b77..3e4a7b14d09d 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,8 @@ +## 0.4.0+2 + +* Updates conversion of `BitmapDescriptor.fromBytes` marker icons to support the + new `size` parameter. Issue [#73789](https://github.com/flutter/flutter/issues/73789). + ## 0.4.0+1 * Updates `README.md` to describe a hit-testing issue when Flutter widgets are overlaid on top of the Map widget. 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 9565935bd8ed..a7fe6bae347b 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 @@ -1,7 +1,8 @@ -// Mocks generated by Mockito 5.2.0 from annotations +// Mocks generated by Mockito 5.3.0 from annotations // in google_maps_flutter_web_integration_tests/integration_test/google_maps_controller_test.dart. // Do not manually edit this file. +// ignore_for_file: no_leading_underscores_for_library_prefixes import 'package:google_maps/google_maps.dart' as _i2; import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart' as _i4; @@ -17,8 +18,12 @@ import 'package:mockito/mockito.dart' as _i1; // ignore_for_file: prefer_const_constructors // ignore_for_file: unnecessary_parenthesis // ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class -class _FakeGMap_0 extends _i1.Fake implements _i2.GMap {} +class _FakeGMap_0 extends _i1.SmartFake implements _i2.GMap { + _FakeGMap_0(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} /// A class which mocks [CirclesController]. /// @@ -27,18 +32,21 @@ class MockCirclesController extends _i1.Mock implements _i3.CirclesController { @override Map<_i4.CircleId, _i3.CircleController> get circles => (super.noSuchMethod(Invocation.getter(#circles), - returnValue: <_i4.CircleId, _i3.CircleController>{}) + returnValue: <_i4.CircleId, _i3.CircleController>{}, + returnValueForMissingStub: <_i4.CircleId, _i3.CircleController>{}) as Map<_i4.CircleId, _i3.CircleController>); @override _i2.GMap get googleMap => (super.noSuchMethod(Invocation.getter(#googleMap), - returnValue: _FakeGMap_0()) as _i2.GMap); + returnValue: _FakeGMap_0(this, Invocation.getter(#googleMap)), + returnValueForMissingStub: + _FakeGMap_0(this, Invocation.getter(#googleMap))) as _i2.GMap); @override set googleMap(_i2.GMap? _googleMap) => super.noSuchMethod(Invocation.setter(#googleMap, _googleMap), returnValueForMissingStub: null); @override - int get mapId => - (super.noSuchMethod(Invocation.getter(#mapId), returnValue: 0) as int); + int get mapId => (super.noSuchMethod(Invocation.getter(#mapId), + returnValue: 0, returnValueForMissingStub: 0) as int); @override set mapId(int? _mapId) => super.noSuchMethod(Invocation.setter(#mapId, _mapId), @@ -67,20 +75,23 @@ class MockCirclesController extends _i1.Mock implements _i3.CirclesController { class MockPolygonsController extends _i1.Mock implements _i3.PolygonsController { @override - Map<_i4.PolygonId, _i3.PolygonController> get polygons => - (super.noSuchMethod(Invocation.getter(#polygons), - returnValue: <_i4.PolygonId, _i3.PolygonController>{}) - as Map<_i4.PolygonId, _i3.PolygonController>); + Map<_i4.PolygonId, _i3.PolygonController> get polygons => (super.noSuchMethod( + Invocation.getter(#polygons), + returnValue: <_i4.PolygonId, _i3.PolygonController>{}, + returnValueForMissingStub: <_i4.PolygonId, _i3.PolygonController>{}) + as Map<_i4.PolygonId, _i3.PolygonController>); @override _i2.GMap get googleMap => (super.noSuchMethod(Invocation.getter(#googleMap), - returnValue: _FakeGMap_0()) as _i2.GMap); + returnValue: _FakeGMap_0(this, Invocation.getter(#googleMap)), + returnValueForMissingStub: + _FakeGMap_0(this, Invocation.getter(#googleMap))) as _i2.GMap); @override set googleMap(_i2.GMap? _googleMap) => super.noSuchMethod(Invocation.setter(#googleMap, _googleMap), returnValueForMissingStub: null); @override - int get mapId => - (super.noSuchMethod(Invocation.getter(#mapId), returnValue: 0) as int); + int get mapId => (super.noSuchMethod(Invocation.getter(#mapId), + returnValue: 0, returnValueForMissingStub: 0) as int); @override set mapId(int? _mapId) => super.noSuchMethod(Invocation.setter(#mapId, _mapId), @@ -109,20 +120,23 @@ class MockPolygonsController extends _i1.Mock class MockPolylinesController extends _i1.Mock implements _i3.PolylinesController { @override - Map<_i4.PolylineId, _i3.PolylineController> get lines => - (super.noSuchMethod(Invocation.getter(#lines), - returnValue: <_i4.PolylineId, _i3.PolylineController>{}) - as Map<_i4.PolylineId, _i3.PolylineController>); + Map<_i4.PolylineId, _i3.PolylineController> get lines => (super.noSuchMethod( + Invocation.getter(#lines), + returnValue: <_i4.PolylineId, _i3.PolylineController>{}, + returnValueForMissingStub: <_i4.PolylineId, _i3.PolylineController>{}) + as Map<_i4.PolylineId, _i3.PolylineController>); @override _i2.GMap get googleMap => (super.noSuchMethod(Invocation.getter(#googleMap), - returnValue: _FakeGMap_0()) as _i2.GMap); + returnValue: _FakeGMap_0(this, Invocation.getter(#googleMap)), + returnValueForMissingStub: + _FakeGMap_0(this, Invocation.getter(#googleMap))) as _i2.GMap); @override set googleMap(_i2.GMap? _googleMap) => super.noSuchMethod(Invocation.setter(#googleMap, _googleMap), returnValueForMissingStub: null); @override - int get mapId => - (super.noSuchMethod(Invocation.getter(#mapId), returnValue: 0) as int); + int get mapId => (super.noSuchMethod(Invocation.getter(#mapId), + returnValue: 0, returnValueForMissingStub: 0) as int); @override set mapId(int? _mapId) => super.noSuchMethod(Invocation.setter(#mapId, _mapId), @@ -152,18 +166,21 @@ class MockMarkersController extends _i1.Mock implements _i3.MarkersController { @override Map<_i4.MarkerId, _i3.MarkerController> get markers => (super.noSuchMethod(Invocation.getter(#markers), - returnValue: <_i4.MarkerId, _i3.MarkerController>{}) + returnValue: <_i4.MarkerId, _i3.MarkerController>{}, + returnValueForMissingStub: <_i4.MarkerId, _i3.MarkerController>{}) as Map<_i4.MarkerId, _i3.MarkerController>); @override _i2.GMap get googleMap => (super.noSuchMethod(Invocation.getter(#googleMap), - returnValue: _FakeGMap_0()) as _i2.GMap); + returnValue: _FakeGMap_0(this, Invocation.getter(#googleMap)), + returnValueForMissingStub: + _FakeGMap_0(this, Invocation.getter(#googleMap))) as _i2.GMap); @override set googleMap(_i2.GMap? _googleMap) => super.noSuchMethod(Invocation.setter(#googleMap, _googleMap), returnValueForMissingStub: null); @override - int get mapId => - (super.noSuchMethod(Invocation.getter(#mapId), returnValue: 0) as int); + int get mapId => (super.noSuchMethod(Invocation.getter(#mapId), + returnValue: 0, returnValueForMissingStub: 0) as int); @override set mapId(int? _mapId) => super.noSuchMethod(Invocation.setter(#mapId, _mapId), @@ -191,7 +208,7 @@ class MockMarkersController extends _i1.Mock implements _i3.MarkersController { @override bool isInfoWindowShown(_i4.MarkerId? markerId) => (super.noSuchMethod(Invocation.method(#isInfoWindowShown, [markerId]), - returnValue: false) as bool); + returnValue: false, returnValueForMissingStub: false) as bool); @override void bindToMap(int? mapId, _i2.GMap? googleMap) => super.noSuchMethod(Invocation.method(#bindToMap, [mapId, googleMap]), 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 744552f45d4d..04cbc4a3416d 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 @@ -1,7 +1,8 @@ -// Mocks generated by Mockito 5.2.0 from annotations +// Mocks generated by Mockito 5.3.0 from annotations // in google_maps_flutter_web_integration_tests/integration_test/google_maps_plugin_test.dart. // Do not manually edit this file. +// ignore_for_file: no_leading_underscores_for_library_prefixes import 'dart:async' as _i2; import 'package:google_maps/google_maps.dart' as _i5; @@ -19,16 +20,29 @@ import 'package:mockito/mockito.dart' as _i1; // ignore_for_file: prefer_const_constructors // ignore_for_file: unnecessary_parenthesis // ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class -class _FakeStreamController_0 extends _i1.Fake - implements _i2.StreamController {} +class _FakeStreamController_0 extends _i1.SmartFake + implements _i2.StreamController { + _FakeStreamController_0(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} -class _FakeLatLngBounds_1 extends _i1.Fake implements _i3.LatLngBounds {} +class _FakeLatLngBounds_1 extends _i1.SmartFake implements _i3.LatLngBounds { + _FakeLatLngBounds_1(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} -class _FakeScreenCoordinate_2 extends _i1.Fake implements _i3.ScreenCoordinate { +class _FakeScreenCoordinate_2 extends _i1.SmartFake + implements _i3.ScreenCoordinate { + _FakeScreenCoordinate_2(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); } -class _FakeLatLng_3 extends _i1.Fake implements _i3.LatLng {} +class _FakeLatLng_3 extends _i1.SmartFake implements _i3.LatLng { + _FakeLatLng_3(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} /// A class which mocks [GoogleMapController]. /// @@ -36,19 +50,23 @@ class _FakeLatLng_3 extends _i1.Fake implements _i3.LatLng {} class MockGoogleMapController extends _i1.Mock implements _i4.GoogleMapController { @override - _i2.StreamController<_i3.MapEvent> get stream => - (super.noSuchMethod(Invocation.getter(#stream), - returnValue: _FakeStreamController_0<_i3.MapEvent>()) - as _i2.StreamController<_i3.MapEvent>); + _i2.StreamController<_i3.MapEvent> get stream => (super.noSuchMethod( + Invocation.getter(#stream), + returnValue: _FakeStreamController_0<_i3.MapEvent>( + this, Invocation.getter(#stream)), + returnValueForMissingStub: _FakeStreamController_0<_i3.MapEvent>( + this, Invocation.getter(#stream))) as _i2 + .StreamController<_i3.MapEvent>); @override - _i2.Stream<_i3.MapEvent> get events => - (super.noSuchMethod(Invocation.getter(#events), - returnValue: Stream<_i3.MapEvent>.empty()) - as _i2.Stream<_i3.MapEvent>); + _i2.Stream<_i3.MapEvent> get events => (super.noSuchMethod( + Invocation.getter(#events), + returnValue: _i2.Stream<_i3.MapEvent>.empty(), + returnValueForMissingStub: _i2.Stream<_i3.MapEvent>.empty()) + as _i2.Stream<_i3.MapEvent>); @override bool get isInitialized => - (super.noSuchMethod(Invocation.getter(#isInitialized), returnValue: false) - as bool); + (super.noSuchMethod(Invocation.getter(#isInitialized), + returnValue: false, returnValueForMissingStub: false) as bool); @override void debugSetOverrides( {_i4.DebugCreateMapFunction? createMap, @@ -78,29 +96,43 @@ class MockGoogleMapController extends _i1.Mock returnValueForMissingStub: null); @override _i2.Future<_i3.LatLngBounds> getVisibleRegion() => (super.noSuchMethod( - Invocation.method(#getVisibleRegion, []), - returnValue: Future<_i3.LatLngBounds>.value(_FakeLatLngBounds_1())) - as _i2.Future<_i3.LatLngBounds>); + Invocation.method(#getVisibleRegion, []), + returnValue: _i2.Future<_i3.LatLngBounds>.value( + _FakeLatLngBounds_1(this, Invocation.method(#getVisibleRegion, []))), + returnValueForMissingStub: _i2.Future<_i3.LatLngBounds>.value( + _FakeLatLngBounds_1( + this, Invocation.method(#getVisibleRegion, [])))) as _i2 + .Future<_i3.LatLngBounds>); @override _i2.Future<_i3.ScreenCoordinate> getScreenCoordinate(_i3.LatLng? latLng) => (super.noSuchMethod(Invocation.method(#getScreenCoordinate, [latLng]), - returnValue: - Future<_i3.ScreenCoordinate>.value(_FakeScreenCoordinate_2())) + returnValue: _i2.Future<_i3.ScreenCoordinate>.value( + _FakeScreenCoordinate_2( + this, Invocation.method(#getScreenCoordinate, [latLng]))), + returnValueForMissingStub: _i2.Future<_i3.ScreenCoordinate>.value( + _FakeScreenCoordinate_2( + this, Invocation.method(#getScreenCoordinate, [latLng])))) as _i2.Future<_i3.ScreenCoordinate>); @override _i2.Future<_i3.LatLng> getLatLng(_i3.ScreenCoordinate? screenCoordinate) => (super.noSuchMethod(Invocation.method(#getLatLng, [screenCoordinate]), - returnValue: Future<_i3.LatLng>.value(_FakeLatLng_3())) - as _i2.Future<_i3.LatLng>); + returnValue: _i2.Future<_i3.LatLng>.value(_FakeLatLng_3( + this, Invocation.method(#getLatLng, [screenCoordinate]))), + returnValueForMissingStub: _i2.Future<_i3.LatLng>.value(_FakeLatLng_3( + this, Invocation.method(#getLatLng, [screenCoordinate])))) as _i2 + .Future<_i3.LatLng>); @override _i2.Future moveCamera(_i3.CameraUpdate? cameraUpdate) => (super.noSuchMethod(Invocation.method(#moveCamera, [cameraUpdate]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i2.Future); + returnValue: _i2.Future.value(), + returnValueForMissingStub: _i2.Future.value()) + as _i2.Future); @override _i2.Future getZoomLevel() => (super.noSuchMethod(Invocation.method(#getZoomLevel, []), - returnValue: Future.value(0.0)) as _i2.Future); + returnValue: _i2.Future.value(0.0), + returnValueForMissingStub: _i2.Future.value(0.0)) + as _i2.Future); @override void updateCircles(_i3.CircleUpdates? updates) => super.noSuchMethod(Invocation.method(#updateCircles, [updates]), @@ -128,7 +160,7 @@ class MockGoogleMapController extends _i1.Mock @override bool isInfoWindowShown(_i3.MarkerId? markerId) => (super.noSuchMethod(Invocation.method(#isInfoWindowShown, [markerId]), - returnValue: false) as bool); + returnValue: false, returnValueForMissingStub: false) as bool); @override void dispose() => super.noSuchMethod(Invocation.method(#dispose, []), returnValueForMissingStub: null); diff --git a/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/markers_test.dart b/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/markers_test.dart index 90195ec6397b..e4c4dd7c0cfe 100644 --- a/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/markers_test.dart +++ b/packages/google_maps_flutter/google_maps_flutter_web/example/integration_test/markers_test.dart @@ -5,8 +5,8 @@ import 'dart:async'; import 'dart:convert'; import 'dart:html' as html; -import 'dart:js_util' show getProperty; import 'dart:typed_data'; +import 'dart:ui'; import 'package:flutter_test/flutter_test.dart'; import 'package:google_maps/google_maps.dart' as gmaps; @@ -155,22 +155,46 @@ void main() { controller.addMarkers(markers); expect(controller.markers.length, 1); - expect(controller.markers[const MarkerId('1')]?.marker?.icon, isNotNull); - - final String blobUrl = getProperty( - controller.markers[const MarkerId('1')]!.marker!.icon!, - 'url', - ); + final gmaps.Icon? icon = + controller.markers[const MarkerId('1')]?.marker?.icon as gmaps.Icon?; + expect(icon, isNotNull); + final String blobUrl = icon!.url!; expect(blobUrl, startsWith('blob:')); final http.Response response = await http.get(Uri.parse(blobUrl)); - expect(response.bodyBytes, bytes, reason: 'Bytes from the Icon blob must match bytes used to create Marker'); }); + // https://github.com/flutter/flutter/issues/73789 + testWidgets('markers with custom bitmap icon pass size to sdk', + (WidgetTester tester) async { + final Uint8List bytes = const Base64Decoder().convert(iconImageBase64); + final Set markers = { + Marker( + markerId: const MarkerId('1'), + icon: BitmapDescriptor.fromBytes(bytes, size: const Size(20, 30)), + ), + }; + + controller.addMarkers(markers); + + expect(controller.markers.length, 1); + final gmaps.Icon? icon = + controller.markers[const MarkerId('1')]?.marker?.icon as gmaps.Icon?; + expect(icon, isNotNull); + + final gmaps.Size size = icon!.size!; + final gmaps.Size scaledSize = icon.scaledSize!; + + expect(size.width, 20); + expect(size.height, 30); + expect(scaledSize.width, 20); + expect(scaledSize.height, 30); + }); + // https://github.com/flutter/flutter/issues/67854 testWidgets('InfoWindow snippet can have links', (WidgetTester tester) async { diff --git a/packages/google_maps_flutter/google_maps_flutter_web/example/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter_web/example/pubspec.yaml index 82c36e22b15f..477fd2aee941 100644 --- a/packages/google_maps_flutter/google_maps_flutter_web/example/pubspec.yaml +++ b/packages/google_maps_flutter/google_maps_flutter_web/example/pubspec.yaml @@ -12,6 +12,10 @@ dependencies: google_maps_flutter_web: path: ../ +dependency_overrides: + google_maps_flutter_platform_interface: + path: ../../google_maps_flutter_platform_interface + dev_dependencies: build_runner: ^2.1.1 flutter_driver: 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 250bb5468fa7..2b09950cc00d 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 @@ -228,14 +228,25 @@ gmaps.InfoWindowOptions? _infoWindowOptionsFromMarker(Marker marker) { // and the marker.infoWindow.anchor property. } -// Computes the options for a new [gmaps.Marker] from an incoming set of options -// [marker], and the existing marker registered with the map: [currentMarker]. -// Preserves the position from the [currentMarker], if set. -gmaps.MarkerOptions _markerOptionsFromMarker( - Marker marker, - gmaps.Marker? currentMarker, -) { - final List iconConfig = marker.icon.toJson() as List; +// Attempts to extract a [gmaps.Size] from `iconConfig[sizeIndex]`. +gmaps.Size? _gmSizeFromIconConfig(List iconConfig, int sizeIndex) { + gmaps.Size? size; + if (iconConfig.length >= sizeIndex + 1) { + final List? rawIconSize = iconConfig[sizeIndex] as List?; + if (rawIconSize != null) { + size = gmaps.Size( + rawIconSize[0] as num?, + rawIconSize[1] as num?, + ); + } + } + return size; +} + +// Converts a [BitmapDescriptor] into a [gmaps.Icon] that can be used in Markers. +gmaps.Icon? _gmIconFromBitmapDescriptor(BitmapDescriptor bitmapDescriptor) { + final List iconConfig = bitmapDescriptor.toJson() as List; + gmaps.Icon? icon; if (iconConfig != null) { @@ -243,17 +254,11 @@ gmaps.MarkerOptions _markerOptionsFromMarker( assert(iconConfig.length >= 2); // iconConfig[2] contains the DPIs of the screen, but that information is // already encoded in the iconConfig[1] - icon = gmaps.Icon() ..url = ui.webOnlyAssetManager.getAssetUrl(iconConfig[1]! as String); - // iconConfig[3] may contain the [width, height] of the image, if passed! - if (iconConfig.length >= 4 && iconConfig[3] != null) { - final List rawIconSize = iconConfig[3]! as List; - final gmaps.Size size = gmaps.Size( - rawIconSize[0] as num?, - rawIconSize[1] as num?, - ); + final gmaps.Size? size = _gmSizeFromIconConfig(iconConfig, 3); + if (size != null) { icon ..size = size ..scaledSize = size; @@ -264,8 +269,26 @@ gmaps.MarkerOptions _markerOptionsFromMarker( // Create a Blob from bytes, but let the browser figure out the encoding final Blob blob = Blob([bytes]); icon = gmaps.Icon()..url = Url.createObjectUrlFromBlob(blob); + + final gmaps.Size? size = _gmSizeFromIconConfig(iconConfig, 2); + if (size != null) { + icon + ..size = size + ..scaledSize = size; + } } } + + return icon; +} + +// Computes the options for a new [gmaps.Marker] from an incoming set of options +// [marker], and the existing marker registered with the map: [currentMarker]. +// Preserves the position from the [currentMarker], if set. +gmaps.MarkerOptions _markerOptionsFromMarker( + Marker marker, + gmaps.Marker? currentMarker, +) { return gmaps.MarkerOptions() ..position = currentMarker?.position ?? gmaps.LatLng( @@ -277,7 +300,7 @@ gmaps.MarkerOptions _markerOptionsFromMarker( ..visible = marker.visible ..opacity = marker.alpha ..draggable = marker.draggable - ..icon = icon; + ..icon = _gmIconFromBitmapDescriptor(marker.icon); // TODO(ditman): Compute anchor properly, otherwise infowindows attach to the wrong spot. // Flat and Rotation are not supported directly on the web. } 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 9670e0f28e2e..34f3a205b052 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/plugins/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.4.0+1 +version: 0.4.0+2 environment: sdk: ">=2.12.0 <3.0.0" @@ -26,6 +26,10 @@ dependencies: sanitize_html: ^2.0.0 stream_transform: ^2.0.0 +dependency_overrides: + google_maps_flutter_platform_interface: + path: ../google_maps_flutter_platform_interface + dev_dependencies: flutter_test: sdk: flutter From c7665d8707181da168d9071f2943d58ab7be14cc Mon Sep 17 00:00:00 2001 From: stuartmorgan Date: Tue, 16 Aug 2022 15:33:26 -0400 Subject: [PATCH 4/5] Replace override with published version --- .../google_maps_flutter_web/pubspec.yaml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) 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 34f3a205b052..731b90547638 100644 --- a/packages/google_maps_flutter/google_maps_flutter_web/pubspec.yaml +++ b/packages/google_maps_flutter/google_maps_flutter_web/pubspec.yaml @@ -22,14 +22,10 @@ dependencies: flutter_web_plugins: sdk: flutter google_maps: ^6.1.0 - google_maps_flutter_platform_interface: ^2.2.0 + google_maps_flutter_platform_interface: ^2.2.2 sanitize_html: ^2.0.0 stream_transform: ^2.0.0 -dependency_overrides: - google_maps_flutter_platform_interface: - path: ../google_maps_flutter_platform_interface - dev_dependencies: flutter_test: sdk: flutter From 558ad92ccd0709f5cb5586e21587d5a93b9ea871 Mon Sep 17 00:00:00 2001 From: stuartmorgan Date: Tue, 16 Aug 2022 15:33:43 -0400 Subject: [PATCH 5/5] Remove override --- .../google_maps_flutter_web/example/pubspec.yaml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/google_maps_flutter/google_maps_flutter_web/example/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter_web/example/pubspec.yaml index 477fd2aee941..82c36e22b15f 100644 --- a/packages/google_maps_flutter/google_maps_flutter_web/example/pubspec.yaml +++ b/packages/google_maps_flutter/google_maps_flutter_web/example/pubspec.yaml @@ -12,10 +12,6 @@ dependencies: google_maps_flutter_web: path: ../ -dependency_overrides: - google_maps_flutter_platform_interface: - path: ../../google_maps_flutter_platform_interface - dev_dependencies: build_runner: ^2.1.1 flutter_driver: